Medan man frågade produktionsservern för att lösa ett kritiskt problem, fick en fråga helt plötsligt min uppmärksamhet. Vi hade skrivit en fråga som skapades att hitta poster som existerar i tabell A men existerar inte i tabell B, baserat på en viss kolumn. Frågan var syntactically korrekt och sprang utan några fel, men det gav inga resultat. Det fanns några poster som vi hoppades få i resultaten, så vi undersökte anledningen till att rätt fråga inte returnerade några.
De INTE I klausulen returnerar rader från det yttre bordet som inte existerar i det inre bordet som används i underfrågan. I denna handledning undersöker vi användningen av NOT IN-klausulen med nullvärden.
Exempel på NOT IN-klausulen
VÄLJ * FRÅN OuterTable VAR PK_Id INTE IN (VÄLJ FK_id från InnerTable);
Exempel på NOT IN-klausulen med NULL-värden i InnerTable.
SKAPA TABELLPRODUKT (PK_Product_Id INT PRIMARY KEY, Namn VARCHAR (255)); INSÄTT I PRODUKTVÄRDEN (1, "Coke"), (2, "Pepsi"), (3, 'Mango'), (4, '7 Up'); SKAPA TABELL PRODUCT_DETAILS (PK_Details_Id INT PRIMÄR NYCKEL, [Beskrivning] VARCHAR (500), FK_Product_Id INT FÖRETAGS NYA REFERENSER PRODUKT (PK_Product_Id)); INSERT IN PRODUCT_DETAILS VÄRDEN (100, '500 ML är bra', 1); INSERT IN PRODUCT_DETAILS VALUES (101, '500 ML är bra', 2); INSERT IN PRODUCT_DETAILS VALUES (102, '500 ML är bra', 3); INSERT IN PRODUCT_DETAILS VALUES (103, '500 ML är bra', NULL);
Som visas i bilden ovan innehåller tabellen PRODUCT_DETAILS en NULL värde.
Nu är vårt mål för att ta reda på namnen på produkterna från produkttabellen vars uppgifter inte finns tillgängliga i tabellen Product_Details. Helst bör den returnera produkt 4 från produkttabellen eftersom detaljerna i produkt 4 inte finns i tabellen Product_Details.
Vi kan tro att det här enkelt kan uppnås med NOT IN-predikatet genom att skriva följande fråga.
VÄLJ * FRÅN PRODUKT VAR PK_Product_Id INTE IN (VÄLJ Fk_Product_Id FRÅN PRODUCT_DETAILS);
Frågan ovan returnerar inte någonting, även om det är korrekt, det är syntaktiskt. På grund av förekomsten av ett NULL-värde i tabellen Product_Details, klarar det inte att returnera de förväntade resultaten.
SQL Server använder Trevärderad logik koncept här.
Som vi vet är det ett NULL-värde i tabellen Product_Details i fk_product_id-kolumnen. en NULL-värdet är ett okänt eller saknat värde.
SQL Server konverterar NOT IN-klausulen med hjälp av trevärdeslogik och utvärderar den på följande sätt.
INTE IN (VÄLJ 1 ELLER 2 ELLER 3 ELLER NULL) INTE IN (Fk_product_id = 1 ELLER Fk_product_id = 2 ELLER Fk_product_id = 3 ELLER Fk_product_id = NULL) INTE IN (Fk_product_id = 1 ELLER Fk_product_id = 2 ELLER Fk_product_id = 3 ELLER UNKNOWN) INTE IN (SANT ELLER SANT ELLER SANT ELLER UNKNOWN) INTE IN (SANT ELLER SANN ELLER UNKNOWN) INTE IN (SANN ELLER UNKNOWN) INTE (UNKNOWN)
Som den slutresultatet utvärderas som UNKNOWN, returnerar NOT IN-frågan inget resultat på grund av förekomsten av ett NULL-värde.
Lösningen är att få INTE-frågorna att fungera med förekomsten av NULL-värden och använda tvåvärderad logik, bara SANT eller FALSK.
- INTE IN MED ÄR INTE NOLL Filter SELECT * FRÅN PRODUKT VAR PK_Product_Id INTE IN (VÄLJ Fk_Product_Id FRÅN PRODUCT_DETAILS VAR Fk_Product_Id ÄR INTE NULL); - INTE existerar SELECT * FRÅN PRODUKT Prd VAR UTAN EXISTERAR (VÄLJ Fk_Product_Id FRÅN PRODUCT_DETAILS WHERE Fk_Product_Id = Prd.PK_Product_Id);
INTE EXISTER ger oss också rätt resultat eftersom det använder tvåvärderad Boolean logik, endast SANT eller Falskt, för att filtrera ut raderna.
- Användning Vänster Gå med VÄLJ * FRÅN PRODUKT VÄNSTER VÄNSTER GÅ MED PRODUCT_DETAILS PrdDetails ON Prd. PK_Product_Id = PrdDetails .FK_Product_Id VAR PrdDetails. FK_Product_Id ÄR NULL
Med hjälp av vänster anslutning kan vi också hämta poster som finns i produkttabellen men existerar inte på sidan Product_Details när vi gör ett medlemskap baserat på den primära nyckeln (pk_product_id) och den främmande nyckeln (fk_product_id).