SQL Server konkatenacja ciągów znaków z wartością Null

85

Tworzę kolumnę obliczoną dla pól, z których niektóre są potencjalnie zerowe.

Problem polega na tym, że jeśli którekolwiek z tych pól jest puste, cała obliczona kolumna będzie zerowa. Z dokumentacji firmy Microsoft rozumiem, że jest to oczekiwane i można je wyłączyć za pomocą ustawienia SET CONCAT_NULL_YIELDS_NULL. Jednak nie chcę zmieniać tego domyślnego zachowania, ponieważ nie znam jego wpływu na inne części SQL Server.

Czy istnieje sposób, aby po prostu sprawdzić, czy kolumna ma wartość null, i dołączyć jej zawartość do obliczonej formuły kolumny tylko wtedy, gdy nie jest pusta?

Alex
źródło
2
Zaakceptowana odpowiedź była poprawna w momencie zadawania pytania, ale dla wszystkich na SQL Server 2012 i późniejszych (i na tym etapie powinni być wszyscy) Odpowiedź @ Martin-Smiths jest najlepsza, ponieważ automatycznie obsługuje wartości null.
Dowlers

Odpowiedzi:

142

Możesz użyć ISNULL(....)

SET @Concatenated = ISNULL(@Column1, '') + ISNULL(@Column2, '')

Jeśli wartość kolumny / wyrażenia rzeczywiście wynosi NULL, wówczas zostanie użyta druga określona wartość (tutaj: pusty ciąg).

marc_s
źródło
22
„Coalesce” to nazwa funkcji zgodna ze standardem ANSI, ale ISNULL jest łatwiejsza do przeliterowania.
Philip Kelley
1
ISNULL wydaje się być również odrobinę szybszy na SQL Server - więc jeśli chcesz go użyć w funkcji, która łączy ciągi znaków w obliczoną kolumnę, możesz zrezygnować ze standardu ANSI i zdecydować się na szybkość (patrz Adam Machanic: sqlblog.com / blogs / adam_machanic / archive / 2006/07/12 /… )
marc_s
Właśnie użyłem tego zapytania Isnull (,), bardzo mi to pomogło, ponieważ łączyłem wartości ze sobą, a jeśli jedna z nich była pusta, wszystko również stawało się puste.
Sizons
Używanie ISNULL()jest dobrym rozwiązaniem, ale począwszy od SQL Server 2012, możesz również użyć CONCATfunkcji, aby uzyskać ten sam wynik:CONCAT(@Column1, @Column2)
Muhammad Musavi
2
Warto tu zauważyć, że jeśli chcesz, aby zamienić nullna coś innego niż pusty ciąg, czyli IsNull(@Column1, 'NULLVALUE')z IsNulldługością wymiana ciąg jest ograniczony do długości kolumny to zastępującego, a nie zCoalesce
Jamie
58

Od SQL Server 2012 jest to znacznie łatwiejsze dzięki tej CONCATfunkcji.

Traktuje NULLjako pusty ciąg

DECLARE @Column1 VARCHAR(50) = 'Foo',
        @Column2 VARCHAR(50) = NULL,
        @Column3 VARCHAR(50) = 'Bar';


SELECT CONCAT(@Column1,@Column2,@Column3); /*Returns FooBar*/
Martin Smith
źródło
Dzięki! To było to, czego potrzebowałem !!
Shiva,
W przypadku starszych wersji otrzymujesz „CONCAT” nie jest rozpoznawalną nazwą funkcji wbudowanej ”, więc użyj COALESCE
Savage
3
@Savage - COALESCE nie działa, ponieważ nie łączy się, po prostu zwraca pierwszy argument inny niż null
codeulike
30

Użyj COALESCE . Zamiast your_columnużywać COALESCE(your_column, ''). To zwróci pusty ciąg zamiast NULL.

Mark Byers
źródło
OP chce połączyć struny razem, COALESCE tego nie zrobi
codeulike
12

Posługiwać się

SET CONCAT_NULL_YIELDS_NULL  OFF 

