节点 Mysql On Duplicate Key Update 仅更新唯一行

Node Mysql On Duplicate Key Update only updates unique row

我正在使用 MySQL 5.7Node JS 6.11.0 并且正在尝试更新 UNIQUE MySQL 列,每当我插入一个冲突的行。但是,当我尝试插入冲突记录时,只有现有记录会更新为 NULL,而不会发生 insert。这是我的代码

     pool.getConnection(function(err, connection) {
        var newClass = req.body;
        var query = `INSERT INTO classes SET ? ON DUPLICATE KEY UPDATE teacher_id = NULL`;

        connection.query(query, newClass, function(err, result) {   
            console.log(result);
            if(result.affectedRows >= 1) {
                res.status(201).end();
                res.json(result);
            }
        });
        connection.release();
    });`

我必须运行查询两次才能插入行;第一次将冲突列设置为空,然后当我再次 运行 相同的查询时,由于没有冲突,该行被插入。

我已经从 MySql 控制台获取 SQL 生成并直接 运行 它,我仍然需要 运行 查询两次才能插入新行.我不明白为什么它会这样。

Sql statement is

INSERT INTO classes SET `stream` = 'Red', `form` = '1', `teacher_id` = '7' ON DUPLICATE KEY UPDATE teacher_id = NULL

我创建的 table SQL 是

| classes | CREATE TABLE `classes` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `form` varchar(10) NOT NULL,
      `stream` varchar(15) NOT NULL,
      `teacher_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `teacher_id` (`teacher_id`),
      CONSTRAINT `classes_ibfk_1` FOREIGN KEY (`teacher_id`) REFERENCES `teachers` 
      ( `id` ) 
   ) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1 |`

为什么 MySQL 会这样?

INSERT INTO classes
        SET stream = 'Red', form = '1',teacher_id = '7'
    ON DUPLICATE KEY UPDATE teacher_id = NULL;

告诉 MySQL 当存在冲突记录(重复的唯一或主键)时,将违规行的 teacher_id 列设置为 null 并停止。

您有几个选项可以达到您想要的结果。

首先你可以使用REPLACE语法。

REPLACE INTO classes SET stream = 'Red', form = '1', teacher_id = '7';

这将首先删除具有 UNIQUE 或主键约束的违规行,然后插入具有指定值的新行。缺点是任何省略的列值都将丢失并设置为其默认值。如果未在查询中指定,也将创建一个新的自动生成的(如果有的话)id。 如果没有违规记录,将发生正常 INSERT

否则,您可以在 UPDATE 子句中使用 VALUES

INSERT INTO classes
        SET stream = 'Red', form = '1', teacher_id = '7'
    ON DUPLICATE KEY UPDATE stream = VALUES(stream),
                            form   = VALUES(form);

这会将违规行的记录更新为查询的 INSERT 部分中指定的值。

参考文献:


根据新意图更新

为了在离开前一行的同时创建新记录,您需要先使现有行上的 UNIQUE 约束失效,然后再使用 INSERT。 目前没有在单个查询中使用 MySQL 执行此操作的方法。

由于 INSERT 的限制,完成您需要的最简单方法是 运行 在 INSERT 查询之前进行 UPDATE 查询。

UPDATE classes 
   SET teacher_id = NULL
   WHERE teacher_id = '7';
INSERT INTO classes
   SET stream = 'Red', 
   form = '1',
   teacher_id = '7';

这将首先检查冲突的 teacher_id 记录并将其设置为 null。如果不存在冲突记录,则不会发生更新。随后的 INSERT 将创建所需的记录,而不会发生冲突。

如果你想根据条件插入数据试试这个

INSERT INTO table1 SELECT 'Red',1,7 FROM table2 where teacher_id IS NULL;

否则,如果您想根据此尝试进行更新。

update table1 SET stream = 'Red', form = '1', teacher_id = '7' where teacher_id IS NULL;

注意:NULL = NULL 并不是真正的 FALSE - 它又是 NULL。但它也不是 TRUE,所以 IF(NULL = NULL) 不会执行 例如,NULL 甚至会针对 NULL 本身测试 FALSE。因此,使用 NULL 只能通过上述函数(和 IS NULL())完成。您的查询可以改写为如上。