2010-07-13 14 views
168

Tôi đã viết một Bản Tuyên Bố T-SQL tương tự như thế này (bản gốc trông khác nhau nhưng tôi muốn đưa ra một ví dụ đơn giản ở đây):T-SQL khoản HỒ SƠ: Làm thế nào để xác định KHI NULL

SELECT first_name + 
    CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name 
FROM dbo.person 

Bản Tuyên Bố này không có bất kỳ lỗi cú pháp nào nhưng mệnh đề trường hợp luôn chọn phần ELSE - cũng như nếu last_name là null. Nhưng tại sao?

Những gì tôi muốn làm là để đoàn kết first_name và last_name, nhưng nếu last_name là null toàn bộ tên trở nên rỗng:

SELECT first_name + 
    CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name 
FROM dbo.person 

Bạn có biết nơi mà vấn đề là gì?

Trả lời

292
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END 
+2

@ đề xuất COALESCE của Luther tốt hơn câu trả lời của tôi. Đó là hiệu quả ít hơn, nhưng thanh lịch hơn nhiều. –

+0

Xử lý nó với một cái gì đó như thế này có thể được sử dụng, hoặc một cái gì đó giống như: COALESCE (last_name, '') Tuyên bố trường hợp, trong khi ngắn gọn, là ít bảo trì hơn COALESCE trong truy vấn lớn. Cuối cùng, bạn có kết quả tương tự. Nếu bạn cần tối ưu hóa, kiểm tra các kế hoạch thực hiện nhưng tôi đã không nhận thấy nhiều sự khác biệt. –

+0

