SQL标准UPSERT通话(SQL standard UPSERT call)

2019-07-21 03:09发布

我在寻找一个标准的SQL“ UPSERT ”语句。 如果是存在一个呼吁插入和更新。

我在找工作,高效,跨平台通话。

我见过MERGEUPSERTREPLACEINSERT .. 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)
);

任何的想法?

Answer 1:

由MySQL和HSQLDB支持的唯一的解决办法是查询您打算更换行,并且有条件地插入或更新。 这意味着你必须编写更多的应用程序代码,以弥补RDBMS实现之间的差异。

  1. START TRANSACTION。
  2. SELECT ... FOR UPDATE。
  3. 如果SELECT找到行,然后更新。
  4. 否则,INSERT。
  5. 承诺。

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();


Answer 2:

在一个命令做一个更新插入语法通过RDBMS变化。

  • MySQL的
    INSERT…ON DUPLICATE KEY UPDATE
  • HSQLDB
    MERGE
  • Postgres的
    INSERT…ON CONFLICT…

参见维基百科的更多 。

如果你想要一个跨平台的解决方案,那么你就需要使用多个命令。 对于现有的行首先检查,然后有条件插入或相应的更新。



文章来源: SQL standard UPSERT call