删除一个表中存在而另一个表中不存在的数据?

Posted

技术标签:

【中文标题】删除一个表中存在而另一个表中不存在的数据?【英文标题】:Delete the data which exist in one table and not exist in the other one? 【发布时间】:2013-04-24 07:21:54 【问题描述】:

我想选择所有存在于特定表中但不存在于另一个表中的行来删除它们。

我编写了以下查询,但我得到两个表中都存在行!

SELECT  UNIQUE b.values_key FROM request_fo a INNER JOIN rm_trans  b 
ON b.values_key != a.req_year || ',' || a.req_ser
AND b.taskcode = 19
AND  b.values_key IS NOT NULL
AND a.req_year IS NOT NULL 
AND a.req_ser IS NOT NULL

我想用下面的方法删除request_fo中存在而rm_trans中不存在的数据:

DELETE request_fo 
FROM request_fo a
INNER JOIN
rm_trans  b 
ON b.values_key != a.req_year || ',' || a.req_ser
AND b.taskcode = 19
AND  b.values_key IS NOT NULL
AND a.req_year IS NOT NULL 
AND a.req_ser IS NOT NULL

是这样吗??

【问题讨论】:

不同的 DBMS 对 DELETE 操作有不同的语法,尤其是带有连接操作的 DELETE。您不能自然而然地期望 MS SQL Server 中有效的东西在 Oracle、DB2、Informix、mysql、PostgreSQL 中有效——它通常但不一定在 Sybase 中有效。 @JonathanLeffler:那请问DELETE a FROM request_fo a LEFT JOIN rm_trans b ON b.values_key = a.req_year + ',' + a.req_ser AND b.taskcode = 19 WHERE b.values_key IS NULL;informix的语法是什么 【参考方案1】:

如果您不能使用连接语法,您也可以使用子选择。

delete from t1
where t1 = something
and not exists
(
   select 1
   from t2
   where t1.key = t2.key
)

【讨论】:

【参考方案2】:

当您想要执行此类操作时,您必须进行综合思考。当您需要NOT IN (...)NOT EXISTS (...) 时,您正在使用!=

您的子句b.values_key != a.req_year || ',' || a.req_sera 中的每一行与b 中的每一行进行比较。在大多数情况下,它们不会等同。但是会有很多示例,其中此特定行中的values_keya 的其他行中的a.req_year || ',' || a.req_ser 匹配,而不是当前正在比较的行。这就是为什么返回的数据确实存在于两个表中。

你想尝试这样的事情:

DELETE FROM a
  WHERE NOT EXISTS (SELECT 1 FROM b
                    WHERE b.values_key = a.req_year || ',' || a.req_ser
                       AND b.task_code = 19)

您还应该将其作为SELECT * FROM a WHERE NOT EXISTS (...) 运行以首先验证它。我会的。

【讨论】:

【参考方案3】:

这是执行此操作的 T-SQL 语法:

改用LEFT JOIN,在WHERE子句中使用b.values_key IS NULL谓词,并在DELETE子句中使用别名a代替表名:

DELETE a 
FROM request_fo a
LEFT JOIN rm_trans  b  ON b.values_key = a.req_year + ',' + a.req_ser
                      AND b.taskcode = 19
WHERE  b.values_key IS  NULL;

在这里查看它的实际效果:

SQL Fiddle Demo

假设req_serreq_year 是字符串数据类型,如果它们是整数,则将它们强制转换。


它是如何工作的?

LEFT JOIN 将包括来自LEFT JOIN 左侧的第一个表request_fo 中的那些不匹配的行,即使没有满足JOIN 条件的条目,在这种情况下为values_key对于那些不匹配的行,值将是 NULL

例如,参见this demo,第一个表中的2013 4 在第二个表中不存在,因此它的values_key 将是NULL,因此添加WHERE b.values_key IS NULL 将为您提供找到的那些在第一个表中,在第二个表中找不到。

【讨论】:

为什么要设置b.values_key IS NULL ?!

以上是关于删除一个表中存在而另一个表中不存在的数据?的主要内容,如果未能解决你的问题,请参考以下文章

定义表中不存在时删除 jsonb 键

选择另一个表中不存在的值

如何获取另一个表中不存在的表的记录?

Delta Lake:如何在下一个版本的 delta 表中不携带已删除的记录?

SQLite查询选择另一个表中不存在的所有记录

HQL 左外连接用于查找一个表中存在而其他表中不存在的记录