GaussDB-INSERT

79 阅读19分钟

GaussDB-INSERT

功能描述

向表中插入一行或多行数据。

注意事项
  • 表的所有者、拥有表INSERT权限的用户或拥有INSERT ANY TABLE权限的用户,可向表中插入数据,三权分立关闭时的系统管理员默认拥有此权限。

  • 如果使用RETURNING子句,用户必须要有该表的SELECT权限。

  • 如果使用ON DUPLICATE KEY UPDATE,用户必须要有该表的INSERT、UPDATE权限,UPDATE子句中列的SELECT权限。

  • 如果使用query子句插入来自查询里的数据行,用户还需要拥有在查询里使用的表的SELECT权限。

  • 如果使用query子句插入来自查询动态数据脱敏列的数据,插入的结果即为脱敏后的值,无法被还原。

  • 当连接到TD兼容的数据库时,td_compatible_truncation参数设置为on时,将启用超长字符串自动截断功能,在后续的INSERT语句中(不包含外表的场景下),对目标表中CHAR和VARCHAR类型的列上插入超长字符串时,系统会自动按照目标表中相应列定义的最大长度对超长字符串进行截断。

    如果向字符集为字节类型编码(SQL_ASCII,LATIN1等)的数据库中插入多字节字符数据(如汉字等),且字符数据跨越截断位置,这种情况下,按照字节长度自动截断,自动截断后会在尾部产生非预期结果。如果用户有对于截断结果正确性的要求,建议用户采用UTF8等能够按照字符截断的输入字符集作为数据库的编码集。

语法格式

