SQL INSERT ON DUPLICATE KEY - возвращает количество только вновь вставленных строк, а не количество вновь вставленных + обновленных строк?

Как я могу получить это? Я знаю, что могу сделать это, получив COUNT всех строк перед выполнением этого запроса на вставку, а затем вычтя его из COUNT всех строк после выполнения этого запроса на вставку, но это нецелесообразно для больших баз данных. Я также нашел эту формулу на stackoverflow.com

(numberOfValuesInInsert * 2) - mysql_affected_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, независимо от того, вставлена ​​ли запись или обновлена. И я прочитал здесь, что он должен возвращать 2 для каждой обновленной записи и 1 для вставленной. Получение количества строк, вставленных для ON DUPLICATE ОБНОВЛЕНИЕ КЛЮЧА множественная вставка?

У меня есть один ПК, это поле "id", если это что-то значит для вас.


person kecman    schedule 25.12.2015    source источник


Ответы (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 на mysql_affected_rows()

Выдержка:

Для инструкций INSERT ... ON DUPLICATE KEY UPDATE значение затронутых строк для каждой строки равно 1, если строка вставляется как новая строка, 2, если существующая строка обновляется, и 0, если для существующей строки устанавливаются ее текущие значения. . Если вы укажете флаг CLIENT_FOUND_ROWS, значение затронутых строк равно 1 (не 0), если для существующей строки установлены ее текущие значения.


А как насчет таблицы t3 в приведенной выше схеме?

Ну, если бы моя вставка stmt из файла PHP была бы

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

Тогда да, результаты были бы такими же. 1 при первом тестировании, затронутые строки = 2 после этого.


Какова точка столбца с именем timesHere?

Это нужно для того, чтобы доказать, что инкремент работает и произошло обновление.

person Drew    schedule 25.12.2015
comment
Меня не будет на моей рабочей станции до завтра, но, глядя на ваш ответ, похоже, что проблема в флаге CLIENT_FOUND_ROWS. Я использую require('mysql') в node.js. Я посмотрю, что я могу сделать завтра и отвечу. Спасибо за ваши усилия! - person kecman; 25.12.2015
comment
Это был флаг FOUND_ROWS, который нужно было добавить в переменную подключения. Теперь моя переменная подключения выглядит так: var connection = mysql.createConnection({ host: dbhost, user: dbuser, password: dbpassword, database: dbname, flags: '-FOUND_ROWS' }); И теперь при обновлении строки значение равно 2, при вставке 1 и при обновлении до текущих значений равно 0. - person kecman; 27.12.2015