zoukankan      html  css  js  c++  java
  • Postgresql插入或更新操作upsert

    幂等性的一个要求是多次操作的结果一致。对于update操作,多次直接的结果都是最后update的值,是满足需求的。

    但对于insert,如果已经插入,第二次会报错,duplicate error, 主键重复或者unique key duplicate。所以需要做一下处理。

    最简单的就是,try-catch,当报错的时候,调用update去更新,或者策略更简单点,直接返回就行,不需要更新,以第一条为准。

    PostgreSQL从9.5之后就提供了原子的upsert语法: 不存在则插入,发生冲突可以update。

    ## Inert语法

    官方文档: https://www.postgresql.org/docs/devel/sql-insert.html

    [ WITH [ RECURSIVE ] with_query [, ...] ]
    INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
       [ OVERRIDING { SYSTEM | USER} VALUE ]
       { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
       [ ON CONFLICT [ conflict_target ] conflict_action ]
       [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
    
    where conflict_target can be one of:
    
       ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
       ON CONSTRAINT constraint_name
    
    and conflict_action is one of:
    
       DO NOTHING
       DO UPDATE SET { column_name = { expression | DEFAULT } |
                       ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                       ( column_name [, ...] ) = ( sub-SELECT )
                     } [, ...]
                 [ WHERE condition ]

    index_column_name

    The name of a table_name column. Used to infer arbiter indexes. Follows CREATE INDEX format. SELECT privilege on index_column_name is required.

    index_expression

    Similar to index_column_name, but used to infer expressions on table_name columns appearing within index definitions (not simple columns).

    Follows CREATE INDEX format. SELECT privilege on any column appearing within index_expression is required.

    ## 使用示例

    创建表
    CREATE TABLE "test"."upsert_test" ( "id" int4 NOT NULL, "name" varchar(255) COLLATE "pg_catalog"."default" ) ;

    当主键id冲突时,更新其他字段
    INSERT INTO test.upsert_test(id, "name") VALUES(1, 'm'),(2, 'n'),(4, 'c')

    ON conflict(id) DO UPDATE SET "name" = excluded.name;

    • did 冲突的主键
    • EXCLUDED 代指要插入的记录

    当主键或者unique key发生冲突时,什么都不做

    INSERT INTO test.upsert_test(id, "name")
    VALUES(1, 'm'),(2, 'n'),(4, 'c')
    ON conflict(id)  DO NOTHING;

     
  • 相关阅读:
    HYSBZ 3813 奇数国
    HYSBZ 4419 发微博
    HYSBZ 1079 着色方案
    HYSBZ 3506 排序机械臂
    HYSBZ 3224 Tyvj 1728 普通平衡树
    Unity 3D,地形属性
    nginx 的naginx 种包含include关键字
    Redis 出现NOAUTH Authentication required解决方案
    mysql 8.0出现 Public Key Retrieval is not allowed
    修改jar包里的源码时候需要注意的问题
  • 原文地址:https://www.cnblogs.com/robertyao/p/10251037.html
Copyright © 2011-2022 走看看