INSERT

通过在表中插入一行或多行来更新表。插入到表中每个列中的值可以是显式指定的,也可以是查询的结果。

另请参阅:

INSERT(多表)

语法

INSERT [ OVERWRITE ] INTO <target_table> [ ( <target_col_name> [ , ... ] ) ]
       {
         VALUES ( { <value> | DEFAULT | NULL } [ , ... ] ) [ , ( ... ) ]  |
         <query>
       }
Copy

必填参数

target_table

指定要在其中插入行的目标表。

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

指定要插入到目标表的相应列中的一个或多个值。

VALUES 子句中,可以指定以下值:

  • value:插入显式指定的值。该值可以是字面量或表达式。

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

  • NULL:插入 NULL 值。

该子句中的每个值都必须用逗号分隔。

您可以通过在该子句中指定其他值集来插入多行。有关更多详细信息,请参阅 使用说明示例 (本主题内容)。

query

指定一个 查询 语句,该语句返回要插入到相应列中的值。这允许您将行从一个或多个源表插入到目标表中。

可选参数

OVERWRITE

指定在将值插入到表中之前应截断目标表。请注意,指定此选项不会影响对表的访问控制权限。

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

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

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

( target_col_name [ , ... ] )

指定目标表中的一列或多列,在其中插入对应的值。指定的目标列数必须与 VALUES 子句中指定的值数或列数(如果这些值是查询的结果)匹配。

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

使用说明

  • 使用单个 INSERT 命令,您可以通过在 VALUES 子句中指定以逗号分隔的其他值集,将多行插入到表中。

    例如,以下子句将在包含 3 列的表中插入 3 行,前两行中插入值 123,第三行中插入值 234

    VALUES ( 1, 2, 3 ) ,
           ( 1, 2, 3 ) ,
           ( 2, 3, 4 )
    
    Copy
  • 要使用 INSERT 上的 OVERWRITE 选项,您必须使用对表具有 DELETE 权限的角色,因为 OVERWRITE 将删除表中的现有记录。

  • 某些表达式不能在 VALUES 子句中指定。作为替代方法,可以在查询子句中指定表达式。例如,您可以将以下内容:

    INSERT INTO table1 (ID, varchar1, variant1)
        VALUES (4, 'Fourier', PARSE_JSON('{ "key1": "value1", "key2": "value2" }'));
    
    Copy

    替换为:

    INSERT INTO table1 (ID, varchar1, variant1)
        SELECT 4, 'Fourier', PARSE_JSON('{ "key1": "value1", "key2": "value2" }');
    
    Copy
  • VALUES 子句限制为 16,384 行。此限制适用于单个 INSERT INTO ...VALUES 语句和单个 INSERT INTO ...SELECT ...FROM VALUES 语句。考虑使用 COPY INTO <table> 命令执行批量数据加载。有关在 SELECT 语句中使用 VALUES 子句的更多信息,请参阅 VALUES

  • 有关在混合表中插入数据的信息,请参阅 加载数据

示例

以下示例使用 INSERT 命令。

使用查询进行单行插入

将三个字符串值转换为日期或时间戳,并将它们插入到 mytable 表中的单行中:

CREATE OR REPLACE TABLE mytable (
  col1 DATE,
  col2 TIMESTAMP_NTZ,
  col3 TIMESTAMP_NTZ);

DESC TABLE mytable;
Copy
+------+------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
| name | type             | kind   | null? | default | primary key | unique key | check | expression | comment | policy name | privacy domain |
|------+------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------|
| COL1 | DATE             | COLUMN | Y     | NULL    | N           | N          | NULL  | NULL       | NULL    | NULL        | NULL           |
| COL2 | TIMESTAMP_NTZ(9) | COLUMN | Y     | NULL    | N           | N          | NULL  | NULL       | NULL    | NULL        | NULL           |
| COL3 | TIMESTAMP_NTZ(9) | COLUMN | Y     | NULL    | N           | N          | NULL  | NULL       | NULL    | NULL        | NULL           |
+------+------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
INSERT INTO mytable
  SELECT
    TO_DATE('2013-05-08T23:39:20.123'),
    TO_TIMESTAMP('2013-05-08T23:39:20.123'),
    TO_TIMESTAMP('2013-05-08T23:39:20.123');

SELECT * FROM mytable;
Copy
+------------+-------------------------+-------------------------+
| COL1       | COL2                    | COL3                    |
|------------+-------------------------+-------------------------|
| 2013-05-08 | 2013-05-08 23:39:20.123 | 2013-05-08 23:39:20.123 |
+------------+-------------------------+-------------------------+

与前面的示例类似,但指定仅更新表中的第一列和第三列:

INSERT INTO mytable (col1, col3)
  SELECT
    TO_DATE('2013-05-08T23:39:20.123'),
    TO_TIMESTAMP('2013-05-08T23:39:20.123');