'COALESCE' về cơ bản được dịch nội bộ thành' CASE'. Vấn đề với CASE là 'last_name' được đánh giá hai lần và nó có thể dẫn đến các tác dụng phụ khác - xem [article] tuyệt vời này (http://sqlmag.com/t-sql/coalesce-vs-isnull). Để giải quyết những gì đã được hỏi, tôi thà đi với 'ISNULL ('' + last_name, '')' được đề cập trong [bình luận] (http://stackoverflow.com/questions/3237646/t-sql-case-clause-how -to-specify-when-null # comment3343348_3237704) bên dưới. – miroxlav

31

Phần WHEN được so sánh với ==, nhưng bạn không thể so sánh với NULL. Hãy thử

CASE WHEN last_name is NULL THEN ... ELSE .. END 

thay hoặc liên hiệp:

COALESCE(' '+last_name,'') 

(' '+ last_name là NULL khi last_name là NULL, vì vậy nó phải trả lại '' trong trường hợp đó)

+0

Ok cảm ơn bạn đã thông tin với phần == trong phần WHEN. Tôi không biết điều đó. Với COALESCE nó cũng hoạt động tốt. Đã không nghĩ rằng có rất nhiều khả năng để làm điều đó. – meni

11

Với truy vấn của bạn, bạn có thể cũng làm điều này:

SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person 
+2

Điều này cho biết thêm một không gian dư thừa khi last_name là null, đó là những gì OP đã cố gắng để tránh. –

+5

Sử dụng tốt hơn 'ISNULL ('' + last_name, '')' để ngăn không gian dư thừa. – Prutswonder

+0

Vâng nhận ra nó sau khi tôi đăng. Tôi nghĩ rằng nó sẽ rời khỏi nó vì nó giải quyết được phần mà anh ta gặp phải. –

7

Vấn đề là null không được coi là bằng chính nó, do đó mệnh đề không bao giờ khớp es.

Bạn cần phải kiểm tra cho null rõ ràng:

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name 
4

thử:

SELECT first_name + ISNULL(' '+last_name, '') AS Name FROM dbo.person 

này cho biết thêm không gian để tên cuối cùng, nếu nó là null, không gian toàn bộ + tên cuối cùng đi vào NULL và bạn chỉ nhận được một tên đầu tiên, nếu không bạn sẽ nhận được một firts + dấu cách + họ.

này sẽ làm việc miễn là các thiết lập mặc định cho nối với chuỗi null được thiết lập:

SET CONCAT_NULL_YIELDS_NULL ON 

này không phải là một mối quan tâm kể từ khi chế độ OFF được đi xa trong các phiên bản tương lai của SQL Server

6

Có rất nhiều giải pháp nhưng không có giải pháp nào giải thích tại sao câu lệnh gốc không hoạt động.

CASE last_name WHEN null THEN '' ELSE ' '+last_name 

Sau khi có, kiểm tra sự bình đẳng, đúng hay sai.

Nếu một hoặc cả hai phần của so sánh là null, kết quả của so sánh sẽ là KHÔNG XỬ LÝ, được coi là sai trong cấu trúc chữ hoa chữ thường. Xem: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

Để tránh điều này, Coalesce là cách tốt nhất.

1
CASE 
    WHEN last_name IS null THEN '' 
    ELSE ' ' + last_name 
END 
+4

Er ... hoàn toàn giống với câu trả lời được chấp nhận. –

0

Khi bạn nhận được thất vọng cố gắng này:

CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END 

Hãy thử này thay vì:

CASE LEN(ISNULL(last_Name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name 
END AS newlastName 

LEN(ISNULL(last_Name,'')) biện pháp số ký tự trong cột đó, sẽ được số không trống rỗng, hoặc NULL, do đó WHEN 0 THEN sẽ đánh giá e thành true và trả về '' như mong đợi.

Tôi hy vọng đây là giải pháp thay thế hữu ích.

Tôi đã bao gồm trường hợp thử nghiệm này cho sql server 2008 trở lên:

DECLARE @last_Name varchar(50) = NULL 

SELECT 
CASE LEN(ISNULL(@last_Name,'')) 
WHEN 0 THEN '' 
ELSE 'A ' + @last_name 
END AS newlastName 

SET @last_Name = 'LastName' 

SELECT 
CASE LEN(ISNULL(@last_Name,'')) 
WHEN 0 THEN '' 
ELSE 'A ' + @last_name 
END AS newlastName 
+2

Bạn có chắc chắn rằng các công trình?Hầu hết các hàm trả về NULL khi đưa ra một đầu vào NULL và các kiểm thử của tôi xác nhận rằng cũng đúng với LEN() tức là, LEN (NULL) trả về NULL, không phải 0. –

+0

Pokechu22 là chính xác, và đây là kịch bản đã sửa: CASE LEN (ISNULL (last_Name) , '')) KHI 0 THÌ '' ELSE '' + last_name END AS newlastName –

+0

Tôi đã cập nhật dựa trên nhận xét của Pokechu22. –

2

Vấn đề là NULL mà không được coi là tương đương với bất cứ điều gì thậm chí không để bản thân, nhưng phần lạ là cũng là không phải là bằng chính nó. Xem xét các báo cáo sau (là BTW bất hợp pháp trong SQL Server T-SQL nhưng hợp lệ trong My-SQL, tuy nhiên đây là những gì ANSI định nghĩa cho null, và có thể được xác minh ngay cả trong SQL Server bằng cách sử dụng báo cáo trường hợp, v.v.)

SELECT NULL = NULL -- Results in NULL

SELECT NULL <> NULL -- Results in NULL

Vì vậy, không có/câu trả lời đúng sai cho câu hỏi, thay vì câu trả lời cũng là null.

này có nhiều ý nghĩa, ví dụ như trong

  1. báo cáo CASE, trong đó bất kỳ giá trị null sẽ luôn luôn sử dụng các mệnh đề ELSE trừ khi bạn sử dụng một cách rõ ràng tình trạng NULL KHI LÀ (KHÔNG điều kiện WHEN NULL)
  2. string nối, như
    SELECT a + NULL -- Results in NULL
  3. Trong một ĐÂU TRÊN hoặc ĐÂU KHÔNG TRONG khoản, như nếu bạn muốn kết quả chính xác đảm bảo trong truy vấn con tương quan để lọc ra bất kỳ giá trị null nào.

Người ta có thể ghi đè lên hành vi này trong SQL Server bằng cách xác định SET ANSI_NULLS OFF, tuy nhiên điều này là KHÔNG đề nghị và không nên được thực hiện vì nó có thể gây ra nhiều vấn đề, đơn giản chỉ vì độ lệch tiêu chuẩn.

(Như một mặt lưu ý, trong My-SQL có một tùy chọn để sử dụng một nhà điều hành đặc biệt <=> để so sánh null.)

Trong khi đó, trong ngôn ngữ lập trình nói chung null được coi là một giá trị thường xuyên và tương đương cho chính nó, tuy nhiên giá trị NAN cũng không bằng với chính nó, nhưng ít nhất nó trả về 'false' khi so sánh nó với chính nó, và khi kiểm tra không bằng các ngôn ngữ lập trình khác nhau có các cách triển khai khác nhau.Tuy nhiên, hãy lưu ý rằng trong ngôn ngữ cơ bản (ví dụ VB, v.v.) không có từ khóa 'null' và thay vào đó, từ khóa 'Không', không thể sử dụng trong so sánh trực tiếp và thay vào đó cần sử dụng 'IS' như trong SQL, tuy nhiên trên thực tế nó bằng với chính nó (khi sử dụng các so sánh gián tiếp).

0

Jason gặp phải lỗi, do đó, điều này hoạt động ...

Có ai có thể xác nhận các phiên bản nền tảng khác không?
SQL Server:

SELECT 
CASE LEN(ISNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name 
END AS newlastName 

MySQL:

SELECT 
CASE LENGTH(IFNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name 
END AS newlastName 

Oracle:

SELECT 
CASE LENGTH(NVL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name 
END AS newlastName 
0

Bạn có thể sử dụng chức năng IsNull

select 
    isnull(rtrim(ltrim([FirstName]))+' ','') + 
    isnull(rtrim(ltrim([SecondName]))+' ','') + 
    isnull(rtrim(ltrim([Surname]))+' ','') + 
    isnull(rtrim(ltrim([SecondSurname])),'') 
from TableDat 

nếu một cột là null bạn wo ULD nhận được một char trống

Tương thích với Microsoft SQL Server 2008+

0

Tôi đã cố gắng đúc thành một chuỗi và thử nghiệm cho một chuỗi số không dài và nó làm việc.

CASE 
    WHEN LEN(CAST(field_value AS VARCHAR(MAX))) = 0 THEN 
     DO THIS 
END AS field 
0

Sử dụng hàm CONCAT có sẵn trong SQL Server 2012 trở đi.

SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE 
0

NULL không bằng bất kỳ thứ gì. Câu lệnh case về cơ bản là khi giá trị = NULL .. nó sẽ không bao giờ nhấn.
Ngoài ra còn có một số quy trình được lưu trữ hệ thống được viết không đúng với cú pháp của bạn. Xem sp_addpullsubscription_agent và sp_who2.
Tôi muốn biết cách thông báo cho Microsoft về những sai lầm đó vì tôi không thể thay đổi hệ thống lưu trữ procs.

Các vấn đề liên quan