Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Bí mật bẩn thỉu của Biểu thức TÌNH HUỐNG

CASE biểu thức là một trong những cấu trúc yêu thích của tôi trong T-SQL. Nó khá linh hoạt và đôi khi là cách duy nhất để kiểm soát thứ tự mà SQL Server sẽ đánh giá các vị từ.
Tuy nhiên, nó thường bị hiểu nhầm.

Biểu thức T-SQL CASE là gì?

Trong T-SQL, CASE là một biểu thức đánh giá một hoặc nhiều biểu thức có thể có và trả về biểu thức thích hợp đầu tiên. Cụm từ biểu thức có thể hơi quá tải ở đây, nhưng về cơ bản nó là bất kỳ thứ gì có thể được đánh giá là một giá trị vô hướng, đơn lẻ, chẳng hạn như một biến, một cột, một chuỗi ký tự hoặc thậm chí là đầu ra của một hàm tích hợp hoặc hàm vô hướng .

Có hai dạng CASE trong T-SQL:

  • Biểu thức CASE đơn giản - khi bạn chỉ cần đánh giá bình đẳng:

    CASE <input> WHEN <eval> THEN <return> … [ELSE <return>] END

  • Biểu thức CASE đã tìm kiếm - khi bạn cần đánh giá các biểu thức phức tạp hơn, chẳng hạn như bất đẳng thức, LIKE hoặc KHÔNG ĐỦ:

    CASE WHEN <input_bool> THEN <return> … [ELSE <return>] END

Biểu thức trả về luôn là một giá trị duy nhất và kiểu dữ liệu đầu ra được xác định theo mức độ ưu tiên của kiểu dữ liệu.

Như tôi đã nói, biểu thức CASE thường bị hiểu nhầm; đây là một số ví dụ:

CASE là một biểu thức, không phải là một câu lệnh

Có vẻ như không quan trọng đối với hầu hết mọi người, và có lẽ đây chỉ là khía cạnh lý thuyết của tôi, nhưng nhiều người gọi nó là CASE tuyên bố - bao gồm cả Microsoft, có tài liệu sử dụng tuyên bố biểu thức thay thế cho nhau tại các thời điểm. Tôi thấy điều này hơi khó chịu (như hàng / bản ghi cột / trường ) và, mặc dù nó chủ yếu là ngữ nghĩa, nhưng có một sự khác biệt quan trọng giữa một biểu thức và một câu lệnh:một biểu thức trả về một kết quả. Khi mọi người nghĩ về CASE như một tuyên bố , nó dẫn đến các thử nghiệm trong việc rút ngắn mã như thế này:

SELECT CASE [status]
    WHEN 'A' THEN
        StatusLabel      = 'Authorized',
        LastEvent        = AuthorizedTime
    WHEN 'C' THEN
        StatusLabel      = 'Completed',
        LastEvent        = CompletedTime
    END
FROM dbo.some_table;

Hoặc cái này:

SELECT CASE WHEN @foo = 1 THEN
    (SELECT foo, bar FROM dbo.fizzbuzz)
ELSE
    (SELECT blat, mort FROM dbo.splunge)
END;

Loại logic điều khiển luồng này có thể có với CASE tuyên bố bằng các ngôn ngữ khác (như VBScript), nhưng không phải trong CASE của Transact-SQL biểu thức . Để sử dụng CASE trong cùng một logic truy vấn, bạn sẽ phải sử dụng CASE biểu thức cho mỗi cột đầu ra:

SELECT 
  StatusLabel = CASE [status]
      WHEN 'A' THEN 'Authorized' 
      WHEN 'C' THEN 'Completed' END,
  LastEvent = CASE [status]
      WHEN 'A' THEN AuthorizedTime
      WHEN 'C' THEN CompletedTime END
FROM dbo.some_table;

CASE sẽ không phải lúc nào cũng ngắn mạch

Tài liệu chính thức đã từng ngụ ý rằng toàn bộ biểu thức sẽ ngắn mạch, có nghĩa là nó sẽ đánh giá biểu thức từ trái sang phải và ngừng đánh giá khi nó gặp một kết quả phù hợp:

Câu lệnh CASE [sic!] Đánh giá các điều kiện của nó một cách tuần tự và dừng với điều kiện đầu tiên có điều kiện được thỏa mãn.

