Napisałem instrukcję T-SQL podobną do tej (ta oryginalna wygląda inaczej, ale chcę tutaj podać prosty przykład):
SELECT first_name +
CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person
Ta instrukcja nie zawiera żadnych błędów składniowych, ale klauzula przypadku zawsze wybiera część ELSE - także jeśli ostatnia nazwa jest pusta. Ale dlaczego?
Chcę zjednoczyć imię i nazwisko, ale jeśli nazwisko jest puste, całe imię staje się puste:
SELECT first_name +
CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name
FROM dbo.person
Czy wiesz, gdzie jest problem?
COALESCE
w zasadzie wewnętrznie przekłada się naCASE
. Problem z CASE polega na tym, żelast_name
jest oceniany dwukrotnie i może prowadzić do innych skutków ubocznych - zobacz ten doskonały artykuł . Aby rozwiązać to, o co pytano, wolę iść zISNULL(' '+ last_name, '')
wymienionym w komentarzu poniżej.CZĘŚĆ KIEDY jest porównywana z ==, ale tak naprawdę nie można porównywać z NULL. Próbować
zamiast lub COALESCE:
(„+ last_name to NULL, gdy last_name jest NULL, więc w takim przypadku powinno zwrócić”)
źródło
Istnieje wiele rozwiązań, ale żadne nie wyjaśnia, dlaczego oryginalne oświadczenie nie działa.
Po tym czasie następuje sprawdzenie równości, która powinna być prawdziwa lub fałszywa.
Jeśli jedna lub obie części porównania mają wartość NULL, wynikiem porównania będzie NIEZNANY, co jest traktowane jak fałsz w strukturze przypadku. Widzieć: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/
Aby tego uniknąć, Coalesce jest najlepszym sposobem.
źródło
Biorąc pod uwagę zapytanie, możesz to również zrobić:
źródło
ISNULL(' '+ last_name, '')
aby zapobiec zbędnej przestrzeni.Problem polega na tym, że wartość null nie jest uważana za równą sobie, dlatego klauzula nigdy się nie zgadza.
Należy jawnie sprawdzić wartość null:
źródło
próbować:
To dodaje spację do nazwiska, jeśli jest puste, cała spacja + nazwisko przechodzi do NULL i dostajesz tylko imię, w przeciwnym razie dostaniesz firts + spację + nazwisko.
będzie to działać tak długo, jak ustawione jest domyślne ustawienie konkatenacji z łańcuchami zerowymi:
nie powinno to stanowić problemu, ponieważ
OFF
tryb ten zniknie w przyszłych wersjach SQl Serverźródło
Problem polega na tym, że NULL nie jest uważany za równy niczego, nawet samemu sobie, ale dziwne jest to, że również nie jest równy sobie.
Rozważ następujące instrukcje (które są BTW nielegalne w SQL Server T-SQL, ale są prawidłowe w My-SQL, jednak to właśnie ANSI definiuje jako null, i można je zweryfikować nawet w SQL Server za pomocą instrukcji case itp.)
SELECT NULL = NULL -- Results in NULL
SELECT NULL <> NULL -- Results in NULL
Więc nie ma prawdziwej / fałszywej odpowiedzi na pytanie, zamiast tego odpowiedź jest również pusta.
Ma to wiele implikacji, na przykład w
WHEN NULL
SELECT a + NULL -- Results in NULL
Można nadpisać to zachowanie w SQL Server, określając
SET ANSI_NULLS OFF
, ale NIE jest to zalecane i nie należy tego robić, ponieważ może powodować wiele problemów, po prostu z powodu odchylenia standardu.(Na marginesie, w My-SQL istnieje opcja użycia specjalnego operatora
<=>
do porównania zerowego.)Dla porównania, w ogólnych językach programowania null jest traktowany jako wartość regularna i jest sobie równy, jednak jest to wartość NAN, która również nie jest sobie równa, ale przynajmniej zwraca wartość „fałsz” podczas porównywania go z samym sobą (i podczas sprawdzania, czy nie jest równy, różne języki programowania mają różne implementacje).
Zauważ jednak, że w językach podstawowych (tj. VB itp.) Nie ma słowa kluczowego „null”, a zamiast tego używa się słowa kluczowego „Nic”, którego nie można użyć w bezpośrednim porównaniu, a zamiast tego należy użyć słowa „IS” jak w języku SQL, jednak w rzeczywistości jest on równy sobie (przy użyciu porównań pośrednich).
źródło
źródło
Kiedy czujesz się sfrustrowany, spróbuj:
Spróbuj zamiast tego:
LEN(ISNULL(last_Name,''))
mierzy liczbę znaków w tej kolumnie, która będzie zero, niezależnie od tego, czy jest pusta, czy też NULLWHEN 0 THEN
oceni wartość true i zwróci „” zgodnie z oczekiwaniami.Mam nadzieję, że jest to pomocna alternatywa.
Uwzględniłem ten przypadek testowy dla serwera SQL 2008 i nowszych wersji:
źródło
Jason złapał błąd, więc to działa ...
Czy ktoś może potwierdzić inne wersje platformy?
SQL Server:
MySQL:
Wyrocznia:
źródło
Możesz użyć funkcji IsNull
jeśli jedna kolumna jest pusta, otrzymasz pusty znak
Kompatybilny z Microsoft SQL Server 2008+
źródło
Użyj funkcji CONCAT dostępnej w SQL Server 2012 i nowszych.
źródło
Próbowałem rzutować na łańcuch i testować łańcuch o zerowej długości i zadziałało.
źródło
NULL nic nie równa. Instrukcja case w zasadzie mówi, kiedy wartość = NULL .. nigdy nie zostanie trafiona.
Istnieje również kilka procedur przechowywanych w systemie, które zostały niepoprawnie zapisane w Twojej składni. Zobacz sp_addpullsubscription_agent i sp_who2.
Chciałbym wiedzieć, jak powiadomić Microsoft o tych błędach, ponieważ nie jestem w stanie zmienić proc. Przechowywanych w systemie.
źródło