Announcement

Collapse
No announcement yet.

Hash mit LIKE filtern

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Hash mit LIKE filtern

    Hi,

    Ich habe eine Liste mit E-Mail Adressen, bei denen "ungültige" vorkommen. Lt. RFC sind diese zwar gültig, aber unser System hat in bestimmten Fällen die E-Mails mit einem Hash versehen, um sie bspw. für Dubletten zu "bereinigen".
    Eine Beispiel E-Mail sieht so aus: 0e7628e64e144110a13196d9fa546d72_han...@exampl e.com

    Nun will ich gerne alle E-Mails haben, die nicht dem Muster entsprechen.
    Meine aktuelle Version ist recht lang, sollte für mein Verständnis aber funktionieren:
    Code:
    ... WHERE Email NOT LIKE '[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][_]%@%'
    [0-9a-z] kommt also 32x hintereinander, weil T-SQL für LIKE meines Wissen nach kein [0-9a-z]{32} kennt.

    Wie gesagt, dachte ich, dass die Variante funktionieren würde, aber die Mails tauchen weiterhin in der Liste auf?!
    Gibt es eine andere Möglichkeit mit T-SQL? Im nächsten Step würde ich sonst ein kleines Script schreiben, das über RegEx die entsprechenden Mails rausfiltert, aber das fände ich ehrlich gesagt unnötig.

    Danke
    PHP rocks!
    Eine Initiative der PHP Community

  • #2
    Hallo,

    du kannst dir auch eine UDF für Regex (mittels SQL-CLR) erstellen.

    Code:
    [SqlFunction(Name = "IsMatch", IsDeterministic = true, IsPrecise = true)]
    public static SqlBoolean RegexIsMatch(string input, string pattern)
    {
        if (string.IsNullOrEmpty(input)) return false;
    
        try
        {
            RegexOptions options =
                RegexOptions.IgnoreCase
                | RegexOptions.Multiline
                | RegexOptions.CultureInvariant;
    
            return Regex.IsMatch(input, pattern, options);
        }
        catch (Exception ex)
        {
            SqlContext.Pipe.Send("Error in searching Pattern: " + ex.Message);
            return SqlBoolean.False;
        }
    }
    Diese UDF kann dann in der Where-Clause verwendet werden.

    mfG Gü

    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      Hallo,

      Code:
      declare @tmp table
      (
          Email nvarchar(max)
      )
      
      insert into @tmp values
      ('[email protected]'),
      ('[email protected]'),
      ('[email protected]')
      
      select *
      from   @tmp
      
      select *
      from   @tmp t
      where  t.Email NOT LIKE '[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][_]%@%'
      liefert
      Code:
      ---------------------------------------------------------------------
      [email protected]
      [email protected]
      [email protected]
      
      (3 Zeilen betroffen)
      
      ---------------------------------------------------------------------
      [email protected]
      [email protected]
      
      (2 Zeilen betroffen)
      Schaut doch korrekt aus?

      mfG Gü
      "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

      Comment


      • #4
        Originally posted by Arne Drews View Post
        Wie gesagt, dachte ich, dass die Variante funktionieren würde, aber die Mails tauchen weiterhin in der Liste auf?!
        Tja, also wenn ich die Doku lese, steht da gar nicht, dass LIKE in Kombi mit [] mehr als ein Zeichen verkraftet. Die Menge der möglichen Zeichen ist natürlich größer 1, aber da steht "einzelnes Zeichen" oder sowas für das Ergebnis des Ausdrucks. Ich glaube, das ist einfach eher ungeeignet, kein RegExp und auch keine "normale" Like Operation.
        Ansonsten, hast Du schon mal die Gegenprobe mit ohne NOT gemacht? Kommt das erwartete Ergebnis? Was musst Du alles wegwerfen von der Einschränkung, bis es passt?
        Ist es am Ende nicht so, dass man vom Feldinhalt nur die ersten 32 Byte entfernen muss und den Rest auf Emailpattern testet? Könnte auch schneller sein. Wobei wahrscheinlich der Index dadurch unbrauchbar wird. Aber man kann auch sagen, man muss eh nur prüfen, wenn die Länge > 34 ist, alles kleinere enthält das Muster nicht.

        gfoidl
        Warum muss man eine Funktion daraus machen?
        Gruß, defo

        Comment


        • #5
          Hallo,

          Warum muss man eine Funktion daraus machen?
          Anders geht Regex im SQL Server nicht. Od. hab ich etwas versäumt?

          mfG Gü
          "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

          Comment


          • #6
            Nein, sorry, das ist eine normale Frage meinerseits. Ich nutze aktiv kein MS SQL und habe Deinen Code so interpreditert, dass ich die Kernfunktion:
            Code:
            Regex.IsMatch(input, pattern, options)
            mit der entsprechenden Parametrierung gleich in SQL einsetzen kann.
            Gruß, defo

            Comment


            • #7
              Hi,

              Danke für eure Hinweise.
              Wie in #3 habe ich es getestet, aber dennoch werden mir solche E-Mails mit angezeigt in der Ergebnisliste.

              defo: [0-9] funktioniert bspw. prima, also sollte das funktionieren. Wie gfoidl ja auch in #3 gezeigt hat.
              Warum er mir die dennoch anzeigt kann ich nicht beurteilen. Auf Steuerzeichen habe ich auch schon mal explizit geprüft, sind keine drin.

              Ich habe mir erstmal so beholfen:
              Code:
              WHERE not (
                          CHARINDEX('_', a.EMail) = 33
                          and
                          CHARINDEX('@', a.EMail) > 33
                      )
              Ist auch nicht die sicherste Variante, aber die Ergebnisse sehen bisher sehr gut aus.
              PHP rocks!
              Eine Initiative der PHP Community

              Comment

              Working...
              X