Tuy nhiên, điều này không phải lúc nào cũng đúng. Và để ghi nhận, trong một phiên bản mới hơn, trang đã tiếp tục cố gắng giải thích một trường hợp mà điều này không được đảm bảo. Nhưng nó chỉ là một phần của câu chuyện:

Trong một số tình huống, một biểu thức được đánh giá trước khi câu lệnh CASE [sic!] Nhận kết quả của biểu thức làm đầu vào của nó. Có thể có sai sót khi đánh giá các biểu thức này. Các biểu thức tổng hợp xuất hiện trong các đối số WHEN của câu lệnh CASE [sic!] Được đánh giá đầu tiên, sau đó được cung cấp cho câu lệnh CASE [sic!]. Ví dụ:truy vấn sau đây tạo ra lỗi chia cho 0 khi tạo ra giá trị của tổng hợp MAX. Điều này xảy ra trước khi đánh giá biểu thức CASE.

Ví dụ về phép chia cho số 0 khá dễ tái tạo và tôi đã chứng minh điều đó trong câu trả lời này trên dba.stackexchange.com:

DECLARE @i INT = 1;
SELECT CASE WHEN @i = 1 THEN 1 ELSE MIN(1/0) END;

Kết quả:

Msg 8134, Mức 16, Trạng thái 1
Đã gặp lỗi chia cho 0.

Có những cách giải quyết nhỏ nhặt (chẳng hạn như ELSE (SELECT MIN(1/0)) END ), nhưng điều này thực sự gây ngạc nhiên cho nhiều người chưa ghi nhớ những câu trên từ Books Online. Lần đầu tiên tôi được biết về kịch bản cụ thể này trong một cuộc trò chuyện về danh sách phân phối e-mail riêng của Itzik Ben-Gan (@ItzikBenGan), người lần lượt được Jaime Lafargue thông báo ban đầu. Tôi đã báo cáo lỗi trong Connect # 690017:CASE / COALESCE không phải lúc nào cũng đánh giá theo thứ tự văn bản; nó nhanh chóng được đóng lại với tên "Theo thiết kế". Paul White (blog | @SQL_Kiwi) sau đó đã đệ trình Connect # 691535:Các tổng thể không tuân theo ngữ nghĩa của CASE, và nó đã bị đóng là "Đã sửa." Cách khắc phục, trong trường hợp này, đã được làm rõ trong bài báo Sách trực tuyến; cụ thể là đoạn mã tôi đã sao chép ở trên.

Hành vi này cũng có thể tự mang lại trong một số trường hợp khác, ít rõ ràng hơn. Ví dụ:Connect # 780132:FREETEXT () không tuân theo thứ tự đánh giá trong câu lệnh CASE (không liên quan đến tổng hợp) cho thấy rằng CASE Thứ tự đánh giá cũng không được đảm bảo là từ trái sang phải khi sử dụng một số hàm toàn văn. Về mục đó, Paul White nhận xét rằng ông cũng quan sát thấy điều gì đó tương tự bằng cách sử dụng LAG() mới được giới thiệu trong SQL Server 2012. Tôi không có bản repro hữu ích, nhưng tôi tin anh ấy và tôi không nghĩ rằng chúng tôi đã khai quật được tất cả các trường hợp phức tạp mà điều này có thể xảy ra.

Vì vậy, khi liên quan đến tổng hợp hoặc các dịch vụ không phải gốc như Tìm kiếm toàn văn bản, vui lòng không đưa ra bất kỳ giả định nào về hiện tượng đoản mạch trong CASE biểu thức.

RAND () có thể được đánh giá nhiều lần

Tôi thường thấy mọi người viết một đơn giản CASE biểu thức, như thế này:

SELECT CASE @variable 
  WHEN 1 THEN 'foo'
  WHEN 2 THEN 'bar'
END

Điều quan trọng là phải hiểu rằng điều này sẽ được thực thi dưới dạng đã tìm kiếm CASE biểu thức, như thế này:

SELECT CASE  
  WHEN @variable = 1 THEN 'foo'
  WHEN @variable = 2 THEN 'bar'
END

Lý do quan trọng phải hiểu rằng biểu thức đang được đánh giá sẽ được đánh giá nhiều lần, là vì nó thực sự có thể được đánh giá nhiều lần. Khi đây là một biến, hoặc một hằng số, hoặc một tham chiếu cột, thì đây không phải là một vấn đề thực sự; tuy nhiên, mọi thứ có thể thay đổi nhanh chóng khi nó là một hàm không xác định. Hãy xem xét rằng biểu thức này mang lại SMALLINT từ 1 đến 3; hãy tiếp tục và chạy nó nhiều lần, và bạn sẽ luôn nhận được một trong ba giá trị đó:

