ALTER TABLE APPEND
通过从现有的源表移动数据,将行附加到目标表。源表中的数据将移到目标表中的匹配列。列的顺序不重要。在成功将数据附加到目标表后,源表变成空表。由于是移动数据而不是复制数据,因此相比类似的 CREATE TABLE AS 或 INSERT INTO 操作,ALTER TABLE APPEND 通常要快得多。
注意
ALTER TABLE APPEND 在源表和目标表之间移动数据块。为了提高性能,ALTER TABLE APPEND 不作为 append 操作的一部分压缩存储。因此,存储使用率会临时增加。要回收空间,请运行 VACUUM 操作。
同名的列还必须具有相同的列属性。如果源表包含目标表中不存在的列(反之亦然),请使用 IGNOREEXTRA 或 FILLTARGET 参数来指定如何管理额外的列。
您不能附加身份列。如果两个表中均包括身份列,则命令会失败。如果只有一个表具有标识列,请包含 FILLTARGET 或 IGNOREEXTRA 参数。有关更多信息,请参阅 ALTER TABLE APPEND 使用说明。
您可以附加 GENERATED BY DEFAULT AS IDENTITY 列。您可以使用您提供的值来更新定义为 GENERATED BY DEFAULT AS IDENTITY 的列。有关更多信息,请参阅 ALTER TABLE APPEND 使用说明。
目标表必须是永久表。但是,源可以是永久表,也可以是配置为流式摄取的实体化视图。如果一个对象定义了分配方式和分配键,则两个对象必须使用相同的分配方式和分配键。如果对对象进行排序,则两个对象必须使用相同的排序方式并定义相同的列作为排序键。
在操作完成之后,ALTER TABLE APPEND 会立即自动提交。该命令不能回滚。您不能在事务数据块 (BEGIN ... END) 中运行 ALTER TABLE APPEND。有关事务的更多信息,请参阅 可序列化的隔离。
所需的权限
根据具体的 ALTER TABLE APPEND 命令,需要以下权限之一:
Superuser
具有 ALTER TABLE 系统权限的用户
具有源表的 DELETE 和 SELECT 权限以及目标表的 INSERT 权限的用户
语法
ALTER TABLE target_table_name APPEND FROM [ source_table_name | source_materialized_view_name ] [ IGNOREEXTRA | FILLTARGET ]
从实体化视图进行追加仅在实体化视图配置为流式摄取到实体化视图的情形下才有效。
参数
- target_table_name
-
要将行附加到的表的名称。只指定表的名称,或者通过格式 schema_name.table_name 使用特定 schema。目标表必须是现有的永久表。
- FROM source_table_name
-
提供要附加的行的表的名称。只指定表的名称,或者通过格式 schema_name.table_name 使用特定 schema。源表必须是现有的永久表。
- FROM source_materialized_view_name
-
提供要附加的行的实体化视图的名称。从实体化视图进行追加仅在实体化视图配置为流式摄取到实体化视图的情形下才有效。源实体化视图必须已经存在。
- IGNOREEXTRA
-
这个关键字指定,如果源表中包含目标表中不存在的列,则应该放弃额外列中的数据。您不能将 IGNOREEXTRA 与 FILLTARGET 配合使用。
- FILLTARGET
-
这个关键字指定,如果目标表中包含源表中不存在的列,则应该使用 DEFAULT 列值(如果已定义列值;否则使用 NULL 值)填充这些列。您不能将 IGNOREEXTRA 与 FILLTARGET 配合使用。
ALTER TABLE APPEND 使用说明
ALTER TABLE APPEND 仅将相同列从源表移到目标表。列的顺序不重要。
如果源表或目标表包含额外的列,则根据以下规则使用 FILLTARGET 或 IGNOREEXTRA:
-
如果源表包含目标表中不存在的列,则包含 IGNOREEXTRA。该命令会忽略源表中额外的列。
-
如果目标表包含源表中不存在的列,则包含 FILLTARGET。该命令使用默认列值或 IDENTITY 值(如果已定义列值;否则使用 NULL 值)填充目标表中的额外列。
-
如果源表和目标表均包含额外的列,则该命令失败。您不能同时使用 FILLTARGET 和 IGNOREEXTRA。
如果两个表中的某个列具有相同名称,但具有不同的属性,则该命令失败。名称类似的列必须具有以下共同的属性:
-
数据类型
-
列大小
-
压缩编码
-
非 Null
-
排序方式
-
排序键列
-
分配方式
-
分配键列
您不能附加身份列。如果源表和目标表中均具有身份列,则该命令失败。如果只有源表具有身份列,则包含 IGNOREEXTRA 参数以忽略身份列。如果只有目标表具有身份列,则包含 FILLTARGET 参数,以便根据为该表定义的 IDENTITY 子句来填充身份列。有关更多信息,请参阅 DEFAULT。
您可以使用 ALTER TABLE APPEND 语句附加默认身份列。有关更多信息,请参阅 CREATE TABLE。
ALTER TABLE APPEND 示例
假设您的组织维护表 SALES_MONTHLY 来获取当前销售交易。您希望每个月将数据从交易表移动到 SALES 表。
您可以使用下面的 INSERT INTO 和 TRUNCATE 命令来完成任务。
insert into sales (select * from sales_monthly); truncate sales_monthly;
不过,您可以使用 ALTER TABLE APPEND 命令执行相同的操作,而且效率要高得多。
首先,查询 PG_TABLE_DEF 系统目录表,验证两个表中包含具有相同列属性的相同列。
select trim(tablename) as table, "column", trim(type) as type, encoding, distkey, sortkey, "notnull" from pg_table_def where tablename like 'sales%'; table | column | type | encoding | distkey | sortkey | notnull -----------+------------+-----------------------------+----------+---------+---------+-------- sales | salesid | integer | lzo | false | 0 | true sales | listid | integer | none | true | 1 | true sales | sellerid | integer | none | false | 2 | true sales | buyerid | integer | lzo | false | 0 | true sales | eventid | integer | mostly16 | false | 0 | true sales | dateid | smallint | lzo | false | 0 | true sales | qtysold | smallint | mostly8 | false | 0 | true sales | pricepaid | numeric(8,2) | delta32k | false | 0 | false sales | commission | numeric(8,2) | delta32k | false | 0 | false sales | saletime | timestamp without time zone | lzo | false | 0 | false salesmonth | salesid | integer | lzo | false | 0 | true salesmonth | listid | integer | none | true | 1 | true salesmonth | sellerid | integer | none | false | 2 | true salesmonth | buyerid | integer | lzo | false | 0 | true salesmonth | eventid | integer | mostly16 | false | 0 | true salesmonth | dateid | smallint | lzo | false | 0 | true salesmonth | qtysold | smallint | mostly8 | false | 0 | true salesmonth | pricepaid | numeric(8,2) | delta32k | false | 0 | false salesmonth | commission | numeric(8,2) | delta32k | false | 0 | false salesmonth | saletime | timestamp without time zone | lzo | false | 0 | false
接下来,查看每个表的大小。
select count(*) from sales_monthly; count ------- 2000 (1 row) select count(*) from sales; count ------- 412,214 (1 row)
现在运行以下 ALTER TABLE APPEND 命令。
alter table sales append from sales_monthly;
再次查看每个表的大小。SALES_MONTHLY 表现在包含 0 行;而 SALES 表增长了 2000 行。
select count(*) from sales_monthly; count ------- 0 (1 row) select count(*) from sales; count ------- 414214 (1 row)
如果源表中的列多于目标表,请指定 IGNOREEXTRA 参数。以下示例使用 IGNOREEXTRA 参数,这样在附加到 SALES 表时,会忽略 SALES_LISTING 表中的额外列。
alter table sales append from sales_listing ignoreextra;
如果目标表中的列多于源表,请指定 FILLTARGET 参数。以下示例使用 FILLTARGET 参数,以填充 SALES_REPORT 表中存在而 SALES_MONTH 表中不存在的列。
alter table sales_report append from sales_month filltarget;
以下示例显示了在实体化视图作为源的情况下如何使用 ALTER TABLE APPEND 的示例。
ALTER TABLE target_tbl APPEND FROM my_streaming_materialized_view;
此示例中的表和实体化视图名称是示例。从实体化视图进行追加仅在实体化视图配置为流式摄取到实体化视图的情形下才有效。它将源实体化视图中的所有记录移动到与实体化视图具有相同架构的目标表中,并保持实体化视图不变。这与数据来源为表时的行为相同。