SELECT * FROM mytable;
Copy
+------------+-------------------------+-------------------------+
| COL1       | COL2                    | COL3                    |
|------------+-------------------------+-------------------------|
| 2013-05-08 | 2013-05-08 23:39:20.123 | 2013-05-08 23:39:20.123 |
| 2013-05-08 | NULL                    | 2013-05-08 23:39:20.123 |
+------------+-------------------------+-------------------------+

使用显式指定的值进行多行插入

创建 employees 表,然后通过在 VALUES 子句中以逗号分隔的列表中提供值组,将四行数据插入到该表中:

CREATE TABLE employees (
  first_name VARCHAR,
  last_name VARCHAR,
  workphone VARCHAR,
  city VARCHAR,
  postal_code VARCHAR);

INSERT INTO employees
  VALUES
    ('May', 'Franklin', '1-650-249-5198', 'San Francisco', 94115),
    ('Gillian', 'Patterson', '1-650-859-3954', 'San Francisco', 94115),
    ('Lysandra', 'Reeves', '1-212-759-3751', 'New York', 10018),
    ('Michael', 'Arnett', '1-650-230-8467', 'San Francisco', 94116);

SELECT * FROM employees;
Copy
+------------+-----------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+-----------+----------------+---------------+-------------|
| May        | Franklin  | 1-650-249-5198 | San Francisco | 94115       |
| Gillian    | Patterson | 1-650-859-3954 | San Francisco | 94115       |
| Lysandra   | Reeves    | 1-212-759-3751 | New York      | 10018       |
| Michael    | Arnett    | 1-650-230-8467 | San Francisco | 94116       |
+------------+-----------+----------------+---------------+-------------+

在多行插入中,请确保插入值的数据类型在各行之间保持一致,因为第一行的数据类型将用作指南。创建表并插入两行:

CREATE OR REPLACE TABLE demo_insert_type_mismatch (v VARCHAR);
Copy

第一次插入按预期工作:

INSERT INTO demo_insert_type_mismatch (v) VALUES
  ('three'),
  ('four');
Copy
+-------------------------+
| number of rows inserted |
|-------------------------|
|                       2 |
+-------------------------+

第二次插入失败,因为第二行 ('d') 中值的数据类型是字符串,不同于第一行 (3) 中值的数字数据类型。即使可以将两组值 强制转换 为VARCHAR(这是表中列的数据类型),插入也会失败。即使值 'd' 的数据类型与列 v 的数据类型相同,插入也会失败:

INSERT INTO demo_insert_type_mismatch (v) VALUES
  (3),
  ('d');
Copy
100038 (22018): DML operation to table DEMO_INSERT_TYPE_MISMATCH failed on column V with error: Numeric value 'd' is not recognized

当各行的数据类型一致时,插入成功,并且两个数值都被强制转换为 VARCHAR 数据类型:

INSERT INTO demo_insert_type_mismatch (v) VALUES
  (3),
  (4);
Copy
+-------------------------+
| number of rows inserted |
|-------------------------|
|                       2 |
+-------------------------+

使用查询进行多行插入

contractors 表中的多行数据插入到 employees 表中:

  • 仅选择 worknum 列中包含区号 650 的行。

  • city 列中插入 NULL 值。

SELECT * FROM employees;
Copy
+------------+-----------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+-----------+----------------+---------------+-------------|
| May        | Franklin  | 1-650-249-5198 | San Francisco | 94115       |
| Gillian    | Patterson | 1-650-859-3954 | San Francisco | 94115       |
| Lysandra   | Reeves    | 1-212-759-3751 | New York      | 10018       |
| Michael    | Arnett    | 1-650-230-8467 | San Francisco | 94116       |
+------------+-----------+----------------+---------------+-------------+
CREATE TABLE contractors (
  contractor_first VARCHAR,
  contractor_last VARCHAR,
  worknum VARCHAR,
  city VARCHAR,
  zip_code VARCHAR);

INSERT INTO contractors
  VALUES
    ('Bradley', 'Greenbloom', '1-650-445-0676', 'San Francisco', 94110),
    ('Cole', 'Simpson', '1-212-285-8904', 'New York', 10001),
    ('Laurel', 'Slater', '1-650-633-4495', 'San Francisco', 94115);

SELECT * FROM contractors;
Copy
+------------------+-----------------+----------------+---------------+----------+
| CONTRACTOR_FIRST | CONTRACTOR_LAST | WORKNUM        | CITY          | ZIP_CODE |
|------------------+-----------------+----------------+---------------+----------|
| Bradley          | Greenbloom      | 1-650-445-0676 | San Francisco | 94110    |
| Cole             | Simpson         | 1-212-285-8904 | New York      | 10001    |
| Laurel           | Slater          | 1-650-633-4495 | San Francisco | 94115    |
+------------------+-----------------+----------------+---------------+----------+
INSERT INTO employees(first_name, last_name, workphone, city, postal_code)
  SELECT contractor_first, contractor_last, worknum, NULL, zip_code
    FROM contractors
    WHERE CONTAINS(worknum,'650');