SELECT CONVERT(SMALLINT, 1+RAND()*3);

Bây giờ, hãy đặt nó vào một CASE đơn giản và chạy nó hàng chục lần - cuối cùng bạn sẽ nhận được kết quả là NULL :

SELECT [result] = CASE CONVERT(SMALLINT, 1+RAND()*3)
  WHEN 1 THEN 'one'
  WHEN 2 THEN 'two'
  WHEN 3 THEN 'three'
END;

Làm thế nào điều này xảy ra? Chà, toàn bộ CASE biểu thức được mở rộng thành một biểu thức được tìm kiếm, như sau:

SELECT [result] = CASE 
  WHEN CONVERT(SMALLINT, 1+RAND()*3) = 1 THEN 'one'
  WHEN CONVERT(SMALLINT, 1+RAND()*3) = 2 THEN 'two'
  WHEN CONVERT(SMALLINT, 1+RAND()*3) = 3 THEN 'three'
  ELSE NULL -- this is always implicitly there
END;

Đổi lại, điều xảy ra là mỗi WHEN mệnh đề đánh giá và gọi RAND() độc lập - và trong mỗi trường hợp, nó có thể mang lại một giá trị khác nhau. Giả sử chúng tôi nhập biểu thức và chúng tôi kiểm tra WHEN đầu tiên mệnh đề, và kết quả là 3; chúng ta bỏ qua điều khoản đó và tiếp tục. Có thể hình dung rằng cả hai mệnh đề tiếp theo sẽ trả về 1 khi RAND() được đánh giá lại - trong trường hợp này không có điều kiện nào được đánh giá là true, vì vậy ELSE tiếp quản.

Các biểu thức khác có thể được đánh giá nhiều lần

Sự cố này không chỉ giới hạn ở RAND() hàm số. Hãy tưởng tượng cùng một kiểu thuyết phi quyết định đến từ các mục tiêu di động này:

SELECT 
  [crypt_gen]   = 1+ABS(CRYPT_GEN_RANDOM(10) % 20),
  [newid]       = LEFT(NEWID(),2),
  [checksum]    = ABS(CHECKSUM(NEWID())%3);

Các biểu thức này rõ ràng có thể mang lại một giá trị khác nếu được đánh giá nhiều lần. Và với một CASE được tìm kiếm , sẽ có lúc mọi đánh giá lại không nằm ngoài tìm kiếm cụ thể cho WHEN hiện tại và cuối cùng nhấn ELSE mệnh đề. Để bảo vệ bạn khỏi điều này, một tùy chọn là luôn viết mã cố định ELSE rõ ràng của riêng bạn; chỉ cần cẩn thận về giá trị dự phòng bạn chọn để trả lại, vì điều này sẽ có một số hiệu ứng lệch nếu bạn đang tìm kiếm phân phối đồng đều. Một tùy chọn khác là chỉ thay đổi WHEN cuối cùng mệnh đề đến ELSE , nhưng điều này vẫn sẽ dẫn đến phân phối không đồng đều. Tùy chọn ưu tiên, theo ý kiến ​​của tôi, là thử và ép buộc SQL Server đánh giá điều kiện một lần (mặc dù điều này không phải lúc nào cũng có thể thực hiện được trong một truy vấn). Ví dụ:so sánh hai kết quả sau:

-- Query A: expression referenced directly in CASE; no ELSE:
SELECT x, COUNT(*) FROM
(
  SELECT x = CASE ABS(CHECKSUM(NEWID())%3) 
  WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' END 
  FROM sys.all_columns
) AS y GROUP BY x;
 
-- Query B: additional ELSE clause:
SELECT x, COUNT(*) FROM
(
  SELECT x = CASE ABS(CHECKSUM(NEWID())%3) 
  WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE '2' END 
  FROM sys.all_columns
) AS y GROUP BY x;
 
-- Query C: Final WHEN converted to ELSE:
SELECT x, COUNT(*) FROM
(
  SELECT x = CASE ABS(CHECKSUM(NEWID())%3) 
  WHEN 0 THEN '0' WHEN 1 THEN '1' ELSE '2' END 
  FROM sys.all_columns
) AS y GROUP BY x;
 
