Trong SQL Server, “SET ANSI_NULLS ON” có nghĩa là gì?


92

Định nghĩa cho biết:

Khi SET ANSI_NULLS được BẬT, một câu lệnh SELECT sử dụng WHERE column_name = NULL trả về 0 hàng ngay cả khi có giá trị rỗng trong column_name. Câu lệnh SELECT sử dụng WHERE column_name <> NULL trả về 0 hàng ngay cả khi có các giá trị không phải null trong column_name.

Điều này có nghĩa là không có nulls sẽ được bao gồm trong truy vấn này?

SELECT Region
FROM employees
WHERE Region = @region

Hay bạn ANSI_NULLchỉ quan tâm đến các truy vấn như thế này (trong đó WHEREbao gồm từ cụ thể NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
Câu trả lời chưa có trong đoạn thứ 4 của tài liệu chính thức mà từ đó bạn đã sao chép đoạn đầu tiên, đó là: -> "SET ANSI_NULLS ON chỉ ảnh hưởng đến phép so sánh nếu một trong các toán hạng của phép so sánh là một biến NULL hoặc NULL theo nghĩa đen. Nếu cả hai bên của phép so sánh đều là cột hoặc biểu thức ghép thì cài đặt không ảnh hưởng đến phép so sánh. "
user1451111

Câu trả lời:


68

Nó có nghĩa là không có hàng sẽ được trả lại nếu @regionNULL, khi được sử dụng trong ví dụ đầu tiên của bạn, ngay cả khi có hàng trong bảng ở đâu RegionNULL.

Khi nào ANSI_NULLSđược bật (mà bạn nên luôn bật, vì tùy chọn không bật sẽ bị loại bỏ trong tương lai), bất kỳ thao tác so sánh nào trong đó (ít nhất) một trong các toán hạng được NULLtạo ra giá trị logic thứ ba - UNKNOWN( trái ngược với TRUEFALSE).

UNKNOWNgiá trị truyền qua bất kỳ toán tử boolean kết hợp nào nếu chúng chưa được quyết định (ví dụ: ANDvới một FALSEtoán hạng hoặc ORvới một TRUEtoán hạng) hoặc phủ định ( NOT).

Các WHEREkhoản được sử dụng để lọc các tập kết quả được tạo ra bởi các FROMđiều khoản, như vậy tổng giá trị của WHEREkhoản phải TRUEcho hàng không được lọc ra. Vì vậy, nếu một UNKNOWNđược tạo ra bởi bất kỳ so sánh nào, nó sẽ khiến hàng đó bị lọc ra.


Câu trả lời của @ user1227804 bao gồm câu trích dẫn này:

Nếu cả hai bên của phép so sánh là cột hoặc biểu thức ghép, cài đặt không ảnh hưởng đến phép so sánh.

từ *SET ANSI_NULLS

Tuy nhiên, tôi không chắc nó đang cố gắng thực hiện điểm nào, vì nếu hai NULLcột được so sánh (ví dụ: trong a JOIN), so sánh vẫn không thành công:

create table #T1 (
    ID int not null,
    Val1 varchar(10) null
)
insert into #T1(ID,Val1) select 1,null

create table #T2 (
    ID int not null,
    Val1 varchar(10) null
)
insert into #T2(ID,Val1) select 1,null

select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and t1.Val1 = t2.Val1

Truy vấn trên trả về 0 hàng, trong khi:

select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and (t1.Val1 = t2.Val1 or t1.Val1 is null and t2.Val1 is null)

Trả về một hàng. Vì vậy, ngay cả khi cả hai toán hạng là cột, NULLkhông bằng nhau NULL. Và tài liệu cho= không có bất cứ điều gì để nói về các toán hạng:

Khi bạn so sánh hai NULLbiểu thức, kết quả phụ thuộc vào ANSI_NULLScài đặt:

Nếu ANSI_NULLSđược đặt thành ON, kết quả là NULL1 , tuân theo quy ước ANSI rằng một NULLgiá trị (hoặc không xác định) không bằng một NULLgiá trị khác hoặc không xác định.

Nếu ANSI_NULLSđược đặt thành OFF, kết quả của NULLso với NULLTRUE.

So sánh NULLvới một NULLgiá trị khác luôn dẫn đến kết quả là FALSE2 .

Tuy nhiên, cả 12 đều không chính xác - kết quả của cả hai phép so sánh là UNKNOWN.


* Ý nghĩa khó hiểu của văn bản này cuối cùng đã được khám phá nhiều năm sau đó. Điều thực sự có nghĩa là, đối với những so sánh đó, cài đặt không có hiệu lực và nó luôn hoạt động như thể cài đặt được BẬT . Sẽ rõ ràng hơn nếu nó đã nói rằng đó SET ANSI_NULLS OFFlà cài đặt không ảnh hưởng.


