使数据插入或更新(ON DUPLICATE KEY UPDATE)

Exisi 2023-02-01 12:10:34
Categories: Tags:
    • 如果要插入的行会导致UNIQUE索引或PRIMARY KEY中的值重复,则带有ON DUPLICATE KEY UPDATE子句的INSERT可以更新现有行。在MySQL 8.0.19及更高版本中,具有一个或多个可选列别名的行别名可以与ON DUPLICATE KEY UPDATE一起使用,以引用要插入的行。

     

    • MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新;如果插入的行数据与现有表中记录的唯一索引或者主键不重复,则执行新纪录插入操作。

     

    • 即数据库中存在某个记录时,执行这个语句会更新,而不存在这条记录时,就会插入数据。并且可以在数据插入后对数据进行二次更新操作

    语法

    INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]

    [INTO] <tbl_name>

    [PARTITION (partition_name [, partition_name] ...)]

    [(<colum_name> [, <colum_name>] ...)]

    [ON DUPLICATE KEY UPDATE <colum_name> = value

     | [row_alias.]<colum_name>

     | [tbl_name.]<colum_name>

     | [row_alias.]col_alias,

    [<colum_name> = value

     | [row_alias.]<colum_name>

     | [tbl_name.]<colum_name>

    •  | [row_alias.]col_alias],

    ];

     

    参数

    说明

    <tbl_name>

    数据表名

    <colum_name>

    数据列名

    row_alias

    数据行别名

    col_alias

    数据列别名

    LOW_PRIORITY

    如果您使用 LOW_PRIORITY 修饰符,则 INSERT 的执行会延迟,直到没有其他客户端正在从表中读取。这包括在现有客户端正在读取以及 INSERT LOW_PRIORITY 语句正在等待时开始读取的其他客户端。因此,发出 INSERT LOW_PRIORITY 语句的客户端可能要等待很长时间。

    LOW_PRIORITY 仅影响仅使用表级锁定的存储引擎(例如 MyISAMMEMORY MERGE)。

    LOW_PRIORITY 通常不应与 MyISAM 表一起使用,因为这样做会禁用并发插入

    HIGH_PRIORITY

    如果您指定 HIGH_PRIORITY,如果服务器是使用该选项启动的,它将覆盖 --low-priority-updates 选项的效果。它还会导致不使用并发插入

    HIGH_PRIORITY 仅影响仅使用表级锁定的存储引擎(例如 MyISAMMEMORY MERGE)。

    IGNORE

    如果使用 IGNORE 修饰符,则在执行 INSERT 语句时发生的可忽略错误将被忽略。如果没有 IGNORE,此类 INSERT 语句将因错误而中止。

     

    例如,如果没有 IGNORE,复制表中现有 UNIQUE 索引或 PRIMARY KEY 值的行会导致重复键错误并且语句被中止。使用 IGNORE,该行将被丢弃并且不会发生错误。忽略的错误会生成警告。

    IGNORE 对插入,分区表有类似的影响,其中没有找到与给定值匹配的分区。

     

    使用 INSERT IGNORE 时,对于包含不匹配值的行,插入操作会静默失败,但会插入匹配的行。使用 IGNORE,将无效值调整为最接近的值并插入;会产生警告,但语句不会中止。您可以使用 mysql_info() C API 函数确定实际插入表中的行数。

     

    您可以使用 REPLACE 而不是 INSERT 来覆盖旧行。在处理包含重复旧行的唯一键值的新行时,REPLACE INSERT IGNORE 对应:新行替换旧行而不是被丢弃。

    PARTITION (

    partition_name

    [, partition_name]

    )

    插入分区表时,您可以控制哪些分区和子分区接受新行。 PARTITION 子句采用逗号分隔的表的一个或多个分区或子分区(或两者)的名称列表。

    如果给定 INSERT 语句要插入的任何行与列出的分区之一不匹配,则 INSERT 语句将失败,并出现错误 Found a row not matching the given partition set

     

    • 下面两个语句会有相同的效果:

    示例

    INSERT INTO table (a,b,c)

    VALUES (1,2,3) 

    ON DUPLICATE KEY UPDATE c=c+1; 

     

    UPDATE table SET c=c+1 WHERE a=1;

     

    Query OK, 1 rows affected (0.15 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    示例

    INSERT INTO table (a,b,c)

    VALUES (1,2,3),(4,5,6) 

    ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

     

    Query OK, 1 rows affected (0.15 sec)

    Records: 0  Duplicates: 0  Warnings: 0

      • 如果是插入操作,受到影响行的值为1;如果更新操作,受到影响行的值为2;如果更新的数据和已有的数据一样(就相当于没变,所有值保持不变),受到影响的行的值为0

     

     

    来自 <https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html>