【问题标题】:How to INSERT INTO...SELECT with ON DUPLICATE KEY如何使用 ON DUPLICATE KEY 插入...选择
【发布时间】:2013-02-05 05:18:25
【问题描述】:

我有两个结构相同的表。表 A 包含所有当前广告,表 B 包含存档广告。第 1 列 (ad_id) 是主键、AI、INT。表引擎是 MyISAM。

我需要将某个日期之前的所有表 A 广告复制到存档表 B。我的目标是复制除 ad_id 之外的所有字段,ad_id 应该自动递增。这是我尝试过的:

INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`) 
    SELECT *
    FROM A
    WHERE YEAR( ad_expire ) <= 2012

表 B 有数以千计的广告,表 A 经常被刷新,以至于唯一 id 字段的数字很少,经常与表 B 中的 id 重复。所以 MySQL 摇摇晃晃地告诉我我有一个 Duplicate entry '8577' for key 'PRIMARY'

所以我做了几次尝试来克服这个问题:

首先,我尝试选择要插入的各个列,将 ad_id 设置为 NULL:

INSERT INTO B(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`) 
    SELECT (NULL, `ad_advertiser`, `ad_ln`, `ad_expire`)
    FROM A
    WHERE YEAR( ad_expire ) <= 2012 

这会导致错误 #1241 - Operand should contain 1 column(s),如果我使用通配符 * 选择器,该错误就会消失,但随后会出现重复错误。

接下来我尝试了SELECT LAST_INSERT_ID(),它总是返回0。

然后我尝试了一些使用ON DUPLICATE KEY UPDATE,但我似乎无法让它工作。

我什至试图通过以下方式获取最高 id:

SELECT @max := max(ad_id) FROM B;

INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`) 
  SELECT *
  FROM A
  WHERE YEAR( ad_expire ) <= 2012

ON DUPLICATE KEY UPDATE ad_id = @max + 1

这仅适用于一行,然后再次导致重复条目(因为@max 是静态变量)。

我在这里做错了什么?我这样做是不是太难了?

【问题讨论】:

  • 你刷新表的方式,为什么不保持当前id的最大值? (delete from A 应该够了)

标签: mysql insert-into on-duplicate-key select-into


【解决方案1】:

在你的情况下为什么不使用?

INSERT INTO B(`ad_advertiser`, `ad_ln`, `ad_expire`) 
    SELECT (`ad_advertiser`, `ad_ln`, `ad_expire`)
    FROM A
    WHERE YEAR( ad_expire ) <= 2012 

【讨论】:

  • 此查询结果为#1241 - Operand should contain 1 column(s)。我实际上有 32 个相同的列,为了简洁起见,我缩短了示例。原来还有 5 个其他 KEY 列用于索引目的,这可能是问题吗?
  • 我从 SELECT 子句中删除了括号,它起作用了。感谢这篇文章:link
【解决方案2】:

您可以在您的ad_id 或您的table B 上删除主键约束 使用以下命令。

ALTER TABLE B DROP PRIMARY KEY

然后尝试您通常的查询,即

INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`) 
    SELECT *
    FROM A
    WHERE YEAR( ad_expire ) <= 2012

更新 1

如果你不想有多个ad_id,那么你可以直接试试这个查询

   INSERT INTO `B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`) 
    SELECT *
    FROM A
    WHERE YEAR( ad_expire ) <= 2012
   ON DUPLICATE KEY UPDATE
    ad_advertiser = VALUES(ad_advertiser), 
    ad_ln = VALUES(ad_ln), 
    ad_expire = VALUES(ad_expire);

这里是SQL Fiddle

【讨论】:

  • 嗯,这会导致重复的 id 列,对吗?不确定对应用程序有什么影响。值得一试的副本我想...
猜你喜欢
  • 1970-01-01
  • 2018-04-07
  • 2010-10-21
  • 2014-06-05
  • 2018-05-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 2011-02-12
相关资源
最近更新 更多