none
Escapen von Sonderzeichen RRS feed

  • Frage

  • Hallo zusammen,

    ich verwende ADO.NET und den Typ SqlParameter, für die Übergabe von Werten in die Where-Bedingung.

    Wird nach einem Begriff mit einem Sonderzeichen gesucht, z.B. nach einer eMail mit einem Unterstrich (first1_last1@test.de), müsste dafür gesorgt werden, dass dieser escaped wird.

    Ist meine Annahme korrekt, dass dies nicht explizit notwendig ist, wenn der Wert (first1_last1@test.de) in das SqlCommand durch einen SqlParameter übergeben wird?

    Meine Vermutung ist, dass ADO.NET für SqlServer so programmiert ist, dass es solche Fälle bereits berücksichtigt.

    Ist diese Annahme korrekt?

    Viele Grüße,
    Christian

    Mittwoch, 26. Oktober 2016 15:53

Antworten

  • Hallo Christian,

    die Value Property deines SqlParameters ist falsch.

    first1!_last1@test.de% ESCAPE '!'

    resultiert letztendlich in folgender WHERE Klausel:

    ...
    WHERE Spaltenname LIKE 'first1!_last1@test.de% ESCAPE ''!'''

    Es wird also explizit nach dem Inhalt:

    first1!_last1@test.de% ESCAPE '!'

    gesucht. Sprich, nach deiner Emailadresse müsste im Spaltenwert noch " ESCAPE '!'" vorkommen, was natürlich nicht der Fall ist.

    Du musst ESCAPE '!' aus dem Parameterwert rausholen und in den CommandText schreiben.

    <SqlCommand>.CommandText = "SELECT id FROM MyTable WHERE mail LIKE @mail_1 ESCAPE '!'"

    Und im Wert des Parameters darf dann eben nur:

    first1!_last1@test.de%

    stehen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Donnerstag, 27. Oktober 2016 16:26
    Moderator

