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 #会复制被复制列定义中的默认表达式。否则默认表达式不会复制,因此新表中复制出的列默认值为 null。注意,复制会调用数据库修改函数(如 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子句为其所在列指定默认数据值。该值是一个不含变量的表达式(特别是,不允许引用当前表中的其他列)。子查询也不允许。默认值表达式的数据类型必须匹配列的数据类型。
默认值表达式会用于任何未为该列指定值的插入操作。如果一列没有默认值,则默认值为 null。
GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] #此子句将列创建为生成列。列不可写入,读取时会返回指定表达式的结果。
指定VIRTUAL时,列会在读取时计算。(外部数据包装器会将它视为新行中的空值,并且可以选择将其存储为空值或完全忽略它。)指定STORED时,列会在写入时计算。(计算出的值会提供给外部数据包装器存储,并且读取时必须返回该值。)默认是VIRTUAL。
生成表达式可以引用表中的其他列,但不能引用其他生成列。使用的任何函数和操作符都必须是不可变的。不允许引用其他表。
server_name #用于该外部表的现有外部服务器的名称。有关定义服务器的细节,参见CREATE SERVER。
OPTIONS ( option 'value' [, ...] ) #要与新外部表或其某一列关联的选项。允许的选项名和值都取决于具体的外部数据包装器,并使用该外部数据包装器的验证器函数进行验证。不允许重复的选项名(不过表选项和列选项同名是允许的)。
核心PostgreSQL系统不会强制执行外部表上的约束(例如CHECK或NOT NULL子句),而且大多数外部数据包装器也不会尝试强制执行它们;也就是说,这些约束只是被假定为真。因为这种强制执行只会适用于通过外部表插入或更新的行,而不会适用于通过其他方式修改的行,例如直接在远程服务器上修改的行,所以这样做意义不大。相反,附加到外部表上的约束应当表示由远程服务器强制执行的约束。
某些专用的外部数据包装器可能是其所访问数据的唯一访问机制,在这种情况下,由外部数据包装器自身执行约束检查也许是合适的。但除非其文档明确说明,否则不应假定某个包装器会这样做。
尽管PostgreSQL不会尝试强制执行外部表上的约束,但出于查询优化的目的,它会假定这些约束是正确的。如果外部表中存在不满足已声明约束的可见行,那么对该表的查询可能会产生错误或不正确的结果。确保约束定义符合实际情况是用户的责任。
当外部表被用作分区表的一个分区时,会有一个隐含约束,即其内容必须满足分区规则。同样,确保这一点是用户的责任,最好的做法是在远程服务器上安装匹配的约束。
在包含外部表分区的分区表中,如果外部数据包装器支持元组路由,那么更改分区键值的UPDATE可能导致某一行从本地分区移动到外部表分区。然而,目前还不能将一行从外部表分区移动到另一个分区。需要这样做的UPDATE会因为分区约束而失败,前提是假定远程服务器已正确强制执行该约束。
对生成列也有类似的考虑。存储型生成列会在本地PostgreSQL服务器上于插入或更新时计算,并交给外部数据包装器写入外部数据存储,但并不会强制要求查询外部表时返回的存储型生成列值与生成表达式保持一致。这同样可能导致不正确的查询结果。
创建通过服务器film_server访问的外部表films:
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;
创建通过服务器server_07访问的外部表measurement_y2016m07,并将其作为范围分区表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子句也是非标准的。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。