Czy ktoś może wyjaśnić, dlaczego trzecia wkładka (oznaczona Query Data) w poniższym kodzie jest dozwolona przez SQL Server?Dlaczego moje ograniczenie sprawdzające nie zatrzymuje tej pustej wkładki?
O ile mogę powiedzieć, ograniczenie wyboru powinno pozwolić tylko:
Code
jest nieważna iSystem
jest null.Code
nie jest pusty iSystem
jest1
.
Moja pierwsza myśl była ANSI NULLS
, ale ich ustawienie on
lub off
żadnej różnicy.
Jest to uproszczony przykład większego problemu, który znaleźliśmy w naszej aplikacji (System sprawdzono pod kątem listy numerów - IN(1, 2, etc.)
). Zastąpiliśmy to sprawdzenie kluczem obcym (zamiast IN
) i nowym ograniczeniem sprawdzającym, które pozwoliło na użycie zarówno wartości zerowej, jak i zerowej; to uniemożliwiło trzecią wstawkę.
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
Nie wstawiłbym (False) w nawiasach po undefined. Z pewnością nie jest to fałsz. –
@Damien_The_Unbeliever - Wiem co masz na myśli, ale dodałem w nawiasie, co 'niezdefiniowane' robi w kierunku wyniku końcowego. Dodam ten komentarz do odpowiedzi. –
Ale to, co dodałeś, nie jest prawdą. Jeśli ostatecznym wynikiem ograniczenia sprawdzającego jest "NIEZNANE", to jest traktowane tak samo, jakby było oceniane jako "PRAWDA" - to właśnie zaskoczyło PO. –