Bất cứ ai có thể giải thích lý do tại sao lần chèn thứ ba (có nhãn Dữ liệu truy vấn) trong mã dưới đây có được cho phép bởi SQL Server không?Tại sao ràng buộc kiểm tra của tôi không dừng việc chèn trống này?
Theo như tôi có thể nói, ràng buộc kiểm tra chỉ nên cho phép:
Code
là null vàSystem
là null.Code
không phải là rỗng vàSystem
là1
.
Suy nghĩ đầu tiên của tôi là ANSI NULLS
, nhưng đặt chúng on
hoặc off
không có sự khác biệt.
Đây là ví dụ đơn giản về vấn đề lớn hơn mà chúng tôi đã tìm thấy trong đơn đăng ký của mình (Hệ thống đã được kiểm tra dựa trên danh sách số - IN(1, 2, etc.)
). Chúng tôi đã thay thế séc này bằng một khóa ngoại (thay vì IN
) và một ràng buộc kiểm tra mới cho phép hoặc là cả hai null hoặc cả hai đều không phải là null; làm điều đó ngăn chặn chèn thứ ba.
IF EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[CK_TestCheck]') AND parent_object_id = OBJECT_ID(N'[dbo].[TestCheck]'))
ALTER TABLE [dbo].[TestCheck] DROP CONSTRAINT [CK_TestCheck]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestCheck]') AND type in (N'U'))
DROP TABLE [dbo].[TestCheck]
GO
SET ANSI_NULLS ON
GO
CREATE TABLE TestCheck(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Code] [varchar](50) NULL,
[System] [tinyint] NULL,
PRIMARY KEY CLUSTERED ([Id] ASC))
GO
ALTER TABLE [dbo].[TestCheck] WITH CHECK ADD CONSTRAINT [CK_TestCheck] CHECK
(
([Code] IS NULL AND [System] IS NULL) --Both null
OR
([Code] IS NOT NULL AND [System] = 1) --Both not null ????
)
GO
ALTER TABLE [dbo].[TestCheck] CHECK CONSTRAINT [CK_TestCheck]
GO
--Good Data
insert TestCheck (Code, [System]) Values(null, null);
insert TestCheck (Code, [System]) Values('123', 1);
--Query Data
insert TestCheck (Code, [System]) Values('123', null);
--Bad data stopped
insert TestCheck (Code, [System]) Values(null, 1);
insert TestCheck (Code, [System]) Values('123', 4);
select * from TestCheck
Where
case when
(
([Code] IS NULL AND [System] IS NULL) --Both null
OR
([Code] IS NOT NULL AND [System] in (1, 2, 3)) --Both not null ????
)
then 0 else 1 end
= 1
Tôi sẽ không đặt (Sai) trong ngoặc đơn sau khi không xác định. Nó chắc chắn không sai. –
@Damien_The_Unbeliever - Tôi biết ý bạn là gì nhưng tôi đã thêm nó vào dấu ngoặc đơn như những gì 'undefined' thực hiện cho kết quả cuối cùng. Tôi sẽ thêm bình luận này vào câu trả lời. –
Nhưng những gì bạn đã thêm là không đúng sự thật. Nếu kết quả cuối cùng của ràng buộc kiểm tra là 'UNKNOWN', thì nó được xử lý giống như nếu nó được đánh giá là' TRUE' - đó là điều khiến OP ngạc nhiên. –