Puste ciągi: dlaczego lub kiedy „równa się”?

17

Kto może wyjaśnić, dlaczego

select case when '' = ' ' then 1 else 0 end, LEN(''), LEN(' '), DATALENGTH(''), DATALENGTH(' ');

plony

----------- ----------- ----------- ----------- -----------
1           0           0           0           1

Zabawną tego konsekwencją jest to, że w

create table test ( val varchar(10) );
insert into test values( '' );
update test set val = ' ' where val = '';

aktualizacja rzeczywiście zastąpi pusty ciąg pustym, ale klauzula where pozostaje prawdą, a powtarzające się wykonanie instrukcji aktualizacji informuje

(1 row(s) affected)
bernd_k
źródło

Odpowiedzi:

22

Wyjaśnienie spacji końcowych :

SQL Server postępuje zgodnie ze specyfikacją ANSI / ISO SQL-92 (Rozdział 8.2, Ogólne zasady nr 3) w zakresie porównywania ciągów ze spacjami. Norma ANSI wymaga uzupełnienia ciągów znaków używanych w porównaniach, aby ich długości pasowały przed porównaniem. Wypełnienie wpływa bezpośrednio na semantykę predykatów klauzul WHERE i HAVING oraz innych porównań ciągów Transact-SQL. Na przykład Transact-SQL uważa, że ​​ciągi „abc” i „abc” są równoważne dla większości operacji porównania.

Jedynym wyjątkiem od tej reguły jest predykat LIKE. Gdy prawa strona wyrażenia predykcyjnego LIKE zawiera wartość ze spacją końcową, SQL Server nie uzupełnia dwóch wartości do tej samej długości przed dokonaniem porównania. Ponieważ predykat LIKE z definicji ma ułatwić wyszukiwanie wzorców, a nie proste testy równości ciągów, nie narusza to wspomnianej wcześniej sekcji specyfikacji ANSI SQL-92.

Oto dobrze znany przykład wszystkich wyżej wymienionych przypadków:

DECLARE @a VARCHAR(10)
DECLARE @b varchar(10)

SET @a = '1'
SET @b = '1 ' --with trailing blank

SELECT 1
WHERE 
    @a = @b 
AND @a NOT LIKE @b
AND @b LIKE @a

Oto więcej szczegółów na temat spacji końcowych i LIKEklauzuli .

Oleg Dok
źródło