SELECT * FROM employees;
Copy
+------------+------------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME  | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+------------+----------------+---------------+-------------|
| May        | Franklin   | 1-650-249-5198 | San Francisco | 94115       |
| Gillian    | Patterson  | 1-650-859-3954 | San Francisco | 94115       |
| Lysandra   | Reeves     | 1-212-759-3751 | New York      | 10018       |
| Michael    | Arnett     | 1-650-230-8467 | San Francisco | 94116       |
| Bradley    | Greenbloom | 1-650-445-0676 | NULL          | 94110       |
| Laurel     | Slater     | 1-650-633-4495 | NULL          | 94115       |
+------------+------------+----------------+---------------+-------------+

使用公共表表达式将 contractors 表中的多行数据插入到 employees 表中:

INSERT INTO employees (first_name, last_name, workphone, city, postal_code)
  WITH cte AS
    (SELECT contractor_first AS first_name,
            contractor_last AS last_name,
            worknum AS workphone,
            city,
            zip_code AS postal_code
       FROM contractors)
  SELECT first_name, last_name, workphone, city, postal_code
    FROM cte;
Copy

使用源表中 id 列的 INNER JOIN 将两个表(emp_addremp_ph)中的列插入到第三个表 (emp) 中:

INSERT INTO emp (id, first_name, last_name, city, postal_code, ph)
  SELECT a.id, a.first_name, a.last_name, a.city, a.postal_code, b.ph
    FROM emp_addr a
    INNER JOIN emp_ph b ON a.id = b.id;
Copy

JSON 数据的多行插入

将两个 JSON 对象插入到表的 VARIANT 列中:

CREATE TABLE prospects (column1 VARIANT);

INSERT INTO prospects
  SELECT PARSE_JSON(column1)
  FROM VALUES
  ('{
    "_id": "57a37f7d9e2b478c2d8a608b",
    "name": {
      "first": "Lydia",
      "last": "Williamson"
    },
    "company": "Miralinz",
    "email": "lydia.williamson@miralinz.info",
    "phone": "+1 (914) 486-2525",
    "address": "268 Havens Place, Dunbar, Rhode Island, 02801"
  }')
  , ('{
    "_id": "57a37f7d622a2b1f90698c01",
    "name": {
      "first": "Denise",
      "last": "Holloway"
    },
    "company": "DIGIGEN",
    "email": "denise.holloway@digigen.net",
    "phone": "+1 (979) 587-3021",
    "address": "441 Dover Street, Ada, New Mexico, 87105"
  }');
Copy

使用 OVERWRITE 插入

此示例使用带有 OVERWRITE 的 INSERT,在将新记录添加到 employees 表后,从 employees 重新构建 sf_employees 表。

下面是两个表的初始数据:

SELECT * FROM employees;
Copy
+------------+-----------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+-----------+----------------+---------------+-------------|
| May        | Franklin  | 1-650-111-1111 | San Francisco | 94115       |
| Gillian    | Patterson | 1-650-222-2222 | San Francisco | 94115       |
| Lysandra   | Reeves    | 1-212-222-2222 | New York      | 10018       |
| Michael    | Arnett    | 1-650-333-3333 | San Francisco | 94116       |
+------------+-----------+----------------+---------------+-------------+
SELECT * FROM sf_employees;
Copy
+------------+-----------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+-----------+----------------+---------------+-------------|
| Mary       | Smith     | 1-650-999-9999 | San Francisco | 94115       |
+------------+-----------+----------------+---------------+-------------+

此语句使用 OVERWRITE 子句将行插入 sf_employees 表中:

INSERT OVERWRITE INTO sf_employees
  SELECT * FROM employees
  WHERE city = 'San Francisco';
Copy

因为 INSERT 使用了 OVERWRITE 子句,所以 sf_employees 中原来的行消失不见了:

SELECT * FROM sf_employees;
Copy
+------------+-----------+----------------+---------------+-------------+
| FIRST_NAME | LAST_NAME | WORKPHONE      | CITY          | POSTAL_CODE |
|------------+-----------+----------------+---------------+-------------|
| May        | Franklin  | 1-650-111-1111 | San Francisco | 94115       |
| Gillian    | Patterson | 1-650-222-2222 | San Francisco | 94115       |
| Michael    | Arnett    | 1-650-333-3333 | San Francisco | 94116       |
+------------+-----------+----------------+---------------+-------------+
语言: 中文