日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

文檔

使用INSERT ON CONFLICT覆蓋寫入數據

更新時間:

本文介紹在AnalyticDB PostgreSQL版數據庫中,如何使用INSERT ON CONFLICT語法覆蓋寫入數據。

針對數據寫入時有主鍵沖突的情況,INSERT ON CONFLICT語法可以將沖突主鍵的INSERT行為轉換為UPDATE行為,從而實現沖突主鍵的覆蓋寫入。該特性又稱UPSERT覆蓋寫,與MySQL的REPLACE INTO類似。

注意事項

  • 僅支持行存表,不支持列存表(由于列存表不支持唯一索引,所以該特性無法支持列存表)。

  • 僅V6.3.6.1及以上內核版本支持在分區表中使用。如何升級內核版本,請參見版本升級

  • 不支持在UPDATE的SET子句中更新分布列和主鍵列。

  • 不支持在UPDATE的WHERE子句中使用子查詢。

  • 不支持Updatable View(可更新視圖)。

  • 不支持在同一條INSERT語句中對同一主鍵插入多條數據(國際SQL標準約束)。

SQL語法

覆蓋寫入語法基于INSERT語句,INSERT語句的語法大綱如下:

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
    { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
    [ ON CONFLICT [ conflict_target ] conflict_action ]
    [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
其中,conflict_target為:
    ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] )
其中,conflict_action為:
    DO NOTHING
    DO UPDATE SET { column_name = { expression | DEFAULT } |
                    ( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] )
                  } [, ...]
              [ WHERE condition ] 

ON CONFLICT子句可以實現覆蓋寫入。該子句由conflict_target和conflict_action組成。

參數

說明

conflict_target

  • conflict_action取值為Do Update時,conflict_target需要指定用來定義沖突的主鍵列或唯一索引列。

  • conflict_action取值為Do Nothing時,conflict_target可省略。

conflict_action

用于指定沖突后需要執行的動作。取值說明:

  • DO NOTHING:如果conflict_target指定的列有沖突,則丟棄待插入的數據。

  • DO UPDATE:如果conflict_target指定的列有沖突,則按照后面的UPDATE子句進行數據覆蓋。

示例

創建一個表t1,表中擁有4列,其中a列為主鍵,建表語句如下:

CREATE TABLE t1 (a int PRIMARY KEY, b int, c int, d int DEFAULT 0);

對表t1插入一行數據,主鍵列a的值為0,插入數據語句如下:

INSERT INTO t1 VALUES (0,0,0,0);

查看表數據:

SELECT * FROM t1;

返回信息如下:

 a | b | c | d
---+---+---+---
 0 | 0 | 0 | 0
(1 row)

如果再對表t1插入一行數據,主鍵列a的值還是0,則會返回一個報錯,插入數據語句如下:

INSERT INTO t1 VALUES (0,1,1,1);

報錯信息如下:

ERROR:  duplicate key value violates unique constraint "t1_pkey"
DETAIL:  Key (a)=(0) already exists.

如果不希望出現上述報錯信息,可以使用本文介紹的覆蓋寫入特性來進行處理:

  • 使用ON CONFLICT DO NOTHING子句:主鍵沖突的情況下,不執行任何操作(適用于有沖突丟棄沖突數據的場景)。

    插入數據語句如下:

    INSERT INTO t1 VALUES (0,1,1,1) ON CONFLICT DO NOTHING;

    查看表數據:

    SELECT * FROM t1;

    表t1沒有進行任何操作,返回示例如下:

     a | b | c | d
    ---+---+---+---
     0 | 0 | 0 | 0
    (1 row)
  • 使用ON CONFLICT DO UPDATE子句:主鍵沖突的情況下,更新非主鍵的列(適用于全部列覆蓋寫入的場景)。

    插入數據語句如下:

    INSERT INTO t1 VALUES (0,2,2,2) ON CONFLICT (a) DO UPDATE SET (b, c, d) = (excluded.b, excluded.c, excluded.d);

    INSERT INTO t1 VALUES (0,2,2,2) ON CONFLICT (a) DO UPDATE SET b = excluded.b, c = excluded.c, d = excluded.d; 

    在DO UPDATE SET子句中,可以使用excluded表示沖突的數據構成的偽表,在主鍵沖突的情況下,引用偽表中列的值覆蓋原來列的值。上述語句中,新插入的數據(0,2,2,2)構成了一個偽表,偽表包含1行4列數據,表名為excluded,可以使用excluded.b, excluded.c, excluded.d去引用偽表中的列。

    查看表數據:

    SELECT * FROM t1;

    表t1中的非主鍵列進行了更新,返回示例如下:

     a | b | c | d
    ---+---+---+---
     0 | 2 | 2 | 2
    (1 row)

