INSERT(多表)

通过在表中插入一个或多个具有列值的行(来自查询)来更新多个表。支持无条件插入和有条件插入。

另请参阅:

INSERT

语法

-- Unconditional multi-table insert
INSERT [ OVERWRITE ] ALL
  intoClause [ ... ]
<subquery>

-- Conditional multi-table insert
INSERT [ OVERWRITE ] { FIRST | ALL }
  { WHEN <condition> THEN intoClause [ ... ] }
  [ ... ]
  [ ELSE intoClause ]
<subquery>
Copy

其中:

intoClause ::=
  INTO <target_table> [ ( <target_col_name> [ , ... ] ) ] [ VALUES ( { <source_col_name> | DEFAULT | NULL } [ , ... ] ) ]
Copy

必填参数

ALL

仅限无条件多表插入

指定每一行执行 INSERT 语句中的每个 INTO 子句。

备注

如果在无条件多表插入中指定了 FIRST 关键字(或者未指定 ALL 关键字),则 Snowflake 返回语法错误。

FIRST ALL

仅限条件多表插入

FIRST

指定每行仅执行条件计算结果为 TRUE 的第一个 WHEN 子句。如果没有 WHEN 子句的计算结果为 TRUE,则执行 ELSE 子句(如果存在)。

ALL

指定每行执行所有 WHEN 子句。如果没有 WHEN 子句的计算结果为 TRUE,则执行 ELSE 子句(如果存在)。

备注

  • 条件多表插入必须至少包含一个 WHEN 子句。

  • 每个 WHEN 子句可以包含多个 INTO 子句,并且这些 INTO 子句可以插入同一个目标表。

  • 要始终执行 WHEN 子句,请使用:

    WHEN 1=1 THEN ...

condition

仅限条件多表插入

指定计算结果必须为 TRUE 的条件,以便插入 INTO 子句中指定的值。条件可以是 SELECT 列表。

target_table

指定要在其中插入行的目标表。同一表可以(在单独的 WHEN 子句中)多次引用。

通过为每个表包含一个 INTO 子句,可以定位多个表。

subquery

指定 SELECT 列表,用于确定要插入目标表的值的来源。

可选参数

OVERWRITE

指定在插入表之前截断目标表,同时保留对表的访问控制权限。

OVERWRITE 的 INSERT 语句可以在当前事务的作用域内进行处理,从而避免提交事务的 DDL 语句,例如:

DROP TABLE t;
CREATE TABLE t AS SELECT * FROM ... ;
Copy

默认值:无值(在执行插入之前 ` 不会 :emph:` 截断目标表)

( target_col_name [ , ... ] )

指定目标表中的一列或多列,在其中插入源中相应列的值。指定的目标列数必须与源中指定的值数匹配。

默认值:无值(目标表中的 :emph:` 所有 ` 列都会更新)

VALUES ( source_col_name | DEFAULT | NULL [ , ... ] )

指定要插入到目标表的相应列中的一个或多个值。这些值可以是:

  • source_col_name:指定源中的列,包含要插入目标表中相应列的值。

  • DEFAULT:插入目标表中相应列的默认值。

  • NULL:插入 NULL 值。

该子句中的每个值都必须用逗号分隔。此外,指定的值数必须与为目标表指定的列数匹配。

默认值:无值(源中 ` 所有 :emph:` 列的值都插入目标表中的相应列)

使用说明

  • INTO 子句中,VALUES 子句可选。如果省略,则 SELECT 列表中的值按其自然顺序插入目标表。

  • WHEN 子句中的表达式(用于条件多表插入)和 VALUES 子句只能通过别名引用子查询。别名必须是以下其中一项:

    • SELECT 表达式指定的显式别名。

    • 表达式的默认别名。

    • 位置别名($1、$2 等)。

    此外,最外层 SELECT 列表中不包含的子查询的列和表达式不能在 WHENVALUES 子句中引用。有关详细信息,请参阅 ` 示例 `_ (本主题内容)。

  • subquery 生成的每一行中,source_col_name 中的值必须与相应 target_col_name 的数据类型兼容。此规则甚至适用于按 WHEN 子句中 condition 筛选出的行。操作顺序不能保证,在针对数据类型兼容性计算 source_col_name 中的值之前,会应用 WHEN 子句中的筛选器。

示例

无条件多表插入

src 表中的每一行插入表 t1t2 中 :emph:` 两次 `。在此示例中,插入的行不完全相同;插入的每一行都有不同的值/顺序,因为我们使用 VALUES 子句来改变数据:

INSERT ALL
  INTO t1
  INTO t1 (c1, c2, c3) VALUES (n2, n1, DEFAULT)
  INTO t2 (c1, c2, c3)
  INTO t2 VALUES (n3, n2, n1)
SELECT n1, n2, n3 from src;

