我在寻找一个标准的SQL“ UPSERT
”语句。 如果是存在一个呼吁插入和更新。
我在找工作,高效,跨平台通话。
我见过MERGE
, UPSERT
, REPLACE
, INSERT .. ON DUPLICATE UPDATE
,但没有声明满足需求。
BTW我用MYSQL和HSQLDB的unitests。 据我所知,HSQLDB是有限的,可能不包括我所需要的,但即使没有它,我无法找到一个标准的方式。 声明只有MYSQL和HSQLDB也将为现在是不够的。
我一直在寻找了一段时间,无法得到答案。
我的表:
CREATE TABLE MY_TABLE (
MY_KEY varchar(50) NOT NULL ,
MY_VALUE varchar(50) DEFAULT NULL,
TIME_STAMP bigint NOT NULL,
PRIMARY KEY (MY_KEY)
);
任何的想法?
由MySQL和HSQLDB支持的唯一的解决办法是查询您打算更换行,并且有条件地插入或更新。 这意味着你必须编写更多的应用程序代码,以弥补RDBMS实现之间的差异。
- START TRANSACTION。
- SELECT ... FOR UPDATE。
- 如果SELECT找到行,然后更新。
- 否则,INSERT。
- 承诺。
MySQL不支持ANSI SQL MERGE语句。 它支持替换并插入...对重复密钥更新。 见我的回答“插入忽略”与“INSERT ... ON DUPLICATE KEY UPDATE”如果要了解他们。
回复意见:是的,另一种方法是刚刚尝试INSERT,看看它是否成功。 否则,做一个更新。 如果你试图INSERT和它击中重复键,它会产生一个错误,它变成了一些客户端接口异常。 在MySQL这样做的缺点是,它产生即使INSERT失败了新的自动递增ID。 所以,你最终的差距。 我知道,在自动递增序列的差距不是一般的东西而发愁,但我去年谁曾在的,因为这影响成功的插件之间的缝隙1000-1500帮助客户,结果是,他们用尽的范围INT在他们的主键。
作为@baraky说,人们可以代替首先尝试的更新,如果影响零行,然后执行INSERT代替。 我对这个策略的评论是,UPDATEing零行也不例外 - 你必须检查是否有更新后,“受影响的行数”知道它是否“成功”与否。
但查询的行数影响你回到原来的问题:你必须在MySQL与HSQLDB使用不同的查询。
HSQLDB:
CALL DIAGNOSTICS(ROW_COUNT);
MySQL的:
SELECT ROW_COUNT();
在一个命令做一个更新插入语法通过RDBMS变化。
- MySQL的
INSERT…ON DUPLICATE KEY UPDATE
- HSQLDB
MERGE
- Postgres的
INSERT…ON CONFLICT…
参见维基百科的更多 。
如果你想要一个跨平台的解决方案,那么你就需要使用多个命令。 对于现有的行首先检查,然后有条件插入或相应的更新。