-- Query D: Push evaluation of NEWID() to subquery:
SELECT x, COUNT(*) FROM
(
  SELECT x = CASE x WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' END 
  FROM 
  (
    SELECT x = ABS(CHECKSUM(NEWID())%3) FROM sys.all_columns
  ) AS x
) AS y GROUP BY x;

Phân phối:

Giá trị Truy vấn A Truy vấn B Truy vấn C Truy vấn D
KHÔNG ĐỦ 2,572 - - -
0 2.923 2.900 2.928 2.949
1 1.946 1.959 1.927 2.896
2 1.295 3.877 3.881 2.891

Phân phối giá trị bằng các kỹ thuật truy vấn khác nhau

Trong trường hợp này, tôi dựa vào thực tế là SQL Server đã chọn đánh giá biểu thức trong truy vấn con và không giới thiệu nó với CASE đã tìm kiếm nhưng điều này chỉ để chứng minh rằng phân phối có thể bị ép buộc để đồng đều hơn. Trong thực tế, đây có thể không phải lúc nào cũng là lựa chọn mà trình tối ưu hóa đưa ra, vì vậy vui lòng không học từ thủ thuật nhỏ này. :-)

CHOOSE () cũng bị ảnh hưởng

Bạn sẽ thấy điều đó nếu bạn thay thế CHECKSUM(NEWID()) biểu thức với RAND() biểu thức, bạn sẽ nhận được các kết quả hoàn toàn khác; đáng chú ý nhất, sau này sẽ chỉ trả về một giá trị. Điều này là do RAND() , như GETDATE() và một số hàm tích hợp khác, được xử lý đặc biệt như một hằng số thời gian chạy và chỉ được đánh giá một lần trên mỗi tham chiếu cho toàn bộ hàng. Lưu ý rằng nó vẫn có thể trả về NULL giống như truy vấn đầu tiên trong mẫu mã trước đó.

Vấn đề này cũng không chỉ giới hạn ở CASE biểu hiện; bạn có thể thấy hành vi tương tự với các hàm tích hợp khác sử dụng cùng ngữ nghĩa cơ bản. Ví dụ:CHOOSE chỉ đơn thuần là đường cú pháp cho một CASE được tìm kiếm phức tạp hơn và điều này cũng sẽ mang lại NULL thỉnh thoảng:

SELECT [choose] = CHOOSE(CONVERT(SMALLINT, 1+RAND()*3),'one','two','three');

IIF() là một hàm mà tôi dự kiến ​​sẽ rơi vào cùng một cái bẫy này, nhưng hàm này thực sự chỉ là một CASE được tìm kiếm biểu thức chỉ có hai kết quả có thể xảy ra và không có ELSE - vì vậy thật khó, nếu không lồng ghép và giới thiệu các chức năng khác, để hình dung một kịch bản mà điều này có thể bị phá vỡ bất ngờ. Trong trường hợp đơn giản, nó là viết tắt phù hợp cho CASE , cũng rất khó để làm bất cứ điều gì hữu ích với nó nếu bạn cần nhiều hơn hai kết quả có thể xảy ra. :-)

COALESCE () cũng bị ảnh hưởng

Cuối cùng, chúng ta nên kiểm tra COALESCE đó có thể có các vấn đề tương tự. Hãy coi rằng các biểu thức này là tương đương:

SELECT COALESCE(@variable, 'constant');
 
SELECT CASE WHEN @variable IS NOT NULL THEN @variable ELSE 'constant' END);

Trong trường hợp này, @variable sẽ được đánh giá hai lần (cũng như bất kỳ hàm hoặc truy vấn con nào, như được mô tả trong mục Kết nối này).

Tôi thực sự có thể nhận được một số cái nhìn khó hiểu khi tôi đưa ra ví dụ sau đây trong một cuộc thảo luận diễn đàn gần đây. Giả sử tôi muốn điền một bảng có phân phối giá trị từ 1-5, nhưng bất cứ khi nào gặp 3, tôi muốn sử dụng -1 thay thế. Không phải là một kịch bản thực tế, nhưng dễ xây dựng và theo dõi. Một cách để viết biểu thức này là:

SELECT COALESCE(NULLIF(CONVERT(SMALLINT,1+RAND()*5),3),-1);

(Bằng tiếng Anh, làm việc từ trong ra ngoài:chuyển đổi kết quả của biểu thức 1+RAND()*5 đến một người thợ rèn; nếu kết quả của chuyển đổi đó là 3, hãy đặt nó thành NULL; nếu kết quả của điều đó là NULL , đặt nó thành -1. Bạn có thể viết điều này với một CASE dài dòng hơn diễn đạt, nhưng ngắn gọn dường như là vua.)