-- If t1 and t2 need to be truncated before inserting, OVERWRITE must be specified
INSERT OVERWRITE ALL
  INTO t1
  INTO t1 (c1, c2, c3) VALUES (n2, n1, DEFAULT)
  INTO t2 (c1, c2, c3)
  INTO t2 VALUES (n3, n2, n1)
SELECT n1, n2, n3 from src;
Copy

条件多表插入

接下来的两个示例演示如何使用 WHEN 子句和 ELSE 子句,确定每行插入哪个表(如果有),从而创建条件多表插入。

这些示例还演示 INSERT ALLINSERT FIRST 之间的使用区别。

执行带 ELSE 子句的所有 WHEN 子句:

  • 同时满足 n1 > 100n1 > 10 的行,因此在使用 ALL 关键字时会在 t1 中插入两次。

  • n1 <= 10 满足 ELSE 情况的行,因此插入 t2

    INSERT ALL
      WHEN n1 > 100 THEN
        INTO t1
      WHEN n1 > 10 THEN
        INTO t1
        INTO t2
      ELSE
        INTO t2
    SELECT n1 from src;
    
    Copy

如果表 src 包含 3 行,其中 n1 的值为 1、11 和 101,则在 INSERT 语句之后,表 t1 和 t2 将包含如下所示的值:

t1:

101

101 > 100,因此第一个 WHEN 子句插入 t1 中

101

101 > 10,因此第二个 WHEN 子句 插入 t1 中

11

11 > 10,因此第二个 WHEN 子句插入 t1 中

n1 = 1 的行未插入 t1 中,因为它不满足插入 t1 中的任何 WHEN 子句,并且 ELSE 子句未插入 t1 中。

t2:

101

101 > 10,因此第二个 WHEN 子句插入 t2 中。(该行也符合子句 WHEN n1 > 100 的条件;但是,该子句不会插入 T2 中。)

11

11 > 10,因此第二个 WHEN 子句插入 t2 中

1

该行不满足任何 WHEN 子句,因此它由 ELSE 子句插入 T2 中

下一个示例与上一个示例类似,只是带有一个 FIRST 子句。

INSERT FIRST
  WHEN n1 > 100 THEN
    INTO t1
  WHEN n1 > 10 THEN
    INTO t1
    INTO t2
  ELSE
    INTO t2
SELECT n1 from src;
Copy

如果表 src 包含 3 行,其中 n1 的值为 1、11 和 101,则在 INSERT 语句之后,表 t1 和 t2 将包含如下所示的值:

t1:

101

101 > 100,因此第一个 WHEN 子句插入 t1 中

11

11 > 10,因此第二个 WHEN 子句插入 t1 中

n1 = 1 的行未插入 t1 中,因为它不满足插入 t1 中的任何 WHEN 子句,并且 ELSE 子句未插入 t1 中。

与前面使用 ALL 的示例不同,带 n1 = 101 的行仅插入 t1 中一次,因为 第一个 WHEN 子句的计算结果为 TRUE,因此第二个 WHEN 子句被忽略。

t2:

11

11 > 10,因此第二个 WHEN 子句插入 t2 中

1

该行不满足任何 WHEN 子句,因此它由 ELSE 子句插入 T2 中

该行 n1 = 101 未插入 t2 中,因为 101 大于 100,因此它与第一个 WHEN 子句匹配,但第一个 WHEN 子句未插入 t2 中,并且该语句不会检查任何其他 WHEN 子句或使用该 ELSE 子句,因为该行已经符合第一个 WHEN 子句的条件。

带别名和引用的多表插入

使用位置别名 ($1)、显式别名 (an_alias) 和默认别名 ("10 + 20") 插入值;此示例将带值 (1, 50, 30) 的单个行插入表 t1

INSERT ALL
  INTO t1 VALUES ($1, an_alias, "10 + 20")
SELECT 1, 50 AS an_alias, 10 + 20;
Copy

说明如何从必须选择引用的列中插入值(表 src 中的 bc):

-- Returns error
  INSERT ALL
    WHEN c > 10 THEN
      INTO t1 (col1, col2) VALUES (a, b)
  SELECT a FROM src;

-- Completes successfully
  INSERT ALL
    WHEN c > 10 THEN
      INTO t1 (col1, col2) VALUES (a, b)
  SELECT a, b, c FROM src;
Copy

说明如何从无法引用的列中插入值 (src1.key);相反,必须选择该列并使用别名:

-- Returns error
  INSERT ALL
    INTO t1 VALUES (src1.key, a)
  SELECT src1.a AS a
  FROM src1, src2 WHERE src1.key = src2.key;

-- Completes successfully
  INSERT ALL
    INTO t1 VALUES (key, a)
  SELECT src1.key AS key, src1.a AS a
  FROM src1, src2 WHERE src1.key = src2.key;
Copy
语言: 中文