SQL INSERT ... ON DUPLICATE KEY - 仅返回新插入行的数量,而不是新插入的行数+更新的行数?

时间:2015-12-25 06:16:13

标签: mysql node.js sql-insert on-duplicate-key

我怎么能得到这个?我知道我可以通过在运行此Insert查询之前获取所有行的COUNT来执行此操作,然后在运行此Insert查询后从所有行的COUNT中减去它,但这对大型数据库来说并不实用。我还在stackoverflow.com上找到了这个公式

(numberOfValuesInInsert * 2) - mysql_affected_rows()

但它似乎对我不起作用,因为无论是否更新或插入新行,我都会受到影响的行= 1

这是在FOR循环中运行的我的node.js代码,所以在循环结束后我得到受影响行的总和:

var sql = "INSERT INTO classdata (id, siteid, name, staff, locationname, start, end) VALUES ?
ON DUPLICATE KEY UPDATE 
siteid=VALUES(siteid), name=VALUES(name), staff=VALUES(staff), locationname=VALUES(locationname), start=VALUES(start), end=VALUES(end)";
var values = [[id, siteId, name, staff, locationName, start,end]];

connection.query(sql, [values],function(err, results) {
            if (!err) {console.log(new Date() + " : New data sucessfully inserted into classdata table. Affected rows: " + results.affectedRows);}});
affectedrows+= results.affectedRows;

它总是打印受影响的行:1,无论是否插入或更新记录。我在这里读到它应该为每个更新的记录返回2,并为插入1。 Getting number of rows inserted for ON DUPLICATE KEY UPDATE multiple insert?

我有一个PK,如果这对你意味着什么,那就是“id”字段。

1 个答案:

答案 0 :(得分:1)

记录架构很重要。请考虑以下事项。

模式

create table t1
(   id int auto_increment primary key,
    thing varchar(100) not null,
    timesHere int not null
);

create table t2
(   id int auto_increment primary key,
    thing varchar(100) not null,
    timesHere int not null,
    unique key(thing)
);

create table t3
(   id int auto_increment primary key,
    thing varchar(100) not null,
    timesHere int not null
);

和这个PHP (注意我使用旧的mysql函数来演示,而不是我会使用该库)

但是,它的mysql_affected_rows函数与你的名字相符。

PHP示例

<?php
    error_reporting(E_ALL); 
    ini_set('display_errors', 1);
    $dbname = 'so_gibberish';
    $dbuser = 'myuser';
    $dbpass = 'mypassword';
    $dbhost = 'localhost';
    $link = mysql_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
    mysql_select_db('so_gibberish') or die("Could not open the db");
    $test_query = "insert t1(thing,timesHere) values ('frog',1) on duplicate key update timesHere=timesHere+1";
    $result = mysql_query($test_query) or die(mysql_error());
    $numrows=mysql_affected_rows($link);
    echo "affected rows=".$numrows."<br/>";
    mysql_close($link);

如果我运行上述操作,它将始终为受影响的行返回1,因为我没有在索引中插入重复值,从而导致唯一的键冲突。

请记住,这是导致更新触发的唯一键冲突,而不是连续插入行。

但是如果我要修改PHP并使用表t2,那么第一次运行会受到行= 1的影响,之后会有相同的数据受影响行= 2

无论您的实际客户端代码是什么,如果您对模式有敏锐的洞察力,您应该看到这些结果

CLIENT_FOUND_ROWS标志的值也可以考虑其中的因素。请参阅以下链接。

mysql_affected_rows()

上的Mysql手册页

摘录:

  

对于INSERT ... ON DUPLICATE KEY UPDATE语句,受影响的行   如果将行作为新行插入,则每行的值为1;如果是,则为2   更新现有行,如果现有行设置为更新,则为0   当前价值。如果指定CLIENT_FOUND_ROWS标志,则   如果将现有行设置为,则af​​fected-rows值为1(不为0)   当前价值。

上面架构中的表t3怎么样?

好吧,如果我从PHP文件中插入stmt是

$test_query = "insert t3(id,thing,timesHere) values (1,'frog',1) on duplicate key update timesHere=timesHere+1";

然后是的,结果会是一样的。 1第一次测试,受影响的行= 2。

名为timesHere的列有什么意义?

那就是证明增量有效并且更新发生了。