Nếu bạn chạy nhiều lần như vậy, bạn sẽ thấy một loạt các giá trị từ 1-5, cũng như -1. Bạn sẽ thấy một số trường hợp của 3 và bạn cũng có thể nhận thấy rằng bạn thỉnh thoảng thấy NULL , mặc dù bạn có thể không mong đợi một trong hai kết quả đó. Hãy kiểm tra phân phối:

USE tempdb;
GO
CREATE TABLE dbo.dist(TheNumber SMALLINT);
GO
INSERT dbo.dist(TheNumber) SELECT COALESCE(NULLIF(CONVERT(SMALLINT,1+RAND()*5),3),-1);
GO 10000
SELECT TheNumber, occurences = COUNT(*) FROM dbo.dist 
  GROUP BY TheNumber ORDER BY TheNumber;
GO
DROP TABLE dbo.dist;

Kết quả (kết quả của bạn chắc chắn sẽ khác nhau, nhưng xu hướng cơ bản phải tương tự):

TheNumber lần xuất hiện
NULL 1.654
- 1 2,002
1 1.290
2 1,266
3 1.287
4 1.251
5 1.250

Phân phối TheNumber bằng COALESCE

Chia nhỏ biểu thức CASE đã tìm kiếm

Bạn đang vò đầu bứt tai chưa? Làm thế nào để các giá trị NULL và 3 hiển thị và tại sao phân phối cho NULL và -1 cao hơn đáng kể? Chà, tôi sẽ trả lời trực tiếp câu trước và đưa ra giả thuyết cho phần sau.

Biểu thức gần như mở rộng thành sau, theo logic, vì RAND() được đánh giá hai lần bên trong NULLIF , và sau đó nhân nó với hai đánh giá cho mỗi nhánh của COALESCE hàm số. Tôi không có trình gỡ lỗi tiện dụng, vì vậy đây không nhất thiết phải * chính xác * những gì được thực hiện bên trong SQL Server, nhưng nó phải đủ tương đương để giải thích điểm:

SELECT 
  CASE WHEN 
      CASE WHEN CONVERT(SMALLINT,1+RAND()*5) = 3 THEN NULL 
      ELSE CONVERT(SMALLINT,1+RAND()*5) 
      END 
    IS NOT NULL 
    THEN
      CASE WHEN CONVERT(SMALLINT,1+RAND()*5) = 3 THEN NULL 
      ELSE CONVERT(SMALLINT,1+RAND()*5) 
      END
    ELSE -1
  END
END

Vì vậy, bạn có thể thấy rằng việc được đánh giá nhiều lần có thể nhanh chóng trở thành cuốn sách Choose Your Own Adventure ™ và cả hai NULL và 3 là những kết quả có thể xảy ra mà dường như không thể xảy ra khi xem xét tuyên bố ban đầu. Một lưu ý phụ thú vị:điều này không xảy ra hoàn toàn giống nhau nếu bạn lấy tập lệnh phân phối ở trên và thay thế COALESCE với ISNULL . Trong trường hợp đó, không có khả năng xảy ra NULL đầu ra; phân phối gần như sau:

TheNumber lần xuất hiện
- 1 1.966
1 1.585
2 1.644
3 1.573
4 1.598
5 1,634

Phân phối TheNumber bằng ISNULL

Một lần nữa, kết quả thực tế của bạn chắc chắn sẽ khác nhau, nhưng không quá nhiều. Vấn đề là chúng ta vẫn có thể thấy 3 lần rơi qua các vết nứt khá thường xuyên, nhưng ISNULL loại bỏ tiềm năng NULL một cách kỳ diệu để làm cho nó thông suốt.

Tôi đã nói về một số khác biệt khác giữa COALESCEISNULL trong một mẹo, có tên "Quyết định giữa COALESCE và ISNULL trong SQL Server." Khi tôi viết điều đó, tôi rất ủng hộ việc sử dụng COALESCE ngoại trừ trường hợp đối số đầu tiên là một truy vấn con (một lần nữa, do lỗi này "khoảng cách tính năng"). Bây giờ tôi không chắc mình cảm thấy mạnh mẽ về điều đó.

Các biểu thức CASE đơn giản có thể được lồng vào các máy chủ được liên kết

