mysql的replace语句_MySQL的SQL语句 - 数据操作语句(11)- REPLACE 语句

REPLACE 语句

1. REPLACE [LOW_PRIORITY | DELAYED]

2. [INTO] tbl_name

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

4. [(col_name [, col_name] ...)]

5. { {VALUES | VALUE} (value_list) [, (value_list)] ...

6. |

7. VALUES row_constructor_list

8. }

9.

10. REPLACE [LOW_PRIORITY | DELAYED]

11. [INTO] tbl_name

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

13. SET assignment_list

14.

15. REPLACE [LOW_PRIORITY | DELAYED]

16. [INTO] tbl_name

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

18. [(col_name [, col_name] ...)]

19. {SELECT ... | TABLE table_name}

20.

21. value:

22. {expr | DEFAULT}

23.

24. value_list:

25. value [, value] ...

26.

27. row_constructor_list:

28. ROW(value_list)[, ROW(value_list)][, ...]

29.

30. assignment:

31. col_name = value

32.

33. assignment_list:

34. assignment [, assignment] ...

REPLACE 的工作方式与 INSERT 完全相同,只是如果表中的旧行与新行具有相同的主键或唯一索引值,则在插入新行之前将删除旧行。

REPLACE是SQL标准的MySQL扩展。它要么插入,要么删除并插入。

DELAYED 插入和替换在 MySQL 5.6 中被弃用了。在 MySQL 8.0 中,不支持 DELAYED。服务器识别但忽略 DELAYED 关键字,将替换作为非延迟替换处理,并生成 ER_WARN_LEGACY_SYNTAX_CONVERTED 警告。(“不再支持REPLACE DELAYED。语句已转换为REPLACE。“)在将来的版本中将删除 DELAYED 关键字。

注意

只有当表具有主键或唯一索引时,REPLACE 才有意义。否则,它就等价于INSERT,因为没有用于确定新行是否与另一行重复的索引。

所有列的值都取自 REPLACE 语句中指定的值。任何缺少的列都设置为其默认值,就像 INSERT 一样。不能引用当前行中的值并在新行中使用它们。如果使用诸如 SET col_name = col_name + 1 这样的赋值,那么右侧对列名的引用将被视为 DEFAULT(col_name),因此该赋值相当于 SET col_name = DEFAULT(col_name) + 1。

在 MySQL8.0.19 及更高版本中,可以使用 VALUES ROW() 指定要插入的列值。

要使用 REPLACE,必须同时具有表的 INSERT 和 DELETE 权限。

如果显式替换生成的列,则唯一允许的值是 DEFAULT。

使用 PARTITION 关键字和用逗号分隔的分区、子分区名称列表,REPLACE 支持显式的分区选择。与 INSERT 一样,如果无法将新行插入这些分区或子分区中,REPLACE 语句将失败,并返回错误:Found a row not matching the given partition set。

REPLACE 语句返回一个计数,指示受影响的行数。这是删除和插入的行的总和。如果单行 REPLACE 的计数为 1,则插入一行,但未删除行。如果计数大于 1,则在插入新行之前删除了一个或多个旧行。如果表包含多个唯一索引,并且新行与不同唯一索引中不同旧行的值重复,则一行可以替换多个旧行。

通过受影响的行数可以很容易地确定 REPLACE 是只添加了一行,还是还替换了某些行:检查计数是1(添加)还是更大(替换)。

如果在使用 C API,则可以使用 mysql_affected_rows() 函数获取受影响的行数。

不能在一个表中替换并在子查询中从同一表的中进行选择。

MySQL 使用以下算法用于 REPLACE(和 LOAD DATA ... REPLACE):

尝试将新行插入表中

由于主键或唯一索引发生重复键错误,插入失败时:

a. 从表中删除具有重复键值的冲突行

b. 再次尝试将新行插入表中

在出现键重复错误的情况下,存储引擎可能执行 REPLACE 来更新记录,而不是先删除再插入,但语义是相同的。除了存储引擎增加 Handler_xxx 状态变量的方式可能存在差异外,没有用户可见的影响。

由于 REPLACE ... SELECT 语句的结果取决于 SELECT 中的行的顺序,并且不能总是保证这种顺序,在源服务器和从服务器记录这些语句时,可能会出现分歧。因此,对于基于语句的复制,REPLACE ... SELECT 语句被标记为不安全。当使用基于语句的模式时,此类语句在错误日志中生成警告,在使用混合模式时,这些语句将使用基于行的格式写入二进制日志。

MySQL 8.0.19 及更高版本支持 TABLE 和 SELECT 与 REPLACE 一起使用,就像 INSERT 一样。

当修改未分区的现有表以适应分区时,或者修改已分区的分区表时,可以考虑更改表的主键。应该知道,如果这样做,REPLACE 语句的结果可能会受到影响,就像修改非分区表的主键一样。考虑由以下 CREATE TABLE 语句创建的表:

1. CREATE TABLE test (

2. id INT UNSIGNED NOT NULL AUTO_INCREMENT,

3. data VARCHAR(64) DEFAULT NULL,

4. ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

5. PRIMARY KEY (id)

6. );

当我们创建这个表并运行 mysql 客户端中显示的语句时,结果如下:

1. mysql> REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');

2. Query OK, 1 row affected (0.04 sec)

3.

4. mysql> REPLACE INTO test VALUES (1, 'New', '2014-08-20 8:47:42');

5. Query OK, 2 rows affected (0.04 sec)

6.

7. mysql> SELECT * FROM test;

8. +----+------+---------------------+

9. | id | data | ts |

10. +----+------+---------------------+

11. | 1 | New | 2014-08-20 18:47:42 |

12. +----+------+---------------------+

13. 1 row in set (0.00 sec)

现在我们创建了第二个表,与第一个表几乎相同,只是主键现在覆盖了2列,如下所示:

1. CREATE TABLE test2 (

2. id INT UNSIGNED NOT NULL AUTO_INCREMENT,

3. data VARCHAR(64) DEFAULT NULL,

4. ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

5. PRIMARY KEY (id, ts)

6. );

当我们在 test2 上运行与原始 test 表相同的两个 REPLACE 语句时,会得到不同的结果:

1. mysql> REPLACE INTO test2 VALUES (1, 'Old', '2014-08-20 18:47:00');

2. Query OK, 1 row affected (0.05 sec)

3.

4. mysql> REPLACE INTO test2 VALUES (1, 'New', '2014-08-20 18:47:42');

5. Query OK, 1 row affected (0.06 sec)

6.

7. mysql> SELECT * FROM test2;

8. +----+------+---------------------+

9. | id | data | ts |

10. +----+------+---------------------+

11. | 1 | Old | 2014-08-20 18:47:00 |

12. | 1 | New | 2014-08-20 18:47:42 |

13. +----+------+---------------------+

14. 2 rows in set (0.00 sec)

这是因为在 test2 上运行时,id 和 ts 列的值必须与要替换的行的值相匹配;否则,将插入一行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值