| ``` [ WITH [ RECURSIVE ] with_query [, ...] ] INSERT [/*+ plan_hint /] [ IGNORE ] INTO table_name [ { [alias_name] [ ( column_name [, ...] ) ] } | { [partition_clause] [ AS alias ] [ ( column_name [, ...] ) ] } ] { DEFAULT VALUES | { VALUES | VALUE } {( { expression | DEFAULT } [, ...] ) }[, ...] | query } [ ON DUPLICATE KEY UPDATE { NOTHING | { column_name = { expression | DEFAULT } } [, ...] [ WHERE condition ] } ] [ RETURNING { | {output_expression [ [ AS ] output_name ] }[, ...]} ];

| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

对子查询和视图插入:

[ WITH [ RECURSIVE ] with_query [, ...] ] INSERT [/*+ plan_hint /] INTO {subquery | view_name} [ AS alias ] [ ( column_name [, ...] ) ] { DEFAULT VALUES | { VALUES | VALUE } {( { expression | DEFAULT } [, ...] ) }[, ...] | query } [ RETURNING { | {output_expression [ [ AS ] output_name ] }[, ...]} ];


#### 参数说明

-   **WITH [ RECURSIVE ] with_query [, ...]**

    用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于临时表。

    如果声明了RECURSIVE,那么允许SELECT子查询通过名称引用。

    其中with_query的详细格式为:

    ```
    with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ]
    ( {SELECT | VALUES | INSERT | UPDATE | DELETE} )
    ```

    – with_query_name指定子查询生成的结果集名称,在查询中可使用该名称访问子查询的结果集。

    – column_name指定子查询结果集中显示的列名。

    – 每个子查询可以是SELECTVALUESINSERTUPDATEDELETE语句。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/0657c38e1c97412aa5eb64d490040d87~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=U9LHOY%2FZDFBQOomyxTENm%2Fp9HYA%3D)NOTICE:

    当子查询为附带RETURNING语句的DML时,INSERT语句的回显记录数由子查询决定。假设存在表T1,执行以下语句:

    ```
    WITH CTE AS (INSERT INTO T1 VALUES(1,2) RETURNING *) INSERT INTO T1 SELECT * FROM CTE;
    ```

    上述语句的回显记录数由以下部分决定,而不是由整条语句决定,即回显为“INSERT 0 1”,而不是“INSERT 0 2”。

    ```
    INSERT INTO T1 VALUES(1,2) RETURNING *
    ```

    – 用户可以使用MATERIALIZED / NOT MATERIALIZED对CTE进行修饰。

    -   如果声明为MATERIALIZED,WITH查询将被物化,生成一个子查询结果集的复制,在引用处直接查询该复制,因此WITH子查询无法和主干SELECT语句进行联合优化(如谓词下推、等价类传递等),对于此类场景可以使用NOT MATERIALIZED进行修饰,如果WITH查询语义上可以作为子查询内联执行,则可以进行上述优化。
    -   如果用户没有显示声明物化属性则遵守以下规则:如果CTE只在所属主干语句中被引用一次,且语义上支持内联执行,则会被改写为子查询内联执行,否则以CTE Scan的方式物化执行。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/ac4525fe67914d2f98bcef118109aac1~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=aqYs1EVPEnq1ZoNADlKvj1n%2FWkA%3D)

    INSERT ON DUPLICATE KEY UPDATE不支持WITHWITH RECURSIVE子句。

-   **plan_hint子句**/*+ */的形式在INSERT关键字后,用于对INSERT对应的语句块生成的计划进行hint调优,详细用法请参见章节[使用Plan Hint进行调优](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0270.html#ZH-CN_TOPIC_0000001865586156)。每条语句中只有第一个/*+ plan_hint */注释块会作为hint生效,里面可以写多条hint。

-   **IGNORE**

    INSERT语句使用IGNORE关键字时,可将某些ERROR级别的错误降级为WARNING级抛出,并根据不同的错误场景将无效值调整为最接近的值插入。GaussDB支持错误降级的错误码如下:

    -   控制破坏NOT NULL约束。
    -   唯一键冲突。
    -   插入的值没有找到对应的分区。
    -   指定分区插入时,插入的数据与指定分区不匹配。
    -   子查询返回多行。
    -   数据过长。
    -   时间函数溢出。
    -0除。
    -   值不正确。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/85279598c1344f6bb40bdfc438dc361e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=8kjqanGfp1B%2Be5DmUzqfTfEzdzs%3D)

    1.  INSERT IGNORE只在MySQL模式(即sql_compatibility = 'MySQL'),b_format_version = '5.7'和b_format_dev_version = 's1'场景下支持。
    1.  INSERT IGNORE不支持密态表、外表。
    1.  INSERT IGNORE不支持延迟生效的主键约束或唯一键约束。
    1.  INSERT IGNORE支持NULL值破坏NOT NULL约束的数据类型对应的oid为:TIMESTAMPOID、TIMESTAMPTZOID、TIMEOID、TIMETZOID、RELTIMEOID、INTERVALOID、TINTERVALOOID、SMALLDATETIMEOID、DATEOID、NAMEOID、POINTOID、PATHOID、POLYGONOID、CIRCLEOID、LSEGOID、BOXOID、JSONOID、JSONBOID、XMLOID、XMLTYPEOID、VARBITOID、NUMERICOID、CIDROID、INETOID、MACADDROID、NUMRANGEOID、INT8RANGEOID、INT4RANGEOID、TSRANGEOID、TSTZRANGEOID、DATERANGEOID、ABSTIMEOID、BOOLOID、INT8OID、INT4OID、INT2OID、INT1OID、FLOAT4OID、FLOAT8OID、CASHOID、UINT1OID、UINT2OID、UINT4OID、UINT8OID、BPCHAROID、VARCHAROID、NVARCHAR2OID、CHAROID、BYTEAOID、RAWOID、BLOBOID、CLOBOID、TEXTOID、YEAROID,各数据类型对应的零值如[表1](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0645.html#ZH-CN_TOPIC_0000001865587440__zh-cn_topic_0000001656059352_table350262715199)所示。
    1.  默认零值参与计算时,需要谨慎使用IGNORE忽略NOT NULL约束。
    1.  INSERT IGNORE不支持包含全局二级索引的表。
    1.  如果错误是在CN上产生,则会显示降级的WARNING信息,如果错误是在DN上产生,则不会显示降级后的WARNING信息。

    []()[]()

    | 数据类型的OID                                                                                            | 默认零值                                                                    |
    | :-------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
    | INT8OID、INT4OID、INT2OID、INT1OID、UINT1OID、UINT2OID、UINT4OID、UINT8OID、FLOAT4OID、FLOAT8OID、NUMERICOID  | 00.00(小数点后0的个数由参数指定)                                                   |
    | BPCHAROID、VARCHAROID、CHAROID、BYTEAOID、RAWOID、BLOBOID、NVARCHAR2OID、CLOBOID、TEXTOID、VARBITOID、NAMEOID | 空字符串                                                                    |
    | NUMRANGEOID、INT8RANGEOID、INT4RANGEOID、TSRANGEOID、TSTZRANGEOID、DATERANGEOID                          | empty                                                                   |
    | TIMEOID                                                                                             | time '00:00:00'                                                         |
    | TIMETZOID                                                                                           | timetz '00:00:00'                                                       |
    | INTERVALOID                                                                                         | interval '00:00:00'                                                     |
    | TINTERVALOOID                                                                                       | tinterval(abstime '1970-01-01 00:00:00', abstime '1970-01-01 00:00:00') |
    | SMALLDATETIMEOID                                                                                    | smalldatetime '1970-01-01 00:00:00'                                     |
    | ABSTIMEOID                                                                                          | abstime '1970-01-01 00:00:00'                                           |
    | RELTIMEOID                                                                                          | reltime '00:00:00'                                                      |
    | TIMESTAMPOID、TIMESTAMPTZOID                                                                         | 1970-01-01 00:00:00                                                     |
    | DATEOID                                                                                             | 1970-01-01                                                              |
    | YEAROID                                                                                             | 0000                                                                    |
    | POINTOID                                                                                            | (0,0)                                                                   |
    | PATHOID、POLYGONOID                                                                                  | ((0,0))                                                                 |
    | CIRCLEOID                                                                                           | <(0,0),0>                                                               |
    | LSEGOID                                                                                             | [(0,0),(0,0)]                                                          |
    | BOXOID                                                                                              | (0,0),(0,0)                                                             |
    | JSONOID、JSONBOID、XMLOID                                                                             | 'null'                                                                  |
    | XMLTYPEOID                                                                                          | '<null/>'                                                              |
    | CIDROID                                                                                             | 0.0.0.0/32                                                              |
    | INETOID                                                                                             | 0.0.0.0                                                                 |
    | MACADDROID                                                                                          | 00:00:00:00:00:00                                                       |
    | BOOLOID                                                                                             | f                                                                       |
    | CASHOID                                                                                             | $0.00                                                                  |

-   **table_name**

    要插入数据的目标表名。

    取值范围:已存在的表名。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/b4348a2a27ce45c9a7b26e11c87f77df~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=DK0DpZ%2B8JMOVILvJrEmi0976k04%3D)

    支持使用DATABASE LINK方式对远端表进行操作,使用方式详情请见[DATABASE LINK](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0711.html#ZH-CN_TOPIC_0000001865745520)。

-   **subquery**

    插入对象可以是子查询,在对子查询进行插入时,会将子查询当成一个临时视图,支持在子查询后面加CHECK OPTION选项。

    ```
    [ WITH [ RECURSIVE ] with_query [, ...] ]
    SELECT [/*+ plan_hint */] [ ALL ]
    { * | {expression [ [ AS ] output_name ]} [, ...] }
    [ into_option ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ [ START WITH condition ] CONNECT BY [NOCYCLE] condition [ ORDER SIBLINGS BY expression ] ]
    [ ORDER BY {expression [ [ ASC | DESC | USING operator ] | nlssort_expression_clause ] [ NULLS { FIRST | LAST } ]} [, ...] ]
    [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
    [ into_option ];
    ```

    其中指定子查询源from_item为:

    ```
    {[ ONLY ] {table_name | view_name} [ * ] [ partition_clause ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    |( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
    |with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    |from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]}
    ```

    如果子查询中只有一张表,则对该表插入数据;如果子查询中有多张表或有嵌套关系,则通过判断是否有保留键表确定是否可插入。关于保留键表和WITH CHECK OPTION请参见[CREATE VIEW](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。

-   **view_name**

    要插入的目标视图。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/aca2314c54614237868eb262ab21c5af~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=QIKsbIzaGPb%2BMckqB4BFVSn0c0c%3D)

    对视图和子查询的插入,有如下约束:

    -   只有直接引用基表用户列的列可进行INSERT-   子查询或视图必须至少包含一个可更新列,关于可更新列请参见[CREATE VIEW](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。
    -   不支持在顶层包含DISTINCTGROUP BYHAVING、LIMIT、OFFSET子句的视图和子查询。
    -   不支持在顶层包含集合运算(UNIONINTERSECTEXCEPT、MINUS)的视图和子查询。
    -   不支持目标列表中包含聚集函数、窗口函数、返回集合函数(array_agg、json_agg、generate_series等)的视图和子查询。
    -   不支持视图仅带有BEFORE/AFTER触发器,没有INSTEAD OF触发器或INSTEAD规则。
    -   不支持ON DUPLICATE KEY UPDATE功能。
    -   视图和子查询中支持的表类型包括普通表、临时表、全局临时表、分区表、二级分区表、ustore表、astore表。
    -   对多表连接视图或子查询,一次只能对一张基表做插入。
    -   INSERT连接视图或子查询时显式指定的插入列或隐式指定(即创建视图或子查询中指定的列)不能引用非保留键表的列,如果使用了WITH CHECK OPTION子句则连接视图中或子查询中的连接列无法进行插入操作。关于保留键表请参见[CREATE VIEW](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。
    -   不支持对系统视图进行INSERT操作。

-   **alias** **_name**

    INSERT语句不包含AS alias语法时的表别名。

    ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/ddf3382182b44ab1b97d5f9bf34d4876~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=1xdI1mkKrnDcM5YUc4%2F81rzrol8%3D)

    1.  INSERT不包含AS alias语法时的表别名不能为关键字(如SELECTVALUE)或者表达式,别名要求符合标识符命名规则。
    1.  INSERT不包含AS alias语法时的表别名不支持INSERT INTO table_name alias_name(alias_name.col1,...,alias_name.coln) VALUES(xxx);的语法格式。
    1.  INSERT的分区表不包含AS alias语法时的表别名不支持指定分区插入操作。

-   **partition_clause**

    指定分区插入操作

    ```
    PARTITION { ( partition_name ) | FOR ( partition_value [, ...] ) } 
    ```

    关键字详见[SELECT](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0675.html#ZH-CN_TOPIC_0000001911665281)章节介绍。

    如果VALUE子句的值和指定分区不一致,结果会提示异常。

-   **column_name**

    目标表中的字段名称:

    -   字段名可以有子字段名或者数组下标修饰。
    -   没有在字段列表中出现的每个字段,将由系统默认值,或者声明时的默认值填充,若都没有则用NULL填充。例如,向一个复合类型中的某些字段插入数据的话,其他字段将是NULL-   目标字段(column_name)可以按顺序排列。如果没有列出任何字段,则默认全部字段,且顺序为表声明时的顺序。
    -   如果VALUE子句和QUERY中只提供了N个字段,则目标字段为前N个字段。
    -   VALUE子句和QUERY提供的值在表中从左到右关联到对应列。

    取值范围:已存在的字段名。

-   **expression**

    赋予对应column的一个有效表达式或值:

    -   如果是INSERT ON DUPLICATE KEY UPDATE语句下,expression可以为VALUES(column_name)或EXCLUDED.column_name用来表示引用冲突行对应的column_name字段的值。其中VALUES(column_name)支持嵌套在复合表达式中,例如:VALUES(column_name)+1VALUES(column_name)+VALUES(column_name)、function_name(VALUES(column_name))等。

        ![](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/5abb0d58243445a99527ebf3eac0f607~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgamVycnl3YW5nMTk4Mw==:q75.awebp?rk3s=f64ab15b&x-expires=1771579622&x-signature=u2JMWra6K3vplhH2J68d4DKMvTY%3D)

        -   上述VALUES(column_name)特性仅支持在ON DUPLICATE KEY UPDATE子句中使用。
        -   上述VALUES(column_name)特性不支持在INNOT IN表达式中使用。

    <!---->

    -   向表中字段插入单引号 " ' "时需要使用单引号自身进行转义。
    -   如果插入行的表达式不是正确的数据类型,系统试图进行类型转换,若转换不成功,则插入数据失败,系统返回错误信息。

-   **DEFAULT**

    对应字段名的缺省值。如果没有缺省值,则为NULL-   **query**

    一个查询语句(SELECT语句),将查询结果作为插入的数据。

-   **RETURNING**

    返回实际插入的行,RETURNING列表的语法与SELECT的输出列表一致。

-   **output_expression**

    INSERT命令在每一行都被插入之后用于计算输出结果的表达式。

    取值范围:该表达式可以使用table的任意字段。可以使用*返回被插入行的所有字段。

-   **output_name**

    字段的输出名称。

    取值范围:字符串,要符合[标识符命名规范](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0321.html#ZH-CN_TOPIC_0000001865746364__zh-cn_topic_0000001704458709_section14873217506)。

-   **ON DUPLICATE KEY UPDATE**

    对于带有唯一约束(UNIQUE INDEX或PRIMARY KEY)的表,如果插入数据违反唯一约束,则对冲突行执行UPDATE子句完成更新。如果UPDATE子句为NOTHING,则不做任何操作。可通过"EXCLUDED." 或者 "VALUES()" 来选择源数据相应的列。

    对于不带唯一约束的表,则仅执行插入。

    -   支持触发器,触发器执行顺序由实际执行流程决定:

        -   执行INSERT: 触发BEFORE INSERT、AFTER INSERT触发器。
        -   执行UPDATE:触发BEFORE INSERT、BEFORE UPDATE、AFTER UPDATE触发器。
        -   执行UPDATE NOTHING: 触发BEFORE INSERT触发器。

    <!---->

    -   不支持延迟生效(DEFERRABLE)的唯一约束或主键。

    <!---->

    -   如果表中存在多个唯一约束,如果所插入数据违反多个唯一约束,对于检测到冲突的第一行进行更新,其他冲突行不更新(检查顺序与索引维护具有强相关性,一般先创建的索引先进行冲突检查)。

    <!---->

    -   主键、唯一索引列不允许UPDATE-   不支持外表。
    -   UPDATEWHERE子句和expression中不支持包含子链接。

#### 示例

-   **插入一条数据**

    **示例:**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t1(col1 INT,col2 VARCHAR);

    --插入数据。
    gaussdb=# INSERT INTO test_t1 (col1, col2) VALUES (1,'AB');

    --只给表中部分列添加值。
    gaussdb=# INSERT INTO test_t1 (col1) VALUES (2);

    --VALUES关键字左边没有括号,右边括号里面必须严格按照表结构的顺序给所有的字段添加值。
    gaussdb=# INSERT INTO test_t1 VALUES (3,'AC');

    --查询表。
    gaussdb=# SELECT * FROM test_t1;
     col1 | col2 
    ------+------
        1 | AB
        2 | 
        3 | AC
    (3 rows)

    --删除。
    gaussdb=# DROP TABLE test_t1;
    ```

-   **插入多条数据**

    **示例:**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t2(col1 INT,col2 VARCHAR);
    gaussdb=# CREATE TABLE test_t3(col1 INT,col2 VARCHAR);

    --插入多条数据。
    gaussdb=# INSERT INTO test_t2 (col1, col2) VALUES (10,'AA'),(20,'BB'),(30,'CC');

    --查询。
    gaussdb=# SELECT * FROM test_t2;
     col1 | col2 
    ------+------
       10 | AA
       20 | BB
       30 | CC
    (3 rows)

    --把test_t2中的数据插入到test_t3中。
    gaussdb=# INSERT INTO test_t3 SELECT * FROM test_t2;

    --查询。
    gaussdb=# SELECT * FROM test_t3;
     col1 | col2 
    ------+------
       10 | AA
       20 | BB
       30 | CC
    (3 rows)

    --删除。
    gaussdb=# DROP TABLE test_t2;
    DROP TABLE test_t3;
    ```

-   **ON DUPLICATE KEY UPDATE**

    **示例:**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t4 (id INT PRIMARY KEY, info VARCHAR(10));
    gaussdb=# INSERT INTO test_t4 VALUES (1, 'AA'), (2,'BB'), (3, 'CC');

    --使用ON DUPLICATE KEY UPDATE关键字。
    gaussdb=# INSERT INTO test_t4 VALUES (3, 'DD'), (4, 'EE') ON DUPLICATE KEY UPDATE info = VALUES(info);

    --查询。
    gaussdb=# SELECT * FROM test_t4;
     id | info 
    ----+------
      1 | AA
      2 | BB
      4 | EE
      3 | DD

    --删除。
    gaussdb=# DROP TABLE test_t4;
    ```

-   **INSERT IGNORE**

    **示例1:破坏NOT NULL约束**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t5(f1 INT NOT NULL);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t5 VALUES(NULL);
    WARNING:  null value in column "f1" violates not-null constraint
    DETAIL:  Failing row contains (null).
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM test_t5;
     f1
    ----
      0
    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t5;
    DROP TABLE
    ```

    **示例2:唯一键冲突**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t6(f1 INT PRIMARY KEY);
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_t6_pkey" for table "test_t6"
    CREATE TABLE

    --插入数据。
    gaussdb=# INSERT INTO test_t6 VALUES(1);
    INSERT 0 1

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t6 VALUES(1);
    INSERT 0 0

    --查询表。
    gaussdb=# SELECT * FROM test_t6;
     f1
    ----
      1
    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t6;
    DROP TABLE
    ```

    **示例3:插入的值没有找到对应的分区**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t7(f1 INT, f2 INT) PARTITION BY LIST(f1) (PARTITION p0 VALUES(1, 4, 7), PARTITION p1 VALUES (2, 5, 8));
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t7 VALUES(3, 5);
    INSERT 0 0

    --查询表。
    gaussdb=# SELECT * FROM test_t7;
     f1 | f2
    ----+----
    (0 rows)

    --删除表。
    gaussdb=# DROP TABLE test_t7;
    DROP TABLE
    ```

    **示例4:指定分区插入时,插入的数据与指定的分区不匹配**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t8(f1 INT NOT NULL, f2 TEXT, f3 INT) PARTITION BY RANGE(f1)(PARTITION p0 VALUES LESS THAN(5), PARTITION p1 VALUES LESS THAN(10), PARTITION p2 VALUES LESS THAN(15), PARTITION p3 VALUES LESS THAN(MAXVALUE));
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t8 PARTITION(p2) VALUES(20, 'Jan', 1);
    INSERT 0 0

    --查询表。
    gaussdb=# SELECT * FROM test_t8;
     f1 | f2 | f3
    ----+----+----
    (0 rows)

    --删除表。
    gaussdb=# DROP TABLE test_t8;
    DROP TABLE
    ```

    **示例5:子查询返回多行**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t9(f1 INT, f2 INT);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --插入数据。
    gaussdb=# INSERT INTO test_t9 VALUES(1, 1), (2, 2), (3, 3);
    INSERT 0 3

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t9 VALUES((SELECT f1 FROM test_t9), 0);
    WARNING:  more than one row returned by a subquery used as an expression
    CONTEXT:  referenced column: f1
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM test_t9 WHERE f2 = 0;
     f1 | f2
    ----+----
        |  0
    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t9;
    DROP TABLE
    ```

    **示例6:数据过长**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t10(f1 VARCHAR(5));
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t10 VALUES('aaaaaaaaa');
    WARNING:  value too long for type character varying(5)
    CONTEXT:  referenced column: f1
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM test_t10;
      f1
    -------
     aaaaa
    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t10;
    DROP TABLE
    ```

    **示例7:时间函数溢出**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t11(f1 DATETIME);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t11 VALUES(date_sub('2000-01-01', INTERVAL 2001 YEAR));
    WARNING:  Datetime function: datetime field overflow
    CONTEXT:  referenced column: f1
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM test_t11;
     f1
    ----

    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t11;
    DROP TABLE
    ```

    **示例8:被0**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t12(f1 INT);
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t12 VALUES(1/0);
    WARNING:  division by zero
    CONTEXT:  referenced column: f1
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM test_t12;
     f1
    ----

    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t12;
    DROP TABLE
    ```

    **示例9:值不正确**

    ```
    --建表。
    gaussdb=# CREATE TABLE test_t13(f0 INT, f1 FLOAT);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'f0' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE

    --使用IGNORE关键字。
    gaussdb=# INSERT IGNORE INTO test_t13 VALUES(1, '1.11aaa');
    WARNING:  invalid input syntax for type real: "1.11aaa"
    LINE 1: INSERT IGNORE INTO test_t13 VALUES(1, '1.11aaa');
                                                  ^
    CONTEXT:  referenced column: f1
    INSERT 0 1

    --查询表。
    gaussdb=# SELECT * FROM  test_t13;
     f0 |  f1
    ----+------
      1 | 1.11
    (1 row)

    --删除表。
    gaussdb=# DROP TABLE test_t13;
    DROP TABLE
    ```

-   **WITH [ RECURSIVE ] with_query [, ...]**

    **示例:**

    ```
    --成绩表。
    gaussdb=# CREATE TABLE grade (
        sid INT,
        course VARCHAR(20),
        score FLOAT
    );
    --学生表。
    gaussdb=# CREATE TABLE student(
        sid INT PRIMARY KEY,
        class INT,
        name  VARCHAR(50),
        sex INT CHECK (sex = 0 or sex = 1)
    );

    --插入数据。
    gaussdb=# WITH student_sid AS ( INSERT INTO student ( sid, CLASS, NAME, sex ) VALUES ( 1, 1, 'scott', 1 ) RETURNING sid ) 
        INSERT INTO grade ( sid, course, score )
        VALUE ( ( SELECT sid FROM student_sid ), 'match', '96' ),
    	  ( ( SELECT sid FROM student_sid ), 'chinese', '82' ),
    	  ( ( SELECT sid FROM student_sid ), 'english', '86' );

    --查询数据。
    gaussdb=# SELECT * FROM student;
     sid | class | name  | sex 
    -----+-------+-------+-----
       1 |     1 | scott |   1
    (1 row)

    gaussdb=# SELECT * FROM grade;
     sid | course  | score 
    -----+---------+-------
       1 | match   |    96
       1 | chinese |    82
       1 | english |    86
    (3 rows)

    --删除。
    gaussdb=# DROP TABLE student;
    gaussdb=# DROP TABLE grade;
    ```

<!---->

-   **向视图或子查询中插入**

    **示例1:插入子查询**

    ```
    --创建SCHEMA。
    gaussdb=# CREATE SCHEMA ins_subqry;
    CREATE SCHEMA
    gaussdb=# SET CURRENT_SCHEMA = 'ins_subqry';
    SET

    --创建表。
    gaussdb=# CREATE TABLE t1 (x1 int, y1 int);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'x1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE
    gaussdb=# CREATE TABLE t2 (x2 int PRIMARY KEY, y2 int);
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
    CREATE TABLE

    --通过子查询向t1插入。
    gaussdb=# INSERT INTO (SELECT * FROM t1) VALUES (1, 1);
    INSERT 0 1
    gaussdb=# INSERT INTO (SELECT * FROM t1 WHERE y1 < 3) VALUES (5, 5);
    INSERT 0 1

    --插入子查询带CHECK OPTION。
    gaussdb=# INSERT INTO (SELECT * FROM t1 WHERE y1 < 3 WITH CHECK OPTION) VALUES (5, 5);
    ERROR:  new row violates WITH CHECK OPTION for view "__unnamed_subquery__"
    DETAIL:  Failing row contains (5, 5).

    --插入子查询带READONLY。
    gaussdb=# INSERT INTO (SELECT * FROM t1 WITH READ ONLY) VALUES (5, 5);
    ERROR:  cannot perform a DML operation on a read-only subquery.

    --插入多表连接的子查询。
    gaussdb=# INSERT INTO (SELECT * FROM t1, t2 WHERE x1 = x2) (x1, y1) VALUES (2, 2);
    INSERT 0 1

    --删除SCHEMA。
    gaussdb=# RESET CURRENT_SCHEMA;
    RESET
    gaussdb=# DROP SCHEMA ins_subqry CASCADE;
    NOTICE:  drop cascades to 2 other objects
    DETAIL:  drop cascades to table ins_subqry.t1
    drop cascades to table ins_subqry.t2
    DROP SCHEMA
    ```

    示例2: 插入视图

    ```
    --创建SCHEMA。
    gaussdb=# CREATE SCHEMA ins_view;
    CREATE SCHEMA
    gaussdb=# SET CURRENT_SCHEMA = 'ins_view';
    SET

    --创建表。
    gaussdb=# CREATE TABLE t1 (x1 int, y1 int);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'x1' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE
    gaussdb=# CREATE TABLE t2 (x2 int PRIMARY KEY, y2 int);
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
    CREATE TABLE

    --创建单表视图。
    gaussdb=# CREATE VIEW v_ins1 AS SELECT * FROM t1;
    CREATE VIEW
    gaussdb=# CREATE VIEW v_ins2 AS SELECT * FROM t1 WHERE y1 < 3;
    CREATE VIEW
    gaussdb=# CREATE VIEW v_ins2_wco AS SELECT * FROM t1 WHERE y1 < 3 WITH CHECK OPTION;
    CREATE VIEW
    gaussdb=# CREATE VIEW v_ins_read AS SELECT * FROM t1 WITH READ ONLY;
    CREATE VIEW

    --通过视图对t1插入。
    gaussdb=# INSERT INTO v_ins1 VALUES (1, 1);
    INSERT 0 1
    gaussdb=# INSERT INTO v_ins2 VALUES (5, 5);
    INSERT 0 1
    gaussdb=# INSERT INTO v_ins2_wco VALUES (5, 5);
    ERROR:  new row violates WITH CHECK OPTION for view "v_ins2_wco"
    DETAIL:  Failing row contains (5, 5).

    gaussdb=# INSERT INTO v_ins_read VALUES (5, 5);
    ERROR:  cannot perform a DML operation on a read-only subquery.

    --创建多表视图。
    gaussdb=# CREATE VIEW vv_ins AS SELECT * FROM t1, t2 WHERE x1 = x2;
    CREATE VIEW

    --通过视图对t1插入。
    gaussdb=# INSERT INTO vv_ins (x1, y1) VALUES (2, 2);
    INSERT 0 1

    --删除SCHEMA。
    gaussdb=# RESET CURRENT_SCHEMA;
    RESET
    gaussdb=# DROP SCHEMA ins_view CASCADE;
    NOTICE:  drop cascades to 7 other objects
    DETAIL:  drop cascades to table ins_view.t1
    drop cascades to table ins_view.t2
    drop cascades to view ins_view.v_ins1
    drop cascades to view ins_view.v_ins2
    drop cascades to view ins_view.v_ins2_wco
    drop cascades to view ins_view.v_ins_read
    drop cascades to view ins_view.vv_ins
    DROP SCHEMA
    ```

#### 优化建议

-   VALUES

    []()[]()通过INSERT语句批量插入数据时,建议将多条记录合并入一条语句中执行插入,以提高数据加载性能。

    例如:

    ```
    INSERT INTO sections VALUES (30, 'Administration', 31, 1900),(40, 'Development', 35, 2000), (50, 'Development' , 60 , 2001);
    ```

    如果INSERTVALUES语句中VALUES的值分布在一个DN上,GaussDB可以把语句下推到对应DN执行。目前只支持VALUES中值为常量,简单表达式和可下推函数(pg_proc中字段provolatile为'i')。如果表中列带有DEFAULT值,只支持DEFAULT值为常量,简单表达式。单VALUES不能下推单DN的语句,多VALUES同样不支持下推。

更多详情请参考GaussDB 文档中心:<https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/productdesc/qlh_03_0001.html>