Alle Antworten

  • Hallo Christian,

    Ich wüsste nicht, das ADO.NET oder andere Datenprovider da klammheimlich im Hintergrund etwas abändert.

    Das escapen von Zeichen musst Du selbst vornehmen, wobei es eh nur zum Tragen kommt, wenn Du den LIKE Operator verwendest; bei = ist sind Wildcard-Zecihen eh egal.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 26. Oktober 2016 16:07
  • Hallo Christian,

    Kurz: Ja, ADO.NET ist richtig programmiert.

    Lang: Du suchst Probleme, wo es keine gibt.

    @ wird als Präfix nur bei Variablennamen verwendet. Innerhalb einer Zeichenfolge hat es keinerlei besondere Bedeutung. (Selbst wenn es eine Variable gleichen Namens geben würde.)

    Bei einem SqlParameter, der eine Zeichenfolge übergibt (wie SqlDbType.NVarChar), wird die übergebene Zeichenfolge in Anführungszeichen gesetzt und ggf. dort enthaltene Anführungszeichen verdoppelt. Für Unicode Daten wird das Präfix "N" vorangestellt.

    Wobei letzteres eine abstrakte Darstellung ist, intern wird das TDS Protokoll verwendet.

    Gruß Elmar


    Mittwoch, 26. Oktober 2016 16:29
    Beantworter
  • Hallo,

    ich vermute, der OP meint die Suche nach _, was in einer LIKE Abfrage ja einem einzelnen beliebigen Zeichen entspricht.

    Spalte LIKE 'first1_last1@test.de'

    würde daher ja auch first1Xlast1@test.de finden.

    @OP: In deinem Fall müsstest Du das so umwandeln:

    Spalte LIKE 'first1[_]last1@test.de'

    wobei Du dann auch gleich mit einem normalen Stringvergleich arbeiten kannst

    Spalte = 'first1_last1@test.de'

    und dabei dann keine Probleme mit dem Unterstrich, Prozentzeichen, usw. hast.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Mittwoch, 26. Oktober 2016 17:40
    Moderator
  • Hallo Stefan,

    da dürftest Du Recht haben - ich hab den "_" schlicht und einfach übersehen.

    @Christian: In der Verwendung als Platzhalter bei den Befehlen, die sie unterstützen (LIKE ,PATINDEX) müssen sie dann tatsächlich manuell maskiert werden, siehe z. B.: LIKE, da eine Analyse der SQL Anweisung von keinem Treiber vorgenommen wird.

    Gruß Elmar

    Mittwoch, 26. Oktober 2016 17:49
    Beantworter
  • Hallo zusammen.

    Ein herzliches Dankeschön an euch alle :-)

    In dem betroffenen Programmcode wird aktuell aus first1_last1@test.de der Wert first1!_last1@test.de ESCAPE '!'% generiert. 

    Diese Wandlung wird vorgenommen für diese Sonderzeichen:

    var _likeWildcards = new List<string>{"%", "_", "[", "]", "^"};

    Ist es korrekt, wenn ich dafür sorge, dass alle _likeWildCards wie folgt maskiert werden?

    1. % => [%]
    2. _ => [_]
    3. [ => [[]
    4. ] => []]
    5. ^ => [^]

    Viele Grüße,
    Christian

    Donnerstag, 27. Oktober 2016 07:31
  • Hallo Christian,

    Der generierte Programmcode ist korrekt und ich würde bei LIKE dabei bleiben und das ESCAPE Zeichen (im Ausdruck "%") nutzen. Denn eine Maskierung mit "[]" hat u. U. Seiteneffekte, wie bei [^], das gleichzeitig ein Platzhalter ist:

    CREATE TABLE Tabelle(Spalte varchar(40));
    INSERT INTO Tabelle(Spalte) VALUES ('abc'), ('[abc]'), ('\abc'), ('^abc');
    GO
    
    -- nur ^abc
    SELECT Spalte FROM Tabelle WHERE Spalte LIKE '\^%' ESCAPE '\'; 
    -- alle ausser ^abc
    SELECT Spalte FROM Tabelle WHERE Spalte LIKE '[^\^]%' ESCAPE '\'; 
    
    -- alle
    SELECT Spalte FROM Tabelle WHERE Spalte LIKE '[^]%'; 
    -- alle
    SELECT Spalte FROM Tabelle WHERE Spalte LIKE '[^^]%'; 
    -- keine
    SELECT Spalte FROM Tabelle WHERE Spalte LIKE '[^[^]]%'; 
    

    Verwendet ihr auch PATINDEX sieht es anders aus, da gibt es leider kein ESCAPE.

    Gruß Elmar

    Donnerstag, 27. Oktober 2016 08:05
    Beantworter
  • Hallo Elmar,

    wenn ich im SSM eine Abfrage mit folgender Bedingung absetze, erhalte ich keinen Treffer:

    where mail like  'first1!_last1@test.de ESCAPE ''!''%'

    Diese Filterbedingung liefert einen Treffer:

    where mail like 'first1[_]last1@test.de'

    In der Tabelle steht 

    first1_last1@test.de

    Wo ist denn bitte der Fehler bei der ersten Bedingung?

    Viele Grüße,
    Christian

    Donnerstag, 27. Oktober 2016 10:35
  • Hallo Christian,

    bei der ersten sind Anführungszeichen enthalten - wobei ich nicht weiß, ob sie aus dem Kopieren von Code resultieren.

    ESCAPE ist ein Schlüsselwort und muss außerhalb der Zeichenkette stehen und von einer Zeichenkette mit einem Zeichen gefolgt sein:

    Funktionieren täte die "korrekte" Variante:

    LIKE 'first1!_last1@test.de' ESCAPE '!'

    Gruß Elmar

    Donnerstag, 27. Oktober 2016 15:13
    Beantworter
  • Hallo Elmar,

    muss der % eigentlich zwingend vor dem ESCAPE erscheinen?

    LIKE 'first1!_last1@test.de%' ESCAPE '!'

    Ist nachstehender Ausdruck falsch?

    LIKE 'first1!_last1@test.de' ESCAPE '!'%
    Grüße,
    Christian

    Donnerstag, 27. Oktober 2016 15:50
  • Hallo Christian,

    ja, der Ausdruck ist falsch. Das Prozentzeichen soll ja, wenn Du LIKE verwendest, angeben, dass nach der Zeichenfolge x beliebige Zeichen folgen dürfen.

    Du hättest das aber relativ schnell auch selbst gemerkt, wenn Du diese WHERE Klausel mal im SSMS probier hättest. Das kommt dann

    Falsche Syntax in der Nähe von '%'.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 27. Oktober 2016 15:53
    Moderator
  • Hallo Stefan,

    ich nutze die SqlParameter. Dessen Value Property zeigt mir diesen Wert:

    first1!_last1@test.de% ESCAPE '!'

    Er trägt den ParameterName '@mail_1'

    Der erstellte CommandText:

    SELECT id FROM MyTable WHERE  mail LIKE @mail_1

    Warum findet er nichts?

    Viele Grüße,
    Christian


    Donnerstag, 27. Oktober 2016 16:07
  • Hallo Christian,

    die Value Property deines SqlParameters ist falsch.

    first1!_last1@test.de% ESCAPE '!'

    resultiert letztendlich in folgender WHERE Klausel:

    ...
    WHERE Spaltenname LIKE 'first1!_last1@test.de% ESCAPE ''!'''

    Es wird also explizit nach dem Inhalt:

    first1!_last1@test.de% ESCAPE '!'

    gesucht. Sprich, nach deiner Emailadresse müsste im Spaltenwert noch " ESCAPE '!'" vorkommen, was natürlich nicht der Fall ist.

    Du musst ESCAPE '!' aus dem Parameterwert rausholen und in den CommandText schreiben.

    <SqlCommand>.CommandText = "SELECT id FROM MyTable WHERE mail LIKE @mail_1 ESCAPE '!'"

    Und im Wert des Parameters darf dann eben nur:

    first1!_last1@test.de%

    stehen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Donnerstag, 27. Oktober 2016 16:26
    Moderator
  • Hallo,

    herzlichen Dank für die tolle Hilfe!!

    Viele Grüße,
    Christian

    Montag, 31. Oktober 2016 12:03