我需要一些 SQL 来更新数据库中的记录(如果存在)并在不存在时插入它,环顾四周似乎有几种解决方案,但我不知道什么是正确/可接受的方法来做到这一点。
理想情况下,我希望它可以在 Firebird 2 和 MySQL 5 上运行,因为需要对两个数据库运行更新,如果在两个数据库上运行相同的 SQL 会更简单,如果它可以在更多数据库上运行,那将是一个加号.
速度和可靠性也是考虑因素,在这种情况下可靠性超过速度,但它可能用于快速连续更新 1000 条记录(在不同的表上)。
有什么服从吗?
在 Firebird 2.1 中,您可以使用UPDATE OR INSERT处理简单的情况,或者使用MERGE处理更复杂的情况。
你应该使用这样的东西:
BEGIN TRANSACTION
IF EXISTS (SELECT * FROM the_table WHERE pk = 'whatever')
UPDATE the_table SET data = 'stuff' WHERE pk = 'whatever'
ELSE
INSERT INTO the_table (pk, data) VALUES ('whatever', 'stuff')
COMMIT
或者这个,但是单独发送它们并忽略来自 INSERT 的任何关于违反主键约束的错误:
INSERT INTO the_table (pk, data) VALUES ('whatever', 'stuff')
UPDATE the_table SET data = 'stuff' WHERE pk = 'whatever'
在 2.1 之前的 firebird 中,您可以使用这种棘手的方法:
insert into table (id, a, b, c) values (:id, :a, :b, :c)
when SQLCODE -803
do
begin
update table set a = :a, b = :b, c = :c where id = :id;
end;
对于 MySQL,请尝试以下REPLACE
命令:http ://dev.mysql.com/doc/refman/5.0/en/replace.html
(有关 Firebird 的等价物,请参阅 Milan Babuskov 对此答案的评论。)
REPLACE 的工作方式与 INSERT 完全相同,只是如果表中的旧行与 PRIMARY KEY 或 UNIQUE 索引的新行具有相同的值,则在插入新行之前删除旧行。
句法 :
替换 [LOW_PRIORITY | 延迟] [进入] tbl_name [(col_name,...)]
{ VALUES | VALUE}
({expr | DEFAULT},...),(...),...
鉴于:使用约束时最好避免 REPLACE。
我在MySQL中使用 INSERT来更新行:
INSERT INTO table () VALUES () ON DUPLICATE KEY UPDATE key
但是你不能使用自动生成的键。