====== INSERT ====== .. container:: refentry :name: SQL-INSERT .. container:: titlepage .. container:: refnamediv .. rubric:: INSERT :name: insert INSERT — 在一个表中创建新行 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: synopsis [ WITH [ RECURSIVE ] with_query [, ...] ] INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ] [ OVERRIDING { SYSTEM | USER } VALUE ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] .. container:: refsect1 :name: id-1.9.3.152.5 .. rubric:: 描述 :name: 描述 ``INSERT``\ 将新行插入到一个表中。我们可以 插入一个或者更多由值表达式指定的行,或者插入来自一个查询的零行 或者更多行。 目标列的名称可以以任意顺序列出。如果没有给出列名列表,则有两种确定 目标列的可能性。第一种是以被声明的顺序列出该表的所有列。另一种可能 性是,如果\ ``VALUES`` 子句或者\ *``query``*\ 只提 供\ *``N``*\ 个列,则以被声明的顺序列出该表的前 *``N``*\ 列。\ ``VALUES`` 子句或者 *``query``*\ 提供的值会被从左至右关联到这些显式或者隐式 给出的目标列。 每一个没有出现在显式或者隐式列列表中的列都将被默认填充,如果为该列 声明过默认值则用默认值填充,否则用空值填充。 如果任意列的表达式不是正确的数据类型,将会尝试自动类型转换。 可选的\ ``RETURNING``\ 子句让\ ``INSERT``\ 根据 实际被插入的每一行来计算和返回值。这主要用来获取由默认值提供 的值,例如一个序列号。不过,允许在其中包括使用该表列的任何表达式。 ``RETURNING``\ 列表的语法与\ ``SELECT``\ 的输出 列表的相同。只有被成功地插入的行才将被返回。 为了向表中插入,你必须具有其上的\ ``INSERT``\ 特权。 如果一个列列表被指定,你只需要其中的列上的\ ``INSERT`` 特权。 使用\ ``RETURNING``\ 子句需要\ ``RETURNING``\ 中提到的所有列的 ``SELECT``\ 权限。     如果使用\ *``query``*\ 子句从查询中插入行, 则当然需要对查询中使用的任何表或列具有\ ``SELECT``\ 权限。 .. container:: refsect1 :name: id-1.9.3.152.6 .. rubric:: 参数 :name: 参数 .. container:: refsect2 :name: SQL-INSERTING-PARAMS .. rubric:: 插入 :name: 插入 这个小节介绍了在只插入新行时可以使用的参数。 .. container:: variablelist *``with_query``* ``WITH``\ 子句允许指定一个或者更多子查询,在 ``INSERT``\ 查询中可以用名称引用这些子查询。详见 `第 7.8 节 `__\ 以及\ `SELECT `__\ 。 *``query``* (\ ``SELECT``\ 语句)也可以包含一个 ``WITH``\ 子句。在这种情况下 *``query``*\ 中可以引用 两组\ *``with_query``*\ ,但是第二个优先级更 高(因为它被嵌套更近)。 *``table_name``* 一个已有表的名称(可以被模式限定)。 *``alias``* *``table_name``* 的替补名称。当提供了一个别名时,它会完全隐藏掉表的实际名称。 当\ ``ON CONFLICT DO UPDATE``\ 的目标是一个\ ``被排除的``\ 表时这特别有用,因为那将被当作表示要被插入行的特殊表的名称。 *``column_name``* 名为\ *``table_name``*\ 的表中的一个列 的名称。如有必要,列名可以用一个子域名或者数组下标限定(指向 一个组合列的某些列中插入会让其他域为空)。当用 ``ON CONFLICT DO UPDATE``\ 引用一列时,不要在一个 目标列的说明中国包括表名。例如, ``INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1``\ 是非法的(这遵循\ ``UPDATE`` 的一般行为)。 ``OVERRIDING SYSTEM VALUE`` 如果没有这个子句,为定义为\ ``GENERATED ALWAYS``\ 的标识列指定一个明确的值(不是\ ``DEFAULT``\ )就是一种错误。这个子句推翻了这种限制。 ``OVERRIDING USER VALUE`` 如果指定这个子句,则会忽略提供给定义为\ ``GENERATED BY DEFAULT``\ 的标识列的值,并且应用默认的由序列生成的值。 例如,当在表之间拷贝值时,这个子句有能派上用场。\ ``INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1``\ 将从\ ``tbl1``\ 中拷贝所有在\ ``tbl2``\ 中不是标识列的列,而\ ``tbl2``\ 中标识列的值将由与\ ``tbl2``\ 关联的序列产生。 ``DEFAULT VALUES`` 所有列都将被其默认值填充(例如这种形式下不允许\ ``OVERRIDING``\ 子句)。 *``expression``* 要赋予给相应列的表达式或者值。 ``DEFAULT`` 相应的列将被其默认值填充。 *``query``* 提供要被插入行的查询(\ ``SELECT``\ 语句)。 其语法描述请参考\ `SELECT `__\ 语句。 *``output_expression``* 在每一行被插入或更新后由\ ``INSERT``\ 命令计算并且返回的 表达式。该表达式可以使用\ *``table_name``* 指定的表中的任何列。写成\ ``*``\ 可返回被插入或更新行的所有列。 *``output_name``* 要用于被返回列的名称。 .. container:: refsect1 :name: id-1.9.3.152.7 .. rubric:: 输出 :name: 输出 成功完成时,\ ``INSERT``\ 命令会返回以下形式的命令标签: .. code:: screen INSERT oid count *``count``*\ 是被插入或更新的行数。 *``oid``*\ 总是0(过去,如果\ *``count``*\ 恰好为1, 并且目标表被声明为\ ``WITH OIDS``\ ,则它是分配给插入行的OID, 否则为0, 但现在已不再支持创建\ ``WITH OIDS``\ 表)。 如果\ ``INSERT``\ 命令包含\ ``RETURNING``\ 子句, 其结果会类似于包含\ ``RETURNING``\ 列表中定义的列和值的 ``SELECT``\ 语句,这些结果是由该命令在被插入或更新行上 计算得到。 .. container:: refsect1 :name: id-1.9.3.152.8 .. rubric:: 注解 :name: 注解 如果指定的表是一个分区表,每一行都会被路由到合适的分区并且插入其中。如果指定的表是一个分区,如果输入行之一违背该分区的约束则将发生错误。 .. container:: refsect1 :name: id-1.9.3.152.9 .. rubric:: 示例 :name: 示例 向\ ``films``\ 中插入一行: .. code:: programlisting INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); 在这个例子中,\ ``len``\ 列被省略并且因此会具有默认值: .. code:: programlisting INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama'); 这个例子为日期列使用\ ``DEFAULT``\ 子句而不是指定一个值: .. code:: programlisting INSERT INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'); INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama'); 插入一个完全由默认值构成的行: .. code:: programlisting INSERT INTO films DEFAULT VALUES; 用多行\ ``VALUES``\ 语法插入多个行: .. code:: programlisting INSERT INTO films (code, title, did, date_prod, kind) VALUES ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); 这个例子从表\ ``tmp_films``\ 中获得一些行插入到表 ``films``\ 中,两个表具有相同的列布局: .. code:: programlisting INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; 这个例子插入数组列: .. code:: programlisting -- 为 noughts-and-crosses 游戏创建一个空的 3x3 棋盘 INSERT INTO tictactoe (game, board[1:3][1:3]) VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}'); -- 实际上可以不用上面例子中的下标 INSERT INTO tictactoe (game, board) VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}'); 向表\ ``distributors``\ 中插入一行,返回由 ``DEFAULT``\ 子句生成的序号: .. code:: programlisting INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did; 增加为 Acme Corporation 管理账户的销售人员的销量,并且把整个被 更新的行以及当前时间记录到一个日志表中: .. code:: programlisting WITH upd AS ( UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation') RETURNING * ) INSERT INTO employees_log SELECT *, current_timestamp FROM upd; .. container:: refsect1 :name: id-1.9.3.152.10 .. rubric:: 兼容性 :name: 兼容性 ``INSERT``\ 符合 SQL 标准,不过 ``RETURNING``\ 子句是一种 OushuDB 扩展, 在 ``INSERT``\ 中使用\ ``WITH``\ 也是。 还有,标准不允许省略列名列表但不通过 ``VALUES``\ 子句或者\ *``query``*\ 填充 所有列的情况。 SQL标准指定只有存在一个总是会生成值的标识列时才能指定\ ``OVERRIDING SYSTEM VALUE``\ 。而 OushuDB 在任何情况下都允许这个子句,并且在不适用时会忽略它。 *``query``*\ 子句可能的限制在 `SELECT `__\ 有介绍。