这是我们正在运行的查询的简化版本,我们需要在主父表中查找子行匹配的所有行。当子表之一为空时,以下查询不返回任何结果。
主表有两个子表:
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');
child2 中没有行,当它为空时,以下查询不返回任何行:
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';
如果将一行添加到 child2,即使它与 WHERE 子句不匹配,SELECT 也会返回主表中的行。
INSERT INTO child2 (id, main_id, name) VALUES (4, 1, 'child2');
我已经在 Derby 和 SQLite 上对此进行了测试,所以这看起来与数据库通用。
为什么会这样?
我能做些什么来修复它?
我可以更改为 UNION 单独的 SELECT,但这更冗长,而且,我们正在动态生成 SQL,我宁愿不必更改我们的代码。
另一个解决方法是向数据库添加一个愚蠢的行,但这很混乱。
PS 主表是资产管理系统中的一个会话表,记录客户查找的资产。有不同类型的查找,每种类型都有一个单独的子表,此外还有一个属性子表,用于可以搜索的会话的键/值对。