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

SQL INSERT ... ON DUPLICATE KEY - return number of only newly inserted rows, not number of newly inserted + updated rows?

我怎样才能得到这个?我知道我可以通过在 运行 这个插入查询之前获取所有行的 COUNT 来做到这一点,然后从 运行 这个插入查询之后的所有行的 COUNT 中减去它,但这对于大数据库来说并不实用。我还在 whosebug.com

上找到了这个公式
(numberOfValuesInInsert * 2) - mysql_affected_rows()

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

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

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,无论是插入还是更新记录。我在这里读到它应该 return 2 用于每个更新的记录,1 用于插入。 Getting number of rows inserted for ON DUPLICATE KEY UPDATE multiple insert?

我有一个PK,就是"id"字段,如果这对你有意义的话。

记录架构很重要。考虑以下因素。

架构

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);

如果我 运行 以上,它将始终 return 受影响的行为 1,因为我没有在索引中插入重复值,这会导致唯一键冲突。

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

但是如果我要修改PHP并使用table t2,那么第一个运行会受到影响rows=1,此后相同数据影响行数=2


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


CLIENT_FOUND_ROWS 标志的值也可以影响它。请参阅以下内容link。

Mysql mysql_affected_rows()

上的手册页

节选:

For INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag, the affected-rows value is 1 (not 0) if an existing row is set to its current values.


上面架构中的 table t3 呢?

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

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

那么是的,结果应该是一样的。 1 第一次测试,此后受影响的行数=2。


名为 timesHere 的列有什么意义?

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