我正在对一个数据库应用程序进行一些维护工作,我发现,最令人高兴的是,即使一个表的值以外键的样式使用,但表上没有外键约束。

我试图在这些列上添加FK约束,但我发现,因为在以前的错误中已经有大量坏数据,这些错误已经被天真地纠正了,所以我需要找到与另一个表不匹配的行,然后删除它们。

我在网上找到了一些这类查询的例子,但它们似乎都提供了例子而不是解释,我不明白为什么它们能起作用。

有人能向我解释一下如何构造一个查询,返回另一个表中没有匹配的所有行,以及它在做什么,这样我就可以自己进行这些查询,而不是对这个混乱中没有FK约束的每个表运行so ?


当前回答

我会使用EXISTS表达式,因为它更强大,你可以更精确地选择你想要加入的行。在LEFT JOIN的情况下,你必须获取连接表中的所有东西。它的效率可能与带有空约束的LEFT JOIN的情况相同。

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)

其他回答

如何在两个表中选择没有匹配条目的行?


    select * from [dbo].[EmppDetails] e
     right join [Employee].[Gender] d on e.Gid=d.Gid
    where e.Gid is Null

    union 
    select * from [dbo].[EmppDetails] e
     left join [Employee].[Gender] d on e.Gid=d.Gid
    where d.Gid is Null

我不知道哪个是优化的(与@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);

我们有以下两张表(工资和员工)

现在我想要员工表中不包含工资的那些记录。 我们可以通过三种方式做到这一点:

使用内部连接

select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)

使用左外连接

select * from employee e 
left outer join salary s on e.id=s.id  where s.id is null

使用完全连接

select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)

SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)

表1有一个列,您希望向其中添加外键约束,但是foreign_key_id_column中的值并不都与表2中的id匹配。

初始选择列出了table1中的id。这些就是我们要删除的行。 where语句中的NOT IN子句将查询限制为foreign_key_id_column中的值不在表2 id列表中的行。 括号中的SELECT语句将获得表2中所有id的列表。

我会使用EXISTS表达式,因为它更强大,你可以更精确地选择你想要加入的行。在LEFT JOIN的情况下,你必须获取连接表中的所有东西。它的效率可能与带有空约束的LEFT JOIN的情况相同。

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)