我对重复更新查询中的插入很困惑.我有MySQL表,结构如下:
如果我的table.person中存在id,或者在此表中插入新记录,我想为person更新some_text和some_other_text值.如果person_id不是PRIMARY,怎么办呢?
Lor*_*nzi 12
您需要一个查询,检查是否存在与record_id(或person_id)相关的任何行.如果存在更新它,否则插入新行
IF EXISTS (SELECT * FROM table.person WHERE record_id='SomeValue')
UPDATE table.person
SET some_text='new_some_text', some_other_text='some_other_text'
WHERE record_id='old_record_id'
ELSE
INSERT INTO table.person (record_id, person_id, some_text, some_other_text)
VALUES ('new_record_id', 'new_person_id', 'new_some_text', 'new_some_other_text')
Run Code Online (Sandbox Code Playgroud)
另一个更好的方法是
UPDATE table.person SET (...) WHERE person_id='SomeValue'
IF ROW_COUNT()=0
INSERT INTO table.person (...) VALUES (...)
Run Code Online (Sandbox Code Playgroud)
你的问题非常有效.这是一个非常常见的要求.由于MySQL提供的功能,大多数人都会弄错.
PRIMARY
密钥存在,否则更新.ON DUPLICATE KEY UPDATE
PRIMARY
或任何UNIQUE
密钥,否则更新!什么可以发生可怕的错误ON DUPLICATE KEY UPDATE
?您使用新的PRIMARY
键值(例如UUID)插入一个所谓的新记录,但您的UNIQUE
密钥恰好有一个重复值.
你想要的是一个正确的例外,表明你试图将一个副本插入一UNIQUE
列.
但你得到的是一个不需要的UPDATE
!MySQL将采用冲突记录并开始覆盖其值.如果这种情况无意中发生,则您已经删除了旧记录,并且对旧记录的任何传入引用现在都引用了新记录.由于您可能不会告诉查询更新PRIMARY
列,因此无法找到新的UUID.如果您遇到这些数据,它可能没有任何意义,您将不知道它来自何处.
我们需要一个实际 插入PRIMARY
的解决方案,除非密钥存在,否则更新.
我们将使用包含两个语句的查询:
PRIMARY
键值匹配的位置(影响0或1行).PRIMARY
键值不存在则插入(插入1或0行).这是查询:
UPDATE my_table SET
unique_name = 'one', update_datetime = NOW()
WHERE id = 1;
INSERT INTO my_table
SELECT 1, 'one', NOW()
FROM my_table
WHERE id = 1
HAVING COUNT(*) = 0;
Run Code Online (Sandbox Code Playgroud)
这些查询中只有一个会产生影响.这UPDATE
很容易.至于INSERT
:WHERE id = 1
如果id存在则产生一行,如果不存在则没有行.HAVING COUNT(*) = 0
如果id是新的,则反转该行,如果已经存在则不生成行.
我已经探索了相同想法的其他变体,例如使用LEFT JOIN
和WHERE
,但它们看起来更复杂.欢迎改进.
13.2.5.3 INSERT ... ON DUPLICATE KEY UPDATE语法
如果指定ON DUPLICATE KEY UPDATE,并且插入的行将导致UNIQUE索引或PRIMARY KEY中出现重复值,则MySQL将执行旧行的UPDATE.
例:
DELIMITER //
DROP PROCEDURE IF EXISTS `sp_upsert`//
DROP TABLE IF EXISTS `table_test`//
CREATE TABLE `table_test` (
`record_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`person_id` INT UNSIGNED NOT NULL,
`some_text` VARCHAR(50),
`some_other_text` VARCHAR(50),
UNIQUE KEY `record_id_index` (`record_id`),
UNIQUE KEY `person_id_index` (`person_id`)
)//
INSERT INTO `table_test`
(`person_id`, `some_text`, `some_other_text`)
VALUES
(1, 'AAA', 'XXX'),
(2, 'BBB', 'YYY'),
(3, 'CCC', 'ZZZ')//
CREATE PROCEDURE `sp_upsert`(
`p_person_id` INT UNSIGNED,
`p_some_text` VARCHAR(50),
`p_some_other_text` VARCHAR(50)
)
BEGIN
INSERT INTO `table_test`
(`person_id`, `some_text`, `some_other_text`)
VALUES
(`p_person_id`, `p_some_text`, `p_some_other_text`)
ON DUPLICATE KEY UPDATE `some_text` = `p_some_text`,
`some_other_text` = `p_some_other_text`;
END//
DELIMITER ;
mysql> CALL `sp_upsert`(1, 'update_text_0', 'update_text_1');
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT
-> `record_id`,
-> `person_id`,
-> `some_text`,
-> `some_other_text`
-> FROM
-> `table_test`;
+-----------+-----------+---------------+-----------------+
| record_id | person_id | some_text | some_other_text |
+-----------+-----------+---------------+-----------------+
| 1 | 1 | update_text_0 | update_text_1 |
| 2 | 2 | BBB | YYY |
| 3 | 3 | CCC | ZZZ |
+-----------+-----------+---------------+-----------------+
3 rows in set (0.00 sec)
mysql> CALL `sp_upsert`(4, 'new_text_0', 'new_text_1');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT
-> `record_id`,
-> `person_id`,
-> `some_text`,
-> `some_other_text`
-> FROM
-> `table_test`;
+-----------+-----------+---------------+-----------------+
| record_id | person_id | some_text | some_other_text |
+-----------+-----------+---------------+-----------------+
| 1 | 1 | update_text_0 | update_text_1 |
| 2 | 2 | BBB | YYY |
| 3 | 3 | CCC | ZZZ |
| 5 | 4 | new_text_0 | new_text_1 |
+-----------+-----------+---------------+-----------------+
4 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17235 次 |
最近记录: |