我正在对数据库应用程序进行一些维护工作,并且我发现,欢乐的乐趣,即使来自一个表的值正在使用外键的样式,表上没有外键约束 .
我正在尝试在这些列上添加FK约束,但我发现,因为表中的错误数据已经完全加载了以前的错误,这些错误已经被天真地纠正过,我需要找到没有的行 . 匹配其他表,然后删除它们 .
我在网上找到了一些这种查询的例子,但它们似乎都提供了例子而不是解释,我不明白为什么它们起作用 .
有人可以向我解释如何构建一个查询,该查询返回在另一个表中没有匹配的所有行,以及它正在做什么,以便我可以自己进行这些查询,而不是为这个混乱中的每个表运行到SO没有FK约束?
8 回答
如何在两个表中选择没有匹配条目的行?
这是一个简单的查询:
关键点是:
LEFT JOIN
被使用;这将返回Table1
中的所有行,无论Table2
中是否存在匹配的行 .WHERE t2.ID IS NULL
条款;这将限制返回的结果只返回从Table2
返回的ID为空的行 - 换句话说Table2
中的 NO 记录来自Table1
的特定ID . 对于来自Table1
的所有记录,Table2.ID
将返回NULL,其中Table2
中的ID不匹配 .我会使用EXISTS表达式,因为它更强大,你可以更精确地选择你想加入的行,如果是
LEFT JOIN
你必须把连接表中的所有东西都拿走 . 它的效率可能与使用null测试的LEFT JOIN
的情况相同 .T2
是您要添加约束的表:并删除结果 .
表1有一个要添加外键约束的列,但foreign_key_id_column中的值并不都与表2中的id匹配 .
初始选择列出了table1中的id . 这些将是我们要删除的行 .
where语句中的'not in'子句将查询限制为只有foreign_key_id_column中的值不在表2 ID列表中的行 .
括号中的select语句将获得表2中所有id的列表 .
让我们有以下2个表(薪水和员工)
Now i want those records from employee table which are not in salary. 我们可以通过3种方式做到这一点 -
从不在其中的员工中选择*(在e.id = s.id中选择员工e内联合薪资的e.id)
在e.id = s.id中选择* from employee e left outer join salary s,其中s.id为null
在e.id = s.id中选择*来自员工e全外联合工资s,其中e.id不在(从工资中选择id)
我不知道哪一个是优化的(与@AdaTheDev相比)但是当我使用时,这个似乎更快(至少对我来说)
SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2
如果您想获得任何其他特定属性,您可以使用:
SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);
您可以选择 Views ,如下所示:
然后处理视图以选择或更新:
产生如下图所示的结果,即填写了非匹配列null .