【问题标题】:SQL INSERT without duplicate (no primary or unique keys)SQL INSERT 没有重复(没有主键或唯一键)
【发布时间】:2013-11-06 21:35:51
【问题描述】:

假设我有一个用于生成表 B 的表 A。我没有可用于 ON DUPLICATE KEY 的主键或唯一键。

我的表 B 有 3 列:A、B 和 C。

我想INSERT 这个只有当行已经不存在时。我可以确定该行是否存在是 A 和 B 的组合。我使用WHERE NOT EXISTS 语句来执行此操作。

INSERT INTO TableB
(A, B, C)
SELECT 
SUM(A),
SUM(B),
SUM(C)
FROM TableA
WHERE NOT EXISTS (SELECT * FROM TABLE B WHERE A=A AND B=B)
GROUP BY A, B

如果表 B 为空,则插入该行。但是,一旦表 B 有记录,即使表 B 中不存在行,也不会插入任何行。

【问题讨论】:

  • 为什么不使用UNIQUE(A, B, C)
  • @Fozi 因为 A 可以重复。 B 也可以如此重复,但只有两者的组合才是独一无二的。这是我使用的数据的性质。
  • Ant 这正是UNIQUE(A, B, C) 将为您做的事情;和UNIQUE(A) UNIQUE(B) UNIQUE(C)不一样。
  • 对不起,我看错了问题:应该是UNIQUE(A, B)
  • @Fozi 我不知道。你在这里提出了一个很好的观点。谢谢。

标签: mysql sql insert on-duplicate-key


【解决方案1】:

您应该在外部查询的列前面加上子查询中的别名:

INSERT INTO TableB (A, B, C)
  SELECT 
      SUM(A),
      SUM(B),
      SUM(C)
    FROM TableA ta
  WHERE NOT EXISTS (SELECT * FROM TableB tb WHERE tb.A=ta.A AND tb.B=ta.B)
  GROUP BY A, B

按照您的编写方式,您将表 TableB 中的值与 TableB 中的值(每一行与自身)进行比较,因此当您插入至少一行时,条件是“没有行是等于它自己”从来都不是真的。

【讨论】:

  • 但是这大大增加了我的查询的执行时间(从大约 0.1s 到 >10s)
  • @Wistar 当然可以!在您的版本中,当TableB 中至少有一行时,NOT EXISTS 条件永远不会满足,并且只需要来自TableB 的一条记录就使该条件失败。当您将其更改为正常工作时(从外部查询中检查表中的值),它必须检查所有行并查看它们是否都没有相同的值 - 它必须更慢(在TableB.A 上有一个复合索引会很好和TableB.B 列)。
  • 正如@Fozi 建议的那样,可能对表B 使用UNIQUE(A,B) 约束,然后使用ON DUPLICATE KEY UPDATE 可能更明智。
【解决方案2】:

我认为最好且更快的方法是在 A + B 上应用 UNIQUE 约束。

Alter TABLE TableB ADD CONSTRAINT unique_A_B UNIQUE(A,B);

然后使用ON DUPLICATE KEY UPDATE:

INSERT INTO TableB (A,B,C)
SELECT 
      SUM(A),
      SUM(B),
      SUM(C)
    FROM TableA 
GROUP BY A, B
ON DUPLICATE KEY UPDATE C=SUM(C);

出于示例目的,我更新了C,但我想在实际情况下,您希望使用Now() 更新行的更新时间戳。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2014-08-04
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多