Một trong những hạn chế của CASE biểu thức được giới hạn ở 10 cấp độ tổ. Trong ví dụ này trên dba.stackexchange.com, Paul White chứng minh (sử dụng Plan Explorer) rằng một biểu thức đơn giản như sau:

SELECT CASE column_name
  WHEN '1' THEN 'a' 
  WHEN '2' THEN 'b'
  WHEN '3' THEN 'c'
  ...
END
FROM ...

Được trình phân tích cú pháp mở rộng thành biểu mẫu đã tìm kiếm:

SELECT CASE 
  WHEN column_name = '1' THEN 'a' 
  WHEN column_name = '2' THEN 'b'
  WHEN column_name = '3' THEN 'c'
  ...
END
FROM ...

Nhưng thực sự có thể được truyền qua kết nối máy chủ được liên kết như sau, truy vấn chi tiết hơn nhiều:

SELECT 
  CASE WHEN column_name = '1' THEN 'a' ELSE
    CASE WHEN column_name = '2' THEN 'b' ELSE
      CASE WHEN column_name = '3' THEN 'c' ELSE 
      ... 
      ELSE NULL
      END
    END
  END
FROM ...

Trong trường hợp này, mặc dù truy vấn ban đầu chỉ có một CASE duy nhất biểu thức với hơn 10 kết quả có thể có, khi được gửi đến máy chủ được liên kết, nó có hơn 10 lồng nhau CASE biểu thức. Do đó, như bạn có thể mong đợi, nó trả về một lỗi:

Không thể chuẩn bị (các) câu lệnh Msg 8180, Mức 16, Trạng thái 1
.
Câu lệnh Msg 125, Mức 15, Trạng thái 4
chỉ có thể được lồng vào mức 10.

Trong một số trường hợp, bạn có thể viết lại nó như Paul đã đề xuất, với một biểu thức như thế này (giả sử column_name là một cột varchar):

SELECT CASE CONVERT(VARCHAR(MAX), SUBSTRING(column_name, 1, 255))
  WHEN 'a' THEN '1'
  WHEN 'b' THEN '2'
  WHEN 'c' THEN '3'
  ...
END
FROM ...

Trong một số trường hợp, chỉ SUBSTRING có thể được yêu cầu thay đổi vị trí nơi biểu thức được đánh giá; ở những người khác, chỉ CONVERT . Tôi đã không thực hiện kiểm tra toàn diện, nhưng điều này có thể liên quan đến nhà cung cấp máy chủ được liên kết, các tùy chọn như đối chiếu Tương thích và Sử dụng đối chiếu từ xa và phiên bản của SQL Server ở một trong hai đầu của đường dẫn.

Câu chuyện ngắn, điều quan trọng cần nhớ là CASE của bạn biểu thức có thể được viết lại cho bạn mà không cần cảnh báo và rằng bất kỳ giải pháp nào bạn sử dụng sau này có thể bị trình tối ưu hóa thay thế, ngay cả khi nó phù hợp với bạn bây giờ.

Ý tưởng cuối cùng của diễn đạt trong CASE và các tài nguyên bổ sung

Tôi hy vọng tôi đã cho một số thực phẩm để suy nghĩ về một số khía cạnh ít được biết đến của CASE biểu thức và một số thông tin chi tiết về các tình huống trong đó CASE - và một số hàm sử dụng cùng một logic cơ bản - trả về kết quả không mong đợi. Một số tình huống thú vị khác trong đó loại vấn đề này đã xảy ra:

  • Stack Overflow:Làm cách nào để biểu thức CASE này tiếp cận mệnh đề ELSE?
  • Tràn ngăn xếp:CRYPT_GEN_RANDOM () Hiệu ứng lạ
  • Tràn ngăn xếp:CHOOSE () Không hoạt động như dự định
  • Stack Overflow:CHECKSUM (NewId ()) thực thi nhiều lần trên mỗi hàng
  • Kết nối # 350485:Lỗi với NEWID () và Biểu thức bảng

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ALTER tốt hơn DROP

  2. Làm thế nào để có được ngày cuối cùng của tháng trong T-SQL

  3. Cung cấp quà Giáng sinh:Mô hình dữ liệu của ông già Noel

  4. SQL AS:Cách sử dụng, ví dụ và cách nó có thể mang lại lợi ích tốt nhất cho bạn

  5. Cách sao chép dữ liệu từ bảng này sang bảng khác trong SQL