Ceci est une version simplifiée d'une requête que nous exécutons où nous devons trouver toutes les lignes de la table parent principale où les lignes enfants correspondent. La requête ci-dessous ne renvoie aucun résultat lorsque l'une des tables enfant est vide.Pourquoi cette requête renvoie-t-elle uniquement des résultats avec des tables enfants non vides?
Le tableau principal a deux tables enfant:
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');
Il n'y a pas de lignes dans child2 et la requête suivante renvoie aucune ligne quand il est vide:
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';
Si une ligne est ajoutée à child2, même s'il ne correspond pas à la clause WHERE, le SELECT renvoie la ligne dans la table principale. Je l'ai testé sur Derby et SQLite, donc cela semble être quelque chose de général avec les bases de données.
Pourquoi cela se comporte-t-il de cette façon?
Que puis-je faire pour le réparer?
Je pourrais passer à des SELECT séparés UNION, mais c'est beaucoup plus bavard, et plus, nous générons dynamiquement le SQL et je préfère ne pas avoir à changer notre code.
Une autre solution consiste simplement à ajouter une ligne bête à la base de données, mais c'est compliqué. PS La table principale est une table de session dans un système de gestion des actifs qui enregistre les actifs que les clients recherchent. Il existe différents types de recherches et chaque type obtient une table enfant distincte, plus une table d'attributs enfant pour les paires clé/valeur de la session sur laquelle la recherche peut être effectuée.
Alors pourquoi ajouter une ligne non-assortie à child2 change le résultat de la requête? Selon cette instruction, même après l'ajout d'une ligne non-assortie à child2, la requête ne devrait toujours renvoyer aucune ligne. –
Peu importe, je vois que c'est le main.id = child2.main_id qui empêchait la requête de retourner des résultats, même si child2.name ne correspond pas. J'ignorais juste cette partie de la requête. –