Пустые строки: почему или когда "равно"?

17

Кто может объяснить, почему

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

доходность

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

Забавным следствием этого является то, что в

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

обновление действительно заменит пустую строку на пустую, но предложение where остается верным, и повторные выполнения оператора update сообщают

(1 row(s) affected)
bernd_k
источник

Ответы:

22

Завершающие пробелы объяснили :

SQL Server следует спецификации ANSI / ISO SQL-92 (Раздел 8.2, Общие правила № 3), как сравнивать строки с пробелами. Стандарт ANSI требует заполнения для строк символов, используемых в сравнениях, чтобы их длина соответствовала перед сравнением. Заполнение напрямую влияет на семантику предикатов предложения WHERE и HAVING и другие сравнения строк Transact-SQL. Например, Transact-SQL считает строки 'abc' и 'abc' эквивалентными для большинства операций сравнения.

Единственным исключением из этого правила является предикат LIKE. Когда правая часть выражения предиката LIKE содержит значение с завершающим пробелом, SQL Server не дополняет два значения одинаковой длиной до того, как произойдет сравнение. Поскольку цель предиката LIKE по определению состоит в том, чтобы облегчить поиск по шаблону, а не в простых тестах на равенство строк, это не нарушает раздел спецификации ANSI SQL-92, упомянутый ранее.

Вот хорошо известный пример всех случаев, упомянутых выше:

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

Вот еще некоторые подробности о конечных пробелах и LIKEпредложении .

Олег Док
источник