5

我需要一些 SQL 来更新数据库中的记录(如果存在)并在不存在时插入它,环顾四周似乎有几种解决方案,但我不知道什么是正确/可接受的方法来做到这一点。

理想情况下,我希望它可以在 Firebird 2 和 MySQL 5 上运行,因为需要对两个数据库运行更新,如果在两个数据库上运行相同的 SQL 会更简单,如果它可以在更多数据库上运行,那将是一个加号.

速度和可靠性也是考虑因素,在这种情况下可靠性超过速度,但它可能用于快速连续更新 1000 条记录(在不同的表上)。

有什么服从吗?

4

6 回答 6

6

在 Firebird 2.1 中,您可以使用UPDATE OR INSERT处理简单的情况,或者使用MERGE处理更复杂的情况。

于 2008-12-05T15:12:41.410 回答
3

你应该使用这样的东西:

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'
于 2008-12-05T11:51:59.020 回答
2

在 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;
于 2009-07-24T20:06:52.887 回答
1

对于 MySQL,请尝试以下REPLACE命令:http ://dev.mysql.com/doc/refman/5.0/en/replace.html

(有关 Firebird 的等价物,请参阅 Milan Babuskov 对此答案的评论。)

于 2008-12-05T11:36:09.960 回答
0

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

句法 :

替换 [LOW_PRIORITY | 延迟] [进入] tbl_name [(col_name,...)]

{ VALUES | VALUE} 

({expr | DEFAULT},...),(...),...

鉴于:使用约束时最好避免 REPLACE。

于 2008-12-05T11:40:49.120 回答
0

我在MySQL中使用 INSERT来更新行:
INSERT INTO table () VALUES () ON DUPLICATE KEY UPDATE key
但是你不能使用自动生成的键。

于 2008-12-05T12:17:16.100 回答