MySQL - 如何在批量INSERT ON DUPLICATE KEY UPDATE查询中计算INSERT和UPDATES?

时间:2015-06-17 02:06:08

标签: mysql

我有一个执行批量INSERT的MySQL查询,并使用ON DUPLICATE KEY UPDATE来更新行,以防有唯一的密钥重复。

INSERT INTO table1
    (col1,col2,col3)
    VALUES 
    (val1,val2,val3),
    (val4,val5,val6),
    (val7,val8,val9),
    ...
    (valn,valx,valz)
    ON DUPLICATE KEY UPDATE
    col3 = VALUES(col3);

换句话说,除非存在重复的唯一键,否则会插入新行,在这种情况下会更新col3。

查询完成后,我想知道INSERTED有多少行以及UPDATED有多少行。这可能吗?

3 个答案:

答案 0 :(得分:2)

不,从rows_affected计数中没有明确的判断方法。我们可以告诉一些极端情况......如果rows_affected正好是我们尝试插入的行数的两倍,我们知道它们都是更新。如果rows_affected计数为零,我们知道没有插入任何行。如果rows_affected计数为1,我们知道插入了一行。但除此之外,还有很多排列。

有可能制作BEFORE INSERTBEFORE UPDATE触发器来增加用户定义的变量。如果我们在INSERT ... ON DUPLICATE KEY UPDATE语句之前立即初始化用户定义的变量,我们可以组合使用这些变量来确定我们尝试插入的行数,以及这些行中有多少导致重复键异常。 (对于没有对该行进行实际更新的UPDATE操作,MySQL不会增加rows_affected。)

修改

如果您保证UPDATE操作将导致对行的实际更改...如果您要更改每行上至少一列的值,对于每个更改的行...以及如果您计算您尝试插入的实际行数,然后您可以从rows_affected中确定插入了多少行,以及更新了多少行。

INSERT ... ON DUPLICATE KEY可以导致插入和更新同一行,和/或导致同一行多次更新。

您是否需要计算“更新”操作的数量,包括对同一行的更新,或者您是否希望计算更新的表中的行数?

答案 1 :(得分:2)

扩展hakkikonu的答案,并先阅读它,否则根本就没有意义......

并同意@ spencer7593的评论,例如"使用lock"进行并发查杀(CK)操作, 并且需要在hak的答案中确定用于确定更新计数的公式

我认为如果没有CK,我无法获得准确的插入和更新计数。投掷AFTER触发器 肯定没有帮助解决它没有 CK,"单独并且同时准确"。

是一个可以为null的table1.blabla列,只用于对table1的批处理,无论频率如何 这些批次。如果批处理没有针对table1运行,则即使未删除该列,也保证blabla为null。这是显而易见的。

我相信你可以获得插入和更新计数 准确。这是基于您的Insert语句的方式。

table1具有专用于批处理代码的写锁定。让我们假设MyISAM存储引擎。嘿,为什么不,我们 在这里做出假设。 blabla列显示null' inserted'并且'更新了'根据你的陈述(与Hakkikonu建议的几乎不同)。  你有自己的数量。

关于spencer在他的答案中写的关于基于的给定行的更新和/或插入不止一次的内容 你的问题的插入声明,我不这么认为。除非您的批次数据中包含重复的密钥,否则无论如何,准确性至关重要。

根据打开ON DUPLICATE KEY的内容,行是否存在开头。如果它扔了它,它是一个更新, 如果没有,请插入。有人纠正我。

然后在结束时执行alter table drop blabla或更新为null。锁被释放。

所以我想更新和插入计数,表的大小以及批次的频率有多重要。

答案 2 :(得分:0)

添加一个类似 blabla 的新列,并将其作为默认值提供null。 我假设,你只会使用一次。

然后

ON DUPLICATE KEY UPDATE
    col3   = VALUES(col3),
    blabla = 'up' ;

SELECT count(blabla) as allrows FROM table1;                      # returns all rows count
SELECT count(blabla) as updrows FROM table1 WHERE blabla = 'up';  # returns update count
SELECT count(blabla) as insrows FROM table1 WHERE blabla IS NULL; # returns inserts