SQL Server Auto-Trim von Varchar-Wert im gleichen Vergleich, aber nicht wie Vergleich

13

Ich bin heute auf ein interessantes Verhalten in SQL Server gestoßen (beobachtet in den Jahren 2005 und 2012), von dem ich gehofft hatte, dass es jemand erklären könnte.

Bei einer Abfrage, die einen Vergleich mit =einem NVARCHAR-Feld durchführte, wurde das Leerzeichen in der Zeichenfolge ignoriert (oder der Wert vor dem Vergleich automatisch abgeschnitten), bei derselben Abfrage mit dem likeOperator wurde das Leerzeichen jedoch nicht ignoriert. Die verwendete Kollatierung ist Latin1_General_CI_AS im Jahr 2012.

Betrachten Sie diese SQL-Geige: http://sqlfiddle.com/#!6/72262/4

Beachten Sie, dass der likeOperator kein Ergebnis für die nachfolgende Leerzeichenfolge zurückgibt, der =Operator jedoch. Warum ist das?

Bonuspunkte: Ich kann dies nicht auf ein VARCHAR-Feld replizieren. Ich hätte gedacht, dass ein Leerzeichen in beiden Datentypen auf die gleiche Weise behandelt wird. Stimmt das?

WT_W
quelle
Ich wollte eine Prüfbedingung schreiben, dass eine Zeichenfolge gekürzt wurde. Ich habe eine Problemumgehung gefunden, die darin besteht, dies zu überprüfen, MyString+'x' = ltrim(rtrim(MyString))+'x'wie in diesem Blog vorgeschlagen
default.kramer

Antworten:

15

Meine erste Antwort deutete darauf hin, dass das auf OFF gesetzte ANSI_PADDING-Flag möglicherweise die Ursache für den Unterschied im Verhalten ist. Dies ist jedoch falsch. Dieses Flag wirkt sich nur auf die Speicherung aus, nicht jedoch auf den Gleichheitsvergleich.

Der Unterschied ergibt sich aus der Implementierung des SQL-Standards durch Microsoft . Der Standard besagt, dass bei der Prüfung auf Gleichheit beide Zeichenfolgen links und rechts vom Gleichheitsoperator aufgefüllt werden müssen, um dieselbe Länge zu haben . Dies erklärt die folgenden Ergebnisse:

insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space    ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace    ' --returns 1

Der LIKE-Operator füllt seine Operanden nicht auf. Es verhält sich auch anders für VARCHARund NVARCHARSpaltentypen :

-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space    ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace    ' -- returns 0

Das Verhalten des LIKE-Operators für den ASCII-Typ ist SQL Server-spezifisch. Für den Unicode-Typ ist es ANSI-kompatibel.

Ralf
quelle
4

SQL wurde in einer Ära geboren, in der die meisten Datenverarbeitungssprachen feste Längen für jedes Feld / jede Variable verwendeten. Das automatische Auffüllen von Textfeldern mit zusätzlichen Leerzeichen war ebenfalls Teil dieses Bildes. Um diesem Verhalten Rechnung zu tragen, wurde der ursprüngliche SQL-CHAR-Typ explizit für den Operator '=' definiert, um nachgestellte Leerzeichen zu ignorieren. (Wenn Sie das seltsam finden, zeigen Sie mir einen überzeugenden Fall, in dem nachgestellte Leerzeichen, die an einen Text angehängt sind, eine echte geschäftliche Bedeutung haben .)

SQL CHAR-Typen haben sich seitdem in alle Richtungen entwickelt, aber es ist nicht unvorstellbar, dass bestimmte modernere Datentypen noch einige Merkmale von ihren historischen Vorgängern geerbt haben.

Erwin Smout
quelle
"Zeigen Sie mir einen überzeugenden Fall, in dem nachgestellte Leerzeichen, die an einen Text angehängt werden, eine echte geschäftliche Bedeutung haben."
Dai
1

In der Dokumentation zu LIKE (Transact-SQL) schreibt Microsoft (Hervorhebung von mir):

Pattern Matching mit LIKE

LIKE unterstützt den ASCII-Mustervergleich und den Unicode-Mustervergleich. Wenn alle Argumente ... ASCII-Zeichendatentypen sind, wird ein ASCII-Musterabgleich durchgeführt. Wenn eines der Argumente vom Unicode-Datentyp ist, werden alle Argumente in Unicode konvertiert und ein Unicode-Musterabgleich durchgeführt. Wenn Sie Unicode-Daten ... mit LIKE verwenden, sind nachgestellte Leerzeichen von Bedeutung. Für Nicht-Unicode-Daten sind nachgestellte Leerzeichen jedoch nicht von Bedeutung. Unicode LIKE ist mit dem ISO-Standard kompatibel. ASCII LIKE ist mit früheren Versionen von SQL Server kompatibel.

Michel de Ruiter
quelle