Dreiwertige Logik von SQL Server und NOT IN-Klausel mit NULL-Werten

Beim Abfragen des Produktionsservers zur Lösung eines kritischen Problems fiel mir plötzlich eine Abfrage auf. Wir hatten eine Abfrage geschrieben, die erstellt wurde Datensätze zu finden, die in Tabelle A vorhanden sind, aber nicht in Tabelle B vorhanden sind, basierend auf einer bestimmten Spalte. Die Abfrage war syntaktisch korrekt und lief fehlerfrei. Es wurden jedoch keine Ergebnisse zurückgegeben. Es gab einige Datensätze, von denen wir hofften, dass sie in die Ergebnisse einfließen würden. Deshalb untersuchten wir den Grund, warum die richtige Abfrage keine zurückgegeben hat.

Das NICHT IN Klausel gibt Zeilen aus der äußeren Tabelle zurück, die in der in der Unterabfrage verwendeten inneren Tabelle nicht vorhanden sind. In diesem Lernprogramm wird die Verwendung der Klausel NOT IN mit Nullwerten untersucht.

Beispiel für die Klausel NOT IN

SELECT * FROM OuterTable WHERE PK_Id NICHT IN (SELECT FK_id von InnerTable); 

Beispiel für die Klausel NOT IN mit NULL-Werten in InnerTable.

CREATE TABLE PRODUCT (PK_Product_Id INT PRIMARY KEY, Name VARCHAR (255)); EINSETZEN IN PRODUKTWERTE (1, 'Cola'), (2, 'Pepsi'), (3, 'Mango'), (4, '7 Up'); CREATE TABLE PRODUCT_DETAILS (PK_Details_Id INT PRIMARY KEY, [Beschreibung] VARCHAR (500), FK_Product_Id INT FOREIGN KEY-REFERENZEN PRODUCT (PK_Product_Id)); INSERT IN PRODUCT_DETAILS VALUES (100, '500 ML ist gut', 1); INSERT IN PRODUCT_DETAILS VALUES (101, '500 ML ist gut', 2); INSERT IN PRODUCT_DETAILS VALUES (102, '500 ML ist gut', 3); INSERT IN PRODUCT_DETAILS VALUES (103, '500 ML ist gut', NULL); 

Wie in der Abbildung oben gezeigt, enthält die Tabelle PRODUCT_DETAILS eine NULL-Wert.

Nun ist unser Ziel um die Namen der Produkte aus der Product-Tabelle herauszufinden, deren Details nicht in der Product_Details-Tabelle verfügbar sind. Idealerweise sollte Product 4 aus der Product-Tabelle zurückgegeben werden, da die Details zu Product 4 nicht in der Product_Details-Tabelle vorhanden sind.

Wir denken vielleicht, dass dies mit dem NOT IN-Prädikat leicht erreicht werden kann, indem Sie die folgende Abfrage schreiben.

SELECT * FROM PRODUCT WO PK_Product_Id NICHT IN (SELECT Fk_Product_Id FROM PRODUCT_DETAILS); 

Die obige Abfrage gibt nichts zurück, obwohl sie syntaktisch korrekt ist. Da in der Tabelle Product_Details ein NULL-Wert vorhanden ist, werden die erwarteten Ergebnisse nicht zurückgegeben.

SQL Server verwendet die Dreiwertige Logik Konzept hier.

Es ist bekannt, dass in der Tabelle Product_Details in der Spalte fk_product_id ein NULL-Wert vorhanden ist. EIN Der NULL-Wert ist ein unbekannter oder fehlender Wert.

SQL Server konvertiert die NOT IN-Klausel unter Verwendung der Dreiwertlogik und wertet sie auf folgende Weise aus.

NOT IN (SELECT 1 ODER 2 ODER 3 ODER NULL) NOT IN (Fk_product_id = 1 OR Fk_product_id = 2 OR Fk_product_id = 3 OR Fk_product_id = NULL) NICHT IN (Fk_product_id = 1 OR Fk_product_id = 2 OR Fk_product_id = 3 OR UNKNOWN) (TRUE ODER TRUE ODER TRUE ODER UNKNOWN) NICHT IN (TRUE ODER TRUE ODER UNKNOWN) NICHT IN (TRUE ODER UNKNOWN) NICHT IN (UNKNOWN) 

Als die Das Endergebnis wird als UNKNOWN ausgewertet. Die NOT IN-Abfrage gibt kein Ergebnis zurück, da ein NULL-Wert vorhanden ist.

Die Lösung besteht darin, die NOT IN-Abfragen mit dem Vorhandensein von NULL-Werten arbeiten zu lassen und zweiwertige Logik zu verwenden, nur TRUE oder FALSE.

--NOT IN MIT IST NICHT NULL Filter SELECT * FROM PRODUCT WO PK_Product_Id NICHT IN (SELECT Fk_Product_Id FROM PRODUCT_DETAILS WO Fk_Product_ID NICHT NULL IST); --NOT existiert SELECT * FROM PRODUCT Prd nicht vorhanden (SELECT Fk_Product_Id FROM PRODUCT_DETAILS WHERE Fk_Product_Id = Prd.PK_Product_Id); 

NOT EXISTS liefert auch die richtigen Ergebnisse, da die boolesche Logik mit zwei Werten (nur TRUE oder False) zum Ausfiltern der Zeilen verwendet wird.

--Verwenden Sie Left Join SELECT * FROM PRODUKT Prd LINKS JOIN PRODUCT_DETAILS PrdDetails ON Prd. PK_Product_Id = PrdDetails .FK_Product_Id WHERE PrdDetails. FK_Product_Id ist NULL 

Mit Left Join können wir auch Datensätze abrufen, die in der Product-Tabelle vorhanden sind, aber nicht auf der Seite Product_Details vorhanden sind, wenn wir einen Join auf der Grundlage des Primärschlüssels (pk_product_id) und des Fremdschlüssels (fk_product_id) durchführen.