Я написал инструкцию T-SQL, похожую на эту (оригинал выглядит иначе, но я хочу привести простой пример):
SELECT first_name +
CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person
В этом операторе нет синтаксических ошибок, но предложение case всегда выбирает ELSE-часть - также, если last_name равно null. Но почему?
То, что я хочу сделать, это объединить first_name и last_name, но если last_name равно null, все имя становится пустым:
SELECT first_name +
CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name
FROM dbo.person
Вы знаете, где проблема?
COALESCE
в основном внутренне переводится наCASE
. Проблема с CASE заключается в том, чтоlast_name
она оценивается дважды, и это может привести к другим побочным эффектам - см. Эту прекрасную статью . Чтобы решить, что спросили, я бы предпочелISNULL(' '+ last_name, '')
упомянуть в комментарии ниже.Часть WHEN сравнивается с ==, но вы не можете сравнить с NULL. Пытаться
вместо этого или COALESCE:
('+ last_name имеет значение NULL, когда last_name равно NULL, поэтому в этом случае должно возвращаться' ')
источник
Есть много решений, но ни одно не объясняет, почему оригинальное утверждение не работает.
После когда происходит проверка на равенство, которая должна быть истинной или ложной.
Если одна или обе части сравнения имеют значение NULL, результатом сравнения будет UNKNOWN, что рассматривается как ложь в структуре дела. См .: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/
Чтобы избежать этого, Coalesce - лучший способ.
источник
По вашему запросу вы также можете сделать это:
источник
ISNULL(' '+ last_name, '')
чтобы предотвратить избыточное пространство.Проблема в том, что нуль не считается равным самому себе, поэтому предложение никогда не совпадает.
Вам нужно явно проверить на ноль:
источник
пытаться:
Это добавляет пробел к фамилии, если она пуста, весь пробел + фамилия переходят в NULL, и вы получаете только имя, в противном случае вы получаете первые + пробел + фамилию.
это будет работать до тех пор, пока задано значение по умолчанию для объединения с пустыми строками:
это не должно вызывать беспокойства, поскольку
OFF
в следующих версиях SQl Server этот режим исчезнетисточник
Проблема в том, что NULL не считается равным чему-либо, даже не самому себе, но странная часть заключается в том, что он также не равен самому себе.
Рассмотрим следующие операторы (что, кстати, недопустимо в T-SQL для SQL Server, но допустимо в My-SQL, однако это то, что ANSI определяет для нуля, и может быть проверено даже в SQL Server с помощью операторов case и т. Д.)
SELECT NULL = NULL -- Results in NULL
SELECT NULL <> NULL -- Results in NULL
Таким образом, нет истинного / ложного ответа на вопрос, вместо этого ответ также является нулевым.
Это имеет много последствий, например, в
WHEN NULL
SELECT a + NULL -- Results in NULL
Можно изменить это поведение в SQL Server, указав
SET ANSI_NULLS OFF
, однако это НЕ рекомендуется и не должно быть сделано, так как это может вызвать много проблем, просто из-за отклонения от стандарта.(Как примечание, в My-SQL есть возможность использовать специальный оператор
<=>
для нулевого сравнения.)Для сравнения, в общих языках программирования ноль рассматривается как обычное значение и равен самому себе, однако это значение NAN, которое также не равно самому себе, но, по крайней мере, возвращает «ложь» при сравнении его с собой, (и при проверке на не равные разные языки программирования имеют разные реализации).
Тем не менее, обратите внимание, что в базовых языках (то есть VB и т. Д.) Нет ключевого слова «null», и вместо этого используется ключевое слово «Nothing», которое нельзя использовать при прямом сравнении, а вместо этого нужно использовать «IS», как в SQL, однако он фактически равен самому себе (при использовании косвенных сравнений).
источник
источник
Когда вы расстроены, пытаясь это:
Попробуйте это вместо этого:
LEN(ISNULL(last_Name,''))
измеряет количество символов в этом столбце, которое будет равно нулю, независимо от того, пусто оно или NULL, поэтомуWHEN 0 THEN
будет иметь значение true и возвращать '', как и ожидалось.Я надеюсь, что это полезная альтернатива.
Я включил этот тест для SQL Server 2008 и выше:
источник
Джейсон поймал ошибку, так что это работает ...
Кто-нибудь может подтвердить другие версии платформы?
SQL Server:
MySQL:
Oracle:
источник
Вы можете использовать функцию IsNull
если один столбец равен нулю, вы получите пустой символ
Совместим с Microsoft SQL Server 2008+
источник
Используйте функцию CONCAT, доступную в SQL Server 2012 и более поздних версиях.
источник
Я попытался привести к строке и проверить строку нулевой длины, и это сработало.
источник
NULL не равняется ничему. Оператор case в основном говорит, что когда значение = NULL .. оно никогда не попадет.
Есть также несколько системных хранимых процедур, которые написаны неправильно с вашим синтаксисом. Смотрите sp_addpullsubscription_agent и sp_who2.
Хотел бы я знать, как уведомить Microsoft об этих ошибках, так как я не могу изменить системные хранимые процессы.
источник