【问题标题】:Avoid unnecessary update in "update or insert" SQL?避免在“更新或插入”SQL 中进行不必要的更新?
【发布时间】:2021-06-16 07:16:12
【问题描述】:

这里是更新或插入的 Firebird SQL 描述:

https://firebirdsql.org/refdocs/langrefupd25-update-or-insert.html

还有我的例子

update or insert into books (id, name)
  values (555, 'Good book')
  matching (id)

如果 book 已经存在 id=555name='Good book' 那么这个命令无论如何都会执行更新语句并且更新触发器的触发是这种更新的唯一效果,不会改变记录的值。如果可更新字段(例如本例中的名称)已经具有指定值,是否可以在此 SQL 中请求不需要执行更新。

我的问题是针对 Firebird 2、3、4。但如果 SQL 服务器、MySQL 或 Oracle 中存在类似的阻止子句,那么我很乐意听到。

【问题讨论】:

  • BEFORE UPDATE 拒绝更新的触发器?
  • 我不确定 Firebird 是否有这样的拒绝功能。而且最好避免更新命令的初始化,这是浪费资源。
  • 那么我想没有这样的功能,除非您的 RDBMS 已经优化了资源浪费并且触发是唯一的副作用。我积极倾向于总是隐含地应用一些优化,例如未决的更改缓存在数据库外部的 RAM 中,然后偶尔刷新到磁盘上。但可以肯定的是,您应该是特定 RDBMS 的专家
  • 然后使用 merge 命令代替 U-or-I。但是,如果您只需要单行,那么冗余更新就不是问题。如果您有很多行,那么它们要么已经存储在某个表中,要么可以之前插入到 GTT(全局临时表)中。在你完成之后 - 运行merge
  • @AlexeyLarionov 没有优化,因为 Firebird 使用 MVCC,一次更新会写入一个新的记录版本,而这个记录版本需要存在某些悲观锁定算法才能工作(无操作更新是有时完全用于此目的,因此无法对其进行优化)

标签: sql firebird


【解决方案1】:

如果您不想更新,那么您不应该使用UPDATE OR INSERT,而是使用MERGE,或者使用INSERT 并捕获并忽略重复键错误(假设您有合适的主键或唯一键)键约束)。

MERGE使用示例:

merge into books 
using (
  select 555 as id, 'Good book' as name
  from rdb$database) as src
on books.id = src.id
when not matched then
  insert (id, name) values (src.id, src.name)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-16
    • 2021-03-06
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多