Dies ist eine vereinfachte Version einer Abfrage, die wir ausführen, wo wir alle Zeilen in der übergeordneten Haupttabelle finden müssen, in der die untergeordneten Zeilen übereinstimmen. Die folgende Abfrage gibt keine Ergebnisse zurück, wenn eine der untergeordneten Tabellen leer ist.Warum gibt diese Abfrage nur Ergebnisse mit nicht leeren untergeordneten Tabellen zurück?
Die Haupttabelle hat zwei untergeordneten Tabellen:
CREATE TABLE main (id INT PRIMARY KEY, name VARCHAR(8));
CREATE TABLE child1(id INT PRIMARY KEY, main_id int, name VARCHAR(8));
ALTER TABLE child1 add constraint fk_child1_main foreign key (main_id) references main (id);
CREATE TABLE child2(id INT PRIMARY KEY, main_id int, name VARCHAR(8));
ALTER TABLE child2 add constraint fk_child2_main foreign key (main_id) references main (id);
INSERT INTO main (id, name) VALUES (1, 'main');
INSERT INTO child1 (id, main_id, name) VALUES (2, 1, 'child1');
Es gibt keine Zeilen in child2 und die folgende Abfrage gibt keine Zeilen, wenn es leer ist:
SELECT
main.*
FROM
main
INNER JOIN
child1
ON
main.id = child1.main_id
INNER JOIN
child2
ON
main.id = child2.main_id
WHERE
child1.name = 'child1' OR
child2.name = 'DOES NOT EXIST';
Wenn eine Zeile hinzugefügt wird child2, selbst wenn es nicht mit der WHERE-Klausel übereinstimmt, gibt SELECT die Zeile in der Haupttabelle zurück.
INSERT INTO child2 (id, main_id, name) VALUES (4, 1, 'child2');
Ich habe dies auf Derby und SQLite getestet, so dass dies etwas allgemein mit Datenbanken aussieht.
Warum verhält sich das so?
Was kann ich tun, um es zu beheben?
Ich könnte zu UNION separate SELECTs ändern, aber das ist viel ausführlicher, und plus, generieren wir die SQL dynamisch und ich würde lieber nicht unseren Code ändern müssen.
Ein weiterer Fix ist nur eine dumme Zeile zur Datenbank hinzufügen, aber das ist chaotisch.
PS Die Haupttabelle ist eine Sitzungstabelle in einem Asset Management-System, die die Assets aufzeichnet, die Clients suchen. Es gibt verschiedene Arten von Suchvorgängen, und jeder Typ erhält eine separate Kindtabelle, außerdem gibt es eine Attributtabelle für Schlüssel/Wert-Paare für die Sitzung, nach der gesucht werden kann.
Warum ändert das Hinzufügen einer nicht übereinstimmenden Zeile zu child2 das Ergebnis der Abfrage? Gemäß dieser Anweisung sollte die Abfrage selbst nach dem Hinzufügen einer nicht übereinstimmenden Zeile zu child2 immer noch keine Zeilen zurückgeben. –
Nevermind, ich sehe, dass es die main.id = child2.main_id ist, die verhindert hat, dass die Abfrage Ergebnisse zurückgibt, selbst wenn child2.name nicht übereinstimmt. Ich habe diesen Teil der Abfrage ignoriert. –