1
vì vậy nếu tôi hiểu bạn đúng: nó cũng ảnh hưởng đến kết quả của cụm từ "Where Region = @region" và không chỉ khi tôi viết cụ thể "Where Region = null"?
Rodniko

7

Nếu @Regionkhông phải là một nullgiá trị (giả sử @Region = 'South'), nó sẽ không trả về các hàng trong đó trường Vùng là rỗng, bất kể giá trị của ANSI_NULLS.

ANSI_NULLS sẽ chỉ tạo ra sự khác biệt khi giá trị của @Regionnull, tức là khi truy vấn đầu tiên của bạn về cơ bản trở thành truy vấn thứ hai.

Trong trường hợp đó, ANSI_NULLS ON sẽ không trả về bất kỳ hàng nào (vì null = nullsẽ mang lại giá trị boolean không xác định (còn gọi là null)) và ANSI_NULLS OFF sẽ trả về bất kỳ hàng nào có trường Vùng là rỗng (vì null = nullsẽ mang lại kết quả true)


6

Nếu ANSI_NULLS được đặt thành "ON" và nếu chúng ta áp dụng =, <> trên giá trị cột NULL trong khi viết câu lệnh select thì nó sẽ không trả về bất kỳ kết quả nào.

Thí dụ

create table #tempTable (sn int, ename varchar(50))

insert into #tempTable
values (1, 'Manoj'), (2, 'Pankaj'), (3, NULL), (4, 'Lokesh'), (5, 'Gopal')

BẬT ANSI_NULLS

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (0 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (0 row(s) affected)

TẮT ANSI_NULLS

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (1 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (4 row(s) affected)

2
+1 vì là câu trả lời DUY NHẤT phân biệt rõ ràng giữa WHERE X IS NULLWHERE X = NULLvà cách ANSI_NULLS ảnh hưởng đến kết quả. Bất chấp những nỗ lực hết sức nhiệt tình của những cử tri xuống dốc, ĐÂY phải là câu trả lời được chấp nhận!
Riegardt Steyn

1
+1 để giải thích bằng cách sử dụng các ví dụ, sẽ luôn rõ ràng và ngắn gọn hơn thay vì các câu dài.
peter.aryanto

3

BẬT ANSI_NULLS

IT Trả về tất cả các giá trị bao gồm cả giá trị rỗng trong bảng

Tắt ANSI_NULLS

nó Kết thúc khi các cột chứa giá trị rỗng


2
Câu trả lời này bổ sung thêm gì cho các câu trả lời đã nêu? Hãy thận trọng với việc thêm câu trả lời mới cho các câu hỏi cũ - Chúng phải chứa phần giải thích mở rộng về các giải pháp đã được đăng hoặc cung cấp thông tin chi tiết mới - Từ đánh giá
Takarii

1

Tôi đoán điều chính ở đây là:

Không bao giờ người dùng:

  • @anything = NULL
  • @anything <> NULL
  • @anything != null

Luôn luôn sử dụng:

  • @anything IS NULL
  • @anything IS NOT NULL

0

Đặt ANSI NULLS OFF sẽ làm cho phép so sánh NULL = NULL trả về true. VÍ DỤ :

        SET ANSI_NULLS OFF
        select * from sys.tables
        where principal_id = Null

sẽ trả về một số kết quả như được hiển thị bên dưới: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Mặc dù truy vấn này sẽ không trả lại bất kỳ kết quả nào:

        SET ANSI_NULLS ON 
        select * from sys.tables
        where principal_id = Null

0

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql

Khi SET ANSI_NULLS được BẬT, một câu lệnh SELECT sử dụng WHERE column_name = NULL trả về 0 hàng ngay cả khi có giá trị rỗng trong column_name. Câu lệnh SELECT sử dụng WHERE column_name <> NULL trả về 0 hàng ngay cả khi có các giá trị không rỗng trong column_name.

Ví dụ

DECLARE @TempVariable VARCHAR(10)
SET @TempVariable = NULL

SET ANSI_NULLS ON
SELECT 'NO ROWS IF SET ANSI_NULLS ON' where    @TempVariable = NULL
-- IF ANSI_NULLS ON , RETURNS ZERO ROWS


SET ANSI_NULLS OFF
SELECT 'THERE WILL BE A ROW IF ANSI_NULLS OFF' where    @TempVariable =NULL
-- IF ANSI_NULLS OFF , THERE WILL BE ROW !
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.