CREATE FOREIGN TABLE — 定义一个新的外部表
CREATE FOREIGN TABLE [ IF NOT EXISTS ]table_name( [ {column_namedata_type[ OPTIONS (option'value' [, ... ] ) ] [ COLLATEcollation] [column_constraint[ ... ] ] |table_constraint| LIKEsource_table[like_option... ] } [, ... ] ] ) [ INHERITS (parent_table[, ... ] ) ] SERVERserver_name[ OPTIONS (option'value' [, ... ] ) ] CREATE FOREIGN TABLE [ IF NOT EXISTS ]table_namePARTITION OFparent_table[ ( {column_name[ WITH OPTIONS ] [column_constraint[ ... ] ] |table_constraint} [, ... ] ) ] { FOR VALUESpartition_bound_spec| DEFAULT } SERVERserver_name[ OPTIONS (option'value' [, ... ] ) ] wherecolumn_constraintis: [ CONSTRAINTconstraint_name] { NOT NULL [ NO INHERIT ] | NULL | CHECK (expression) [ NO INHERIT ] | DEFAULTdefault_expr| GENERATED ALWAYS AS (generation_expr) [ STORED | VIRTUAL ] } [ ENFORCED | NOT ENFORCED ] andtable_constraintis: [ CONSTRAINTconstraint_name] { NOT NULLcolumn_name[ NO INHERIT ] | CHECK (expression) [ NO INHERIT ] } [ ENFORCED | NOT ENFORCED ] andlike_optionis: { INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | STATISTICS | ALL } andpartition_bound_specis: IN (partition_bound_expr[, ...] ) | FROM ( {partition_bound_expr| MINVALUE | MAXVALUE } [, ...] ) TO ( {partition_bound_expr| MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUSnumeric_literal, REMAINDERnumeric_literal)
CREATE FOREIGN TABLE 在当前数据库中创建一个新的外部表。该表将由发出该命令的用户拥有。
如果给定了模式名(例如,CREATE FOREIGN TABLE myschema.mytable ...),那么该表会被创建在指定的模式中。否则,它会被创建在当前模式中。外部表的名称必须与同一模式中任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。
CREATE FOREIGN TABLE 还会自动创建一个数据类型,用来表示与该外部表的一行相对应的复合类型。因此,外部表不能与同一模式中任何现有数据类型同名。
如果指定了 PARTITION OF 子句,那么该表会作为 parent_table 的一个分区被创建,并带有指定的边界。
要能够创建外部表,你必须在外部服务器上拥有 USAGE 特权,并且对该表中使用的所有列类型也拥有 USAGE 特权。
IF NOT EXISTS如果已经存在同名的关系,则不抛出错误。在这种情况下会发出一个通知。注意,无法保证现有的关系与将要创建的关系有任何相似之处。
table_name要创建的表的名称(可选带模式限定)。
column_name要在新表中创建的列的名称。
data_type该列的数据类型。其中可以包含数组说明符。有关 PostgreSQL 支持的数据类型的更多信息,请参阅 Chapter 8。
COLLATE collation COLLATE 子句为该列分配一个排序规则(该列必须是可排序的数据类型)。如果没有指定,则使用该列数据类型的默认排序规则。
INHERITS ( parent_table [, ... ] ) 可选的 INHERITS 子句指定一个表的列表,新的外部表会自动继承这些表的所有列。父表可以是普通表或外部表。更多细节请参见 CREATE TABLE 中类似形式的说明。
PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT } 这种形式可用于把外部表创建为给定父表的一个分区,并带有指定的分区边界值。更多细节请参见 CREATE TABLE 中类似形式的说明。注意,如果父表上存在 UNIQUE 索引,则当前不允许把外部表创建为该父表的分区。(另请参见 ALTER TABLE ATTACH PARTITION。)
LIKE source_table [ like_option ... ] LIKE 子句指定一个表,新表会自动从该表复制所有列名、列的数据类型以及非空约束。
与 INHERITS 不同,创建完成后新表与原表是完全解耦的。对原表的更改不会被应用到新表上,并且在扫描原表时也无法包含新表的数据。
同样与 INHERITS 不同的是,由 LIKE 复制的列和约束不会与同名的列和约束合并。如果显式指定了相同的名称,或者在另一个 LIKE 子句中出现了相同的名称,则会报错。
可选的 like_option 子句指定要复制原表的哪些额外属性。指定 INCLUDING 表示复制该属性,指定 EXCLUDING 表示省略该属性。默认为 EXCLUDING。如果对同一类对象做了多次指定,将使用最后一次的指定。可用的选项有:
INCLUDING COMMENTS被复制的列、约束以及扩展统计信息上的注释将会被复制。默认行为是排除注释,因此新表中对应的对象将没有任何注释。
INCLUDING CONSTRAINTS CHECK 约束会被复制。列约束和表约束之间不做区分。非空约束总是会被复制到新表中。
INCLUDING DEFAULTS 被复制列定义的默认表达式会被复制。否则,默认表达式不会被复制,这会导致新表中被复制的列的默认值为空。注意,复制那些调用数据库修改函数(例如 nextval)的默认值,可能会在原表和新表之间建立一种功能上的关联。
INCLUDING GENERATED被复制列定义的所有生成表达式都会被复制。默认情况下,新列将是普通的基础列。
INCLUDING STATISTICS扩展统计信息会被复制到新表中。
INCLUDING ALL INCLUDING ALL 是一种简写形式,它会选择所有可用的单独选项。(在 INCLUDING ALL 之后写出单独的 EXCLUDING 子句,以选择除某些特定选项之外的所有选项,这可能很有用。)
CONSTRAINT constraint_name 列约束或表约束的可选名称。如果违反了约束,约束名称会出现在错误消息中,因此像 col must be positive 这样的约束名称可以用来向客户端应用传达有用的约束信息。(指定包含空格的约束名称时需要使用双引号。)如果没有指定约束名称,系统会生成一个名称。
NOT NULL [ NO INHERIT ]该列不允许包含空值。
标记为 NO INHERIT 的约束不会传播到子表。
NULL该列允许包含空值。这是默认设置。
提供该子句只是为了与非标准 SQL 数据库兼容。不建议在新应用中使用它。
CHECK ( expression ) [ NO INHERIT ] CHECK 子句指定一个产生布尔结果的表达式,外部表中的每一行都应满足该表达式;也就是说,对于外部表中的所有行,该表达式的结果应该是 TRUE 或 UNKNOWN,而绝不能是 FALSE。指定为列约束的检查约束应该只引用该列的值,而出现在表约束中的表达式则可以引用多个列。
目前,CHECK 表达式不能包含子查询,也不能引用当前行中列以外的变量。可以引用系统列 tableoid,但不能引用其他任何系统列。
标记为 NO INHERIT 的约束不会传播到子表。
DEFAULT
default_expr DEFAULT 子句为它所在的列定义所对应的列指定一个默认数据值。该值可以是任何不含变量的表达式(不允许使用子查询,也不允许交叉引用当前表中的其他列)。默认表达式的数据类型必须与该列的数据类型匹配。
在任何没有为该列指定值的插入操作中都会使用该默认表达式。如果某列没有默认值,那么其默认值就是空值。
GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ]该子句将该列创建为一个生成列。这种列不能被写入,读取时将返回指定表达式的结果。
当指定了 VIRTUAL 时,该列将在被读取时计算。(外部数据封装器会在新行中把它看作空值,并且可以选择将它作为空值存储,或者完全忽略它。)当指定了 STORED 时,该列将在写入时计算。(计算出的值会被交给外部数据封装器进行存储,并且必须在读取时返回。)默认为 VIRTUAL。
生成表达式可以引用表中的其他列,但不能引用其他生成列。所使用的任何函数和操作符都必须是不可变的。不允许引用其他表。
server_name供该外部表使用的现有外部服务器的名称。有关定义服务器的详细信息,请参见 CREATE SERVER。
OPTIONS ( option 'value' [, ...] )与新外部表或其某一列相关联的选项。允许的选项名称和值特定于每个外部数据封装器,并通过该外部数据封装器的验证器函数进行验证。不允许重复的选项名称(不过表选项和列选项使用相同的名称是可以的)。
外部表上的约束(例如 CHECK 或 NOT NULL 子句)不会被 PostgreSQL 核心系统强制执行,大多数外部数据封装器也不会尝试强制执行它们;也就是说,约束只是被假定为成立。这样的强制执行意义不大,因为它只会应用于通过外部表插入或更新的行,而不会应用于通过其他方式修改的行,例如直接在远程服务器上修改的行。相反,附加在外部表上的约束应该表示一个由远程服务器正在强制执行的约束。
某些专用的外部数据封装器可能是其所访问数据的唯一访问机制,在这种情况下,由外部数据封装器自身来执行约束强制可能是合适的。但是,除非封装器的文档中说明了这一点,否则你不应该假定封装器会这样做。
尽管 PostgreSQL 不会尝试强制执行外部表上的约束,但为了进行查询优化,它会假定这些约束是正确的。如果外部表中存在不满足已声明约束的可见行,对该表的查询可能会产生错误或不正确的结果。确保约束定义符合实际情况是用户的责任。
当外部表被用作分区表的分区时,存在一个隐式约束,即其内容必须满足分区规则。同样,确保这一点成立也是用户的责任,最好的做法是在远程服务器上安装一个匹配的约束。
在包含外部表分区的分区表中,如果外部数据封装器支持元组路由,那么改变分区键值的 UPDATE 可能会导致一行从本地分区移动到外部表分区。但是,目前无法把一行从外部表分区移动到另一个分区。假如该分区约束在远程服务器上得到了正确的强制执行,那么需要这样做的 UPDATE 将会因为这个分区约束而失败。
类似的考虑也适用于生成列。存储型生成列会在本地 PostgreSQL 服务器上于插入或更新时计算,并被交给外部数据封装器以写出到外部数据存储中,但并不会强制要求外部表的查询为存储型生成列返回与生成表达式一致的值。同样,这可能导致不正确的查询结果。
创建外部表 films,它将通过服务器 film_server 来访问:
CREATE FOREIGN TABLE films (
code char(5) NOT NULL,
title varchar(40) NOT NULL,
did integer NOT NULL,
date_prod date,
kind varchar(10),
len interval hour to minute
)
SERVER film_server;
创建外部表 measurement_y2016m07,它将通过服务器 server_07 来访问,并作为范围分区表 measurement 的一个分区:
CREATE FOREIGN TABLE measurement_y2016m07
PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01')
SERVER server_07;
CREATE FOREIGN TABLE 命令在很大程度上符合 SQL 标准;不过,与 CREATE TABLE 的情况很类似,NULL 约束和零列的外部表是允许的。指定列默认值的能力也是 PostgreSQL 的扩展。以 PostgreSQL 所定义形式出现的表继承是非标准的。该命令所支持的 LIKE 子句也是非标准的。