除了上述兩種情況,覆蓋寫入功能支持更多使用場景,場景如下:

  • 主鍵沖突的情況下,在部分列中覆蓋寫入數據(適用于基于沖突數據覆蓋部分列的場景):

    例如主鍵沖突后,僅覆蓋c列的數據,插入數據語句如下:

    INSERT INTO t1 VALUES (0,0,3,0) ON CONFLICT (a) DO UPDATE SET c = excluded.c;

    查看表數據:

    SELECT * FROM t1;

    返回示例如下:

     a | b | c | d
    ---+---+---+---
     0 | 2 | 3 | 2
    (1 row)

  • 主鍵沖突的情況下,更新部分列的數據(適用于基于原始數據更新部分列場景):

    例如主鍵沖突后,將d列的數據加1,插入數據語句如下:

    INSERT INTO t1 VALUES (0,0,3,0) ON CONFLICT (a) DO UPDATE SET d = t1.d + 1;

    查看表數據:

    SELECT * FROM t1;

    返回示例如下:

     a | b | c | d
    ---+---+---+---
     0 | 2 | 3 | 3
    (1 row)

  • 主鍵沖突的情況下,更新數據為默認值(適用于沖突后,回退數據到默認值的場景):

    例如主鍵沖突后,將d列恢復到默認值(上文中d列的默認值為0),插入數據語句如下:

    INSERT INTO t1 VALUES (0,0,3,0) ON CONFLICT (a) DO UPDATE SET d = default;

    查看表數據:

    SELECT * FROM t1;

    返回示例如下:

     a | b | c | d
    ---+---+---+---
     0 | 2 | 3 | 0
    (1 row)

  • 插入多條數據:

    • 例如插入2行數據,其中主鍵沖突的行不進行任何操作,主鍵不沖突的行正常插入,插入數據語句如下:

      INSERT INTO t1 VALUES (0,0,0,0), (1,1,1,1) ON CONFLICT DO NOTHING;

      查看表數據:

      SELECT * FROM t1;

      返回示例如下:

       a | b | c | d
      ---+---+---+---
       0 | 2 | 3 | 0
       1 | 1 | 1 | 1
      (2 rows)

    • 例如插入2行數據,主鍵沖突的行進行覆蓋寫入,主鍵不沖突的行正常插入,插入數據語句如下:

      INSERT INTO t1 VALUES (0,0,0,0), (2,2,2,2) ON CONFLICT (a) DO UPDATE SET (b, c, d) = (excluded.b, excluded.c, excluded.d);

      查看表數據:

      SELECT * FROM t1;

      返回示例如下:

       a | b | c | d
      ---+---+---+---
       0 | 0 | 0 | 0
       1 | 1 | 1 | 1
       2 | 2 | 2 | 2
      (3 rows)

  • 插入的數據來自于子查詢,如果主鍵沖突,則覆蓋寫入(用于合并兩表數據或更復雜的INSERT INTO SELECT場景):

    創建表t2,數據結構與表t1一致,建表語句如下:

    CREATE TABLE t2 (like t1);

    在表t2中插入兩行數據,插入數據語句如下:

    INSERT INTO t2 VALUES (2,22,22,22),(3,33,33,33);

    將表t2的數據插入表t1,如果主鍵沖突,則覆蓋寫入非主鍵的列,插入數據語句如下:

    INSERT INTO t1 SELECT * FROM t2 ON CONFLICT (a) DO UPDATE SET (b, c, d) = (excluded.b, excluded.c, excluded.d);

    查看表數據:

    SELECT * FROM t1;

    返回示例如下:

     a | b  | c  | d
    ---+----+----+----
     0 |  0 |  0 |  0
     1 |  1 |  1 |  1
     2 | 22 | 22 | 22
     3 | 33 | 33 | 33
    (4 rows)