==================== CREATE FOREIGN TABLE ==================== .. container:: refentry :name: SQL-CREATEFOREIGNTABLE .. container:: titlepage .. container:: refnamediv .. rubric:: CREATE FOREIGN TABLE :name: create-foreign-table CREATE FOREIGN TABLE — 定义一个新的外部表 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: synopsis CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ OPTIONS ( option 'value' [, ... ] ) ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] SERVER server_name [ OPTIONS ( option 'value' [, ... ] ) ] CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name PARTITION OF parent_table [ ( { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] partition_bound_spec SERVER server_name [ OPTIONS ( option 'value' [, ... ] ) ] 其中 column_constraint 是: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED } 而 table_constraint 是: [ CONSTRAINT constraint_name ] CHECK ( expression ) [ NO INHERIT ] .. container:: refsect1 :name: SQL-CREATEFOREIGNTABLE-DESCRIPTION .. rubric:: 描述 :name: 描述 ``CREATE FOREIGN TABLE``\ 在当前数据库中创建 一个新的外部表。该表将由发出这个命令的用户所拥有。 如果给定了一个模式名称(例如\ ``CREATE FOREIGN TABLE myschema.mytable ...``\ ),那么该表会被创建在指定的模式中。 否则它会被创建在当前模式中。该外部表的名称必须与同一个模式中 的任何其他外部表、表、序列、索引、视图或者物化视图区分开来。 ``CREATE FOREIGN TABLE``\ 还将自动创建 一个数据类型来表示该外部表行相应的组合类型。因此,外部表不能和 同一个模式中任何现有的数据类型同名。 如果指定了\ ``PARTITION OF``\ 子句, 则该表被创建为具有指定边界的\ ``parent_table``\ 的分区。 要创建一个外部表,你必须具有该外部服务器上的\ ``USAGE`` 特权,以及该表中用到的所有列类型上的\ ``USAGE``\ 特权。 .. container:: refsect1 :name: id-1.9.3.66.6 .. rubric:: 参数 :name: 参数 .. container:: variablelist ``IF NOT EXISTS`` 已经存在同名关系时不要抛出错误。这种情况下会发出一个提示。注意, 并不保证已经存在的关系与将要创建的那一个相似。 *``table_name``* 要创建的表的名称(可以被模式限定)。 *``column_name``* 要在新表中创建的列名。 *``data_type``* 该列的数据类型。可以包括数组指示符。 ``COLLATE collation`` ``COLLATE``\ 子句为该列(必须是一个可排序的数据类型) 赋予一个排序规则。如果没有指定,则会使用该列的数据类型的默认 排序规则。 ``INHERITS ( parent_table`` [, ... ] ) 可选的\ ``INHERITS``\ 子句指定了一个表的列表,新的外部表 会自动从中继承所有列。父表可以是普通表或者外部表。详见 `CREATE TABLE `__\ 的类似形式。 ``PARTITION OF parent_table`` FOR VALUES *``partition_bound_spec``* 此语句可以用来将外部表创建为父表的一个指定区间的分区表。 详见\ `CREATE TABLE `__\ 的类似形式。 注意如果父表存在\ ``UNIQUE``\ 类型的索引时,当前是不允许将外部表 创建为该父表的分区表。(另见 ```ALTER TABLE ATTACH PARTITION`` `__\ 。) ``CONSTRAINT constraint_name`` 一个可选的用于列或者表约束的名字。如果该约束被违背,这个约束名字会 出现在错误消息中,这样\ ``col must be positive``\ 这种约束名就 可以被用来与客户端应用交流有用的约束信息(指定包含空格的约束名需要 使用双引号)。如果没有指定约束名,系统会自动生成一个。 ``NOT NULL`` 该列不允许包含空值。 ``NULL`` 该列可以包含空值,这是默认值。 提供这个子句只是为了兼容非标准的 SQL 数据库。在新的应用中 不鼓励使用它。 ``CHECK ( expression`` ) [ NO INHERIT ] ``CHECK``\ 子句指定一个产生布尔结果的表达式,该外部表 中的每一行都应该满足该表达式。也就是说,对于该外部表中所有的行, 这个表达式应该产生 TRUE 或者 UNKNOWN 而不能产生 FALSE。被 作为列约束指定的检查约束应该只引用该列的值,而出现在表约束中的 表达式可以引用多列。 当前,\ ``CHECK``\ 表达式不能包含子查询,也不能 引用除当前行的列之外的其他变量。可以引用系统列 ``tableoid``\ ,但是不能引用其他系统列。 被标记为\ ``NO INHERIT``\ 的约束将不会传播到子表上。 ``DEFAULT default_expr`` ``DEFAULT``\ 子句为包含它的列定义赋予一个默认数据值。该 值是任意不包含变量的表达式(不允许子查询和对当前表中其他列的交叉 引用)。默认值表达式的数据类型必须匹配列的数据类型。 默认值表达式将被用在任何没有指定列值的插入操作中。如果一列没有 默认值,则默认值为空值。 ``GENERATED ALWAYS AS ( generation_expr`` ) STORED 该子句创建一个\ *生成列*\ 。 此列不能写入,只能在读取时返回所指定的表达式的值。 关键字\ ``STORED``\ 是必须的,用来表明该列将在写入时计算。 (计算出的值将会传递给外部数据封装器负责保存,并在读取时返回。) 生成表达式可以引用表中的其他列,但不能引用其他的生成列。 所使用的函数和操作符必须是不可变。 不能引用其他表。 *``server_name``* 要用于该外部表的一个现有外部服务器的名称。有关定义一个服务器 的细节可以参考\ `CREATE SERVER `__\ 。 ``OPTIONS ( option`` '*``value``*' [, ...] ) 要与新外部表或者它的一个列相关联的选项。被允许的选项名称和值是与 每一个外部数据包装器相关的,并且它们会被该外部数据包装器的验证器 函数验证。不允许重复的选项名称(不过一个表选项和一个列选项重名是 可以的)。 .. container:: refsect1 :name: id-1.9.3.66.7 .. rubric:: 注解 :name: 注解 PostgreSQL核心系统不会强制外部表上的约束( 例如\ ``CHECK``\ 或\ ``NOT NULL``\ 子句),大部分外部 数据包装器也不会尝试强制它们。也就是说,这类约束会被简单地认为保持 为真。这种强制其实没什么意义,因为它只适用于通过该外部表插入或者更 新的行,而对通过其他方式修改的行(例如直接在远程服务器上修改)没有 作用。附着在外部表上的约束应该表示由外部服务器强制的一个约束。 有些特殊目的的外部数据包装器可能是它们所访问的数据的唯一一种访问 机制,在那种情况下让外部数据包装器自己来执行约束强制可能是合适的。 但是不应该假设包装器会这样做,除非它的文档说它会。 尽管PostgreSQL不会尝试强制外部表上的约束, 但它确实假定它们对于查询优化的目的是正确的。如果在外部表中有不 满足约束的行可见,在该表上的查询可能会产生不正确的回答。确保 约束定义符合实际是用户的责任。 类似的要点也适用于生成列。生成列在本地PostgreSQL 服务器发生插入或更新时进行计算,并将计算结果传递给外部数据封装器,由外部数据 封装器负责把结果写到外部数据存储中,但是并不强制要求查询外部表时返回的生成列 的值一定是与生成表达式一致。 总而言之,此行为可能导致查询到不正确的结果。 虽然列可以从本地分区移到外部表分区(使用的外部数据封装器支持元组路由),但是 不能将列从外部表分区移动到本地分区。 .. container:: refsect1 :name: SQL-CREATEFOREIGNTABLE-EXAMPLES .. rubric:: 示例 :name: 示例 创建外部表\ ``films``\ ,通过服务器\ ``film_server``\ 访问它: .. code:: programlisting 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`` 的分区: .. code:: programlisting CREATE FOREIGN TABLE measurement_y2016m07 PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01') SERVER server_07; .. container:: refsect1 :name: SQL-CREATEFOREIGNTABLE-COMPATIBILITY .. rubric:: 兼容性 :name: 兼容性 ``CREATE FOREIGN TABLE``\ 命令大部分符合 SQL标准。不过,与 ```CREATE TABLE`` `__ 很相似,它允许\ ``NULL``\ 约束以及零列外部表。能够指定列默认值 也是一种PostgreSQL扩展。 PostgreSQL定义的表继承形式是非标准的。 .. container:: refsect1 :name: id-1.9.3.66.10 .. rubric:: 另见 :name: 另见 `ALTER FOREIGN TABLE `__, `DROP FOREIGN TABLE `__, `CREATE TABLE `__, `CREATE SERVER `__, `IMPORT FOREIGN SCHEMA `__