[英]SQL - Check table for new rows?
我有两个表,例如:
Table A Table B
======= =======
Name | Color Name | Color
---------------------- ----------------------
Mickey Mouse | red Mickey Mouse | red
Donald Duck | green Donald Duck | blue
Donald Duck | blue Minnie | red
Goofy | black
Minnie | red
表 A 是我的源表,B 是目标表。 现在我需要一个查询来查找表 A 中所有不同(附加)的行,以便可以用这些行更新表 B。 所以我需要一个查询来从表 A 中找到以下行:
Name | Color
----------------------
Donald Duck | green
Goofy | black
这种查询的好方法是什么? 它应该尽可能高效(避免太多连接)。 谢谢你的帮助!
我会使用 NOT EXISTS 结构。
SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
SELECT 1 FROM TableB
WHERE TableA.Name = TableB.Name
AND TableA.Color = TableB.Color)
SELECT a.Name, a.Color
FROM a LEFT OUTER JOIN b ON (a.Name = b.Name AND a.Color = b.Color)
WHERE b.Name IS NULL AND b.Color IS NULL
Select A.Name, A.Color
From A left join B on A.Name = B.Name and A.Color = B.Color
Where B.Name is null
在 SQL Server 2008 中,您可以使用EXCEPT
运算符,它的用法类似于UNION
但返回第一个查询中的所有内容,除了它也在第二个查询中:
SELECT * FROM TABLEA EXCEPT SELECT * FROM TABLEB
我知道 Oracle 有一个MINUS
运算符可以做同样的事情。
您可以使用 EXCEPT 运算符,它与 UNION 相反。 在 Oracle 中,相当于 MINUS。
SELECT * FROM TABLE_A
EXCEPT
SELECT * FROM TABLE_B
我通常添加一列“updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP”,我使用它的值来检查何时插入新行或修改现有行。
在我开发的一个应用程序中,我需要解决一个与您类似的问题,所以我将 B 的 MAX(updated) 保存在某处,然后通过查询识别出 A.updated>B.updated 的所有行,结果是所有新的+修改的行。
由于字段默认值为 CURRENT_TIMESTAMP 并且它会自动更新“ON UPDATE”,因此您无需明确设置其值。
NOT EXISTS
子查询应该解析为外连接:
SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
SELECT 1
FROM TableB
WHERE TableA.Color = TableB.Color
AND TableA.Name = TableB.Name
)
或者您可以直接使用外连接:
SELECT TableA.Name, TableA.Color
FROM TableA
LEFT OUTER JOIN TableB
ON TableA.Name = TableB.Name
AND TableA.Color = TableB.Color
WHERE TableB.Name IS NULL
它们的性能应该相同; 这是一个你觉得更直观的问题。
已经有很多正确的答案,但我想提出一个哲学观点:
这个数据库模式在单个模式内的生产环境中真的可行吗?
有两个包含数据的表,然后编写一个查询来比较一个和另一个真的有意义吗? 我认为只有一个表是有意义的,也许可以输入一个日期标识符来查找在某个点之后添加的记录。
我能想到的唯一情况是你有两个独立的数据库并且你想要“同步”它们,或者当你想要找到两者之间的差异时,比如比较备份和生产.
在 Oracle 中,您可能会使用:
MERGE INTO b USING
(SELECT name, color
FROM a) src
ON (src.name = b.name AND color = src.color)
WHEN NOT MATCHED THEN
INSERT (name, color)
VALUES (src.name, src.color);
如果你的表有一个主键(你真的有没有一个的表吗?)比如 NAME,并且你想根据表 B 中记录的存在来插入或更新,你可以使用:
MERGE INTO b USING
(SELECT name, color
FROM a) src
ON (src.name = b.name)
WHEN NOT MATCHED THEN
INSERT (name, color)
VALUES (src.name, src.color)
WHEN MATCHED THEN
UPDATE
SET color = src.color;
我认为 SQL Server 也有一个 MERGE 语句或类似的语句。
SELECT TableA.Name, TableA.Color FROM TableA WHERE TableA.Name + TableA.Color NOT IN (SELECT TableB.Name + TableB.Color FROM TableB)
INSERT INTO B
SELECT a.Name, a.Color
FROM A a
LEFT JOIN B b ON a.Name = b.Name AND a.Color = b.Color
WHERE b.Color IS NULL AND b.Name IS NULL
select
name,
color
from
tableA
where
concat(name, '|',color)
not in
(
select
concat(name, '|',color)
from
tableB
)-- not in
工作腼腆可以在db fiddle找到
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.