a konkatenacja wartości null do łańcucha nie spowoduje null.

Pamiętaj, że jest to przestarzała opcja, unikaj używania. Więcej informacji można znaleźć w dokumentacji .

Simran
źródło
11

Możesz także użyć CASE - mój poniższy kod sprawdza zarówno wartości null, jak i puste ciągi i dodaje separator tylko wtedy, gdy istnieje wartość do naśladowania:

SELECT OrganisationName, 
'Address' = 
CASE WHEN Addr1 IS NULL OR Addr1 = '' THEN '' ELSE Addr1 END + 
CASE WHEN Addr2 IS NULL OR Addr2 = '' THEN '' ELSE ', ' + Addr2 END + 
CASE WHEN Addr3 IS NULL OR Addr3 = '' THEN '' ELSE ', ' + Addr3 END + 
CASE WHEN County IS NULL OR County = '' THEN '' ELSE ', ' + County END 
FROM Organisations 
Eddie
źródło
8

Chciałem się tylko przyczynić, gdyby ktoś szukał pomocy przy dodawaniu separatorów między ciągami, w zależności od tego, czy pole ma wartość NULL, czy nie.

A więc w przykładzie tworzenia adresu jednowierszowego z oddzielnych pól

Address1 , Address2 , Address3 , miasto , kod pocztowy

w moim przypadku mam następującą kolumnę obliczeniową, która wydaje się działać tak, jak chcę:

case 
    when [Address1] IS NOT NULL 
    then (((          [Address1]      + 
          isnull(', '+[Address2],'')) +
          isnull(', '+[Address3],'')) +
          isnull(', '+[City]    ,'')) +
          isnull(', '+[PostCode],'')  
end

Mam nadzieję, że to komuś pomoże!

ebooyens
źródło
Jest tam sporo zbędnych zagnieżdżonych nawiasów, które można by usunąć. Inną wskazówką jest to, że możesz również usunąć instrukcję case, tak jakby address1 była pusta, całe wyrażenie zostanie ocenione na null (chociaż posiadanie instrukcji case zwraca uwagę, że może się to zdarzyć)
Alternator,
7

ISNULL(ColumnName, '')

Ian Jacobs
źródło
1

Ja też miałem z tym duży problem. Nie udało się go uruchomić, korzystając z powyższych przykładów przypadków, ale to działa dla mnie:

Replace(rtrim(ltrim(ISNULL(Flat_no, '') + 
' ' + ISNULL(House_no, '') + 
' ' + ISNULL(Street, '') + 
' ' + ISNULL(Town, '') + 
' ' + ISNULL(City, ''))),'  ',' ')

Zastąp poprawia podwójne spacje spowodowane łączeniem pojedynczych spacji bez niczego między nimi. r / ltrim usuwa spacje na końcach.

BryDav
źródło
0

Na serwerze Sql:

insert into Table_Name(PersonName,PersonEmail) values(NULL,'[email protected]')

PersonName is varchar(50), NULL is not a string, because we are not passing with in single codes, so it treat as NULL.

Kod za:

string name = (txtName.Text=="")? NULL : "'"+ txtName.Text +"'";
string email = txtEmail.Text;

insert into Table_Name(PersonName,PersonEmail) values(name,'"+email+"')
Srinivasula Reddy
źródło
0

Ten przykład pomoże ci obsługiwać różne typy podczas tworzenia instrukcji wstawiania

select 
'insert into doc(Id, CDate, Str, Code, Price, Tag )' + 
'values(' +
      '''' + convert(nvarchar(50), Id) + ''',' -- uniqueidentifier
    + '''' + LEFT(CONVERT(VARCHAR, CDate, 120), 10) + ''',' -- date
    + '''' + Str+ ''',' -- string
    + '''' + convert(nvarchar(50), Code)  + ''',' -- int
    + convert(nvarchar(50), Price) + ',' -- decimal
    + '''' + ISNULL(Tag, '''''') + '''' + ')'  -- nullable string

 from doc
 where CDate> '2019-01-01 00:00:00.000'
Akmal Salikhov
źródło