============ CREATE TABLE ============ .. container:: refentry :name: SQL-CREATETABLE .. container:: titlepage .. container:: refnamediv .. rubric:: CREATE TABLE :name: create-table CREATE TABLE — 定义一个新表 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: synopsis CREATE [ { TEMPORARY | TEMP } ] TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] [ DISTRIBUTED BY (, [ ... ] ) | DISTRIBUTED RANDOMLY ] [ PARTITION BY { LIST | VALUE } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACE tablespace_name ] CREATE [ { TEMPORARY | TEMP } ] TABLE [ IF NOT EXISTS ] table_name OF type_name [ ( { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] [ DISTRIBUTED BY (, [ ... ] ) | DISTRIBUTED RANDOMLY ] [ PARTITION BY { LIST | VALUE } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACE tablespace_name ] 其中 column_constraint 是: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | UNIQUE | PRIMARY KEY | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] table_constraint 是: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | UNIQUE ( column_name [, ... ] ) | PRIMARY KEY ( column_name [, ... ] ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] like_option 是: { INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | STATISTICS | STORAGE } partition_bound_spec 是: IN ( partition_bound_expr [, ...] ) | FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUS numeric_literal, REMAINDER numeric_literal ) 一个EXCLUDE约束中的exclude_element是: { column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] .. container:: refsect1 :name: SQL-CREATETABLE-DESCRIPTION .. rubric:: 描述 :name: 描述 ``CREATE TABLE``\ 将在当前数据库中创建一个新的、初始为空的表。该表将由发出该命令的用户所拥有。 如果给定了一个模式名(例如\ ``CREATE TABLE myschema.mytable ...``\ ),那么该表被创建在指定的模式中。否则它被创建在当前模式中。临时表存在于一个特殊的模式中,因此在创建一个临时表时不能给定一个模式名。该表的名称必须与同一个模式中的任何其他表、序列、索引、视图或外部表的名称区分开。 ``CREATE TABLE``\ 也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中任何已有数据类型的名称。 可选的约束子句指定一个插入或更新操作要成功,新的或更新过的行必须满足的约束(测试)。一个约束是一个 SQL 对象,它帮助以多种方式定义表中的合法值集合。 有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列时方便书写的记号习惯。 要能创建一个表,你必须分别具有所有列类型或\ ``OF``\ 子句中类型的\ ``USAGE``\ 特权。 .. container:: refsect1 :name: id-1.9.3.85.6 .. rubric:: 参数 :name: 参数 .. container:: variablelist ``TEMPORARY`` or ``TEMP`` 如果指定,该表被创建为一个临时表。临时表会被在会话结束时自动被删除,或者也可以选择在当前事务结束时删除(见下文的\ ``ON COMMIT``\ )。当临时表存在时,已有的同名持久表将对于当前会话不可见,不过可以使用模式限定的名称进行引用。在一个临时表上创建的任何索引也自动地变为临时的。 自动清理守护进程 不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行\ ``ANALYZE``\ 。 可以选择将\ ``GLOBAL``\ 或\ ``LOCAL``\ 写在\ ``TEMPORARY``\ 或\ ``TEMP``\ 的前面。这当前在OushuDB中没有区别并且已被废弃,见\ `Compatibility `__\ 。 ``IF NOT EXISTS`` 如果一个同名关系已经存在,不要抛出一个错误。在这种情况下会发出一个提示。注意这不保证现有的关系是和将要被创建的表相似的东西。 *``table_name``* 要被创建的表名(可以选择用模式限定)。 ``OF type_name`` 创建一个\ *类型化的表*\ ,它的结构取自于指定的组合类型(名字可以选择用模式限定)。一个类型化的表和它的类型绑定在一起,例如如果类型被删除,该表也将被删除(用\ ``DROP TYPE ... CASCADE``\ )。 当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在\ ``CREATE TABLE``\ 命令中直接指定。但是\ ``CREATE TABLE``\ 命令可以对表增加默认值和约束,并且可以指定存储参数。 *``column_name``* 列的名称会在新表中被建立。 *``data_type``* 列的数据类型. 这可以包括数组 规格. ``COLLATE collation`` ``COLLATE``\ 子句为该列(必须是一种可排序数据类型)赋予一个排序规则。 如果没有指定,将使用该列数据类型的默认排序规则。 ``INHERITS ( parent_table`` [, ... ] ) 可选的\ ``INHERITS``\ 子句指定一个表的列表, 新表将从其中自动地继承所有列。 父表可以是普通表或者外部表。 ``INHERITS``\ 的使用在新的子表和它的父表之间创建一种持久的关系。 对于父表的模式修改通常也会传播到子表, 并且默认情况下子表的数据会被包括在对父表的扫描中。 如果在多个父表中存在同名的列,除非父表中每一个这种列的数据类型都能匹配, 否则会报告一个错误。如果没有冲突,那么重复列会被融合来形成新表中的一个单一列。 如果新表中的列名列表包含一个也是继承而来的列名,该数据类型必须也匹配继承的列, 并且列定义会被融合成一个。如果新表显式地为列指定了任何默认值, 这个默认值将覆盖来自该列继承声明中的默认值。 否则,任何父表都必须为该列指定相同的默认值,或者会报告一个错误。 ``CHECK``\ 约束本质上也采用和列相同的方式被融合: 如果多个父表或者新表定义中包含相同的命名\ ``CHECK``\ 约束, 这些约束必须全部具有相同的检查表达式,否则将报告一个错误。 具有相同名称和表达式的约束将被融合成一份拷贝。 一个父表中的被标记为\ ``NO INHERIT``\ 的约束将不会被考虑。 注意新表中一个未命名的\ ``CHECK``\ 约束将永远不会被融合, 因为那样总是会为它选择一个唯一的名字。 列的\ ``STORAGE``\ 设置也会从父表复制过来。 如果父表中的列是标识列,那么该属性不会被继承。 如果需要,可以将子表中的列声明为标识列。 ``DISTRIBUTED BY (, [ ... ] ) | DISTRIBUTED RANDOMLY`` 表的分布通常有哈希分布和随机分布。 哈希分布是指通过对分布键进行哈希运算,将具有相同哈希值的数据行分配到同一个存储节点上。 如果选择了合适的分布键,可以确保数据较为均匀地分布,进行某些查询时能快速定位需要查询的节点和摒弃不需要查询的节点,某些查询时能避免重新对表进行分布,从而提高查询性能。 哈希分布适用于数据分布相对固定、需要快速定位和访问数据的场景。 随机分布则是将数据行按照顺序依次发送到各个存储节点上,具有相同值的数据行不一定位于同一个存储节点上。 随机分布保证了数据绝对的平均分布,但在查询时需要所有节点,性能相对哈希分布可能会稍逊一筹。 然而,在某些情况下,例如数据分布本身就比较随机,或者难以确定合适的哈希分布键时,随机分布也可以是一种可行的选择。 在这个版本中,MAGMA表仅支持哈希分布,当然哈希分布也能发挥MAGMA最好的查询性能。HORC表支持哈希分布和随机分布。 创建MAGMA表时如果不指定分布键,MAGMA表会自动选定第一列作为分布键,并在NOTICE消息中指出选定的分布键。 哈希分片的bucket_num在magma-topology.yaml配置文件中配置的num_ranges分片数一致,无需用户手动指定。 ``PARTITION BY { LIST | VALUE } ( { column_name`` \| ( *``expression``* ) } [ *``opclass``* ] [, ...] ) 可选的\ ``PARTITION BY``\ 子句指定了对表进行分区的策略。 这样创建的表称为\ *分区*\ 表。 带括号的列或表达式的列表构成表的\ *分区键*\ 。 但对于列表分区,分区键必须由单个列或表达式组成。 范围和列表分区需要 btree 运算符类,而哈希分区需要哈希运算符类。 如果没有运算符类被显式指定,将使用相应类型的默认运算符类; 如果不存在默认运算符类,则将引发错误。 使用哈希分区时,所使用的运算符类必须实现支持功能 2。 分区表被分成多个子表(称为分区),它们是使用单独的\ ``CREATE TABLE``\ 命令创建的。 分区表本身是空的。插入到表中的数据行将根据分区键中的列或表达式的值路由到分区。 分区表不支持\ ``EXCLUDE``\ 约束; 但是,你可以在各个分区上定义这些约束。 MAGMA 表暂时不支持分区,即将支持动态分区。 ``LIKE source_table`` [ *``like_option``* ... ] ``LIKE``\ 指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。 和\ ``INHERITS``\ 不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表,并且不可能在原始表的扫描中包括新表的数据。 同样与\ ``INHERITS``\ 不同,用\ ``LIKE``\ 拷贝的列和约束不会和相似的命名列及约束融合。如果显式指定了相同的名称或者在另一个\ ``LIKE``\ 子句中指定了相同的名称,将会发出一个错误。 可选的\ *``like_option``*\ 子句指定要复制的原始表的附加属性。 指定 ``INCLUDING`` 复制该属性, 指定 ``EXCLUDING`` 忽略该属性。\ ``EXCLUDING``\ 为默认值。 如果对同一类型的对象指定了多个规范,则使用最后一个规范。可用的选项包括: .. container:: variablelist ``INCLUDING COMMENTS`` 复制的列、约束和索引的注释将被复制。默认行为是去除注释,从而导致新表中复制的列和约束没有注释。 ``INCLUDING CONSTRAINTS`` ``CHECK``\ 约束将被复制。 列约束和表约束之间没有区别。非空约束始终复制到新表。 ``INCLUDING DEFAULTS`` 复制列定义的默认表达式将被复制。否则,不会复制默认表达式,从而导致新表中复制的列具有空默认值。 注意,复制调用数据库修改函数的默认值,例如\ ``nextval``\ ,可能在原始表和新表之间创建功能联系。 ``INCLUDING GENERATED`` 列定义的任何生成表达式将被复制。 默认情况下,新列将是常规基本列。 ``INCLUDING IDENTITY`` 已复制列定义的任何标识规范都将被复制。为新表的每个标识列创建一个新序列,与与旧表关联的序列分开。 ``INCLUDING STATISTICS`` 扩展统计信息将复制到新表。 ``INCLUDING STORAGE`` 已复制列定义的\ ``STORAGE``\ 设置将被复制。 默认行为是排除\ ``STORAGE``\ 设置,从而导致新表中已复制列具有类型规定的默认设置。 ``LIKE``\ 子句也能被用来从视图、外部表或组合类型拷贝列定义。 ``CONSTRAINT constraint_name`` 一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似\ ``列必须为正``\ 的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如果没有指定约束名,系统将生成一个。 ``NOT NULL`` 该列不允许包含空值。 ``NULL`` 该列允许包含空值。这是默认情况。 这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。 ``CHECK ( expression`` ) [ NO INHERIT ] ``CHECK``\ 指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。 当前,\ ``CHECK``\ 表达式不能包含子查询,也不能引用当前行的列之外的变量。可以引用系统列\ ``tableoid``\ ,但不能引用其他系统列。 一个被标记为\ ``NO INHERIT``\ 的约束将不会传播到子表。 当一个表有多个\ ``CHECK``\ 约束时,检查完\ ``NOT NULL``\ 约束后,对于每一行会以它们名称的字母表顺序来进行检查。 ``DEFAULT default_expr`` ``DEFAULT``\ 子句为出现在其定义中的列赋予一个默认数据。该值是可以使用变量的表达式(特别是,不允许用对其他列的交叉引用)。子查询也是不允许的。 默认值表达式的数据类型必须匹配列的数据类型。 默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。 ``GENERATED ALWAYS AS ( generation_expr`` ) STORED 此子句将列创建为\ *generated column*\ 。 列无法被写入,读取时将返回指定表达式的结果。 关键字\ ``STORED``\ 表示将在写入时计算列并将存储在磁盘上。 生成表达式可以引用表中的其他列,但不能引用其他生成的列。使用的任何函数和运算符都必须是不可改变的。不允许引用其他表。 ``GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options`` ) ] 该子句将列创建为\ *标识列*\ 。 它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中获取值。 子句\ ``ALWAYS``\ 和\ ``BY DEFAULT``\ 确定在 ``INSERT``\ 语句中,序列值如何优先于用户指定的值。 如果指定了\ ``ALWAYS``\ ,则只有在\ ``INSERT`` 语句指定\ ``OVERRIDING SYSTEM VALUE``\ 时才接受用户指定的值。 如果指定了\ ``BY DEFAULT``\ ,则用户指定的值优先。 有关详细信息,请参见\ `INSERT `__\ 。 (在\ ``COPY``\ 命令中,无论此设置如何,都始终使用用户指定的值。) 可选的\ *``sequence_options``*\ 子句可用于覆盖序列的选项。 有关详细信息,请参见\ `CREATE SEQUENCE `__\ 。 ``UNIQUE`` (列约束) \ ``UNIQUE ( column_name`` [, ... ] ) ``UNIQUE``\ 约束指定一个表中的一列或多列组成的组包含唯一的值。唯一表约束的行为与列约束的行为相同,只是表约束能够跨越多列。 对于一个唯一约束的目的来说,空值不被认为是相等的。 每一个唯一表约束必须命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不相同(否则它将是一个被列举了两次的约束)。 在为多级分区层次结构建立唯一约束时, 目标分区表的分区键中的所有列,以及那些由它派生的所有分区表, 必须被包含在约束定义中。 添加唯一约束将自动在使用于约束的列或列组上创建唯一的 btree索引。 ``PRIMARY KEY`` (列约束) \ ``PRIMARY KEY ( column_name`` [, ... ] ) ``PRIMARY KEY``\ 约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个主键,可以作为列约束或表约束。 主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余的并且会被丢弃)。 ``PRIMARY KEY``\ 强制的数据约束可以看成是\ ``UNIQUE``\ 和\ ``NOT NULL``\ 的组合, 不过把一组列标识为主键也为模式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。 ``PRIMARY KEY`` 约束共享\ ``UNIQUE`` 约束放到分区表上时限制。 添加\ ``PRIMARY KEY``\ 约束将自动在用于约束的列或列组上创建唯一的 btree 索引。 可选的\ ``INCLUDE`` 子句允许指定将被包含在索引的非-键部分中的列的列表。 虽然包含的列的唯一性是非强制的,但约束仍依赖于它们。 因此,这些包含的列上的某些操作(例如\ ``DROP COLUMN``\ )可能会导致级联约束和索引删除。 ``EXCLUDE [ USING index_method`` ] ( *``exclude_element``* WITH *``operator``* [, ... ] ) *``index_parameters``* [ WHERE ( *``predicate``* ) ] ``EXCLUDE``\ 子句定一个排除约束,它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,不是所有的比较都将会返回\ ``TRUE``\ 。如果所有指定的操作符都测试相等,这就等价于一个\ ``UNIQUE``\ 约束,尽管一个普通的唯一约束将更快。不过,排除约束能够指定比简单相等更通用的约束。例如,你可以使用\ ``&&``\ 操作符指定一个约束,要求表中没有两行包含相互覆盖的圆(见 `第 8.8 节 `__\ )。 排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法\ *``index_method``*\ 的一个适当的操作符类(见\ `第 11.10 节 `__\ )相关联。操作符被要求是交换的。每一个\ *``exclude_element``*\ 可以选择性地指定一个操作符类或者顺序选项,这些在\ `CREATE INDEX `__\ 中有完整描述。 访问方法必须支持\ ``amgettuple``\ ,目前这意味着GIN无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是GiST或SP-GiST。 *``predicate``*\ 允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周围的圆括号是必须的。 ``REFERENCES reftable`` [ ( *``refcolumn``* ) ] [ MATCH *``matchtype``* ] [ ON DELETE *``referential_action``* ] [ ON UPDATE *``referential_action``* ] (column constraint) \ ``FOREIGN KEY ( column_name`` [, ... ] ) REFERENCES *``reftable``* [ ( *``refcolumn``* [, ... ] ) ] [ MATCH *``matchtype``* ] [ ON DELETE *``referential_action``* ] [ ON UPDATE *``referential_action``* ] (表约束) 这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在被引用列上的值。 如果\ *``refcolumn``*\ 列表被忽略,将使用\ *``reftable``*\ 的主键。 被引用列必须是被引用表中一个非可延迟唯一约束或主键约束的列。 用户必须在被引用的表(或整个表,或特定的引用列)上拥有\ ``REFERENCES``\ 权限。 增加的外键约束需要\ ``SHARE ROW EXCLUSIVE`` 锁定引用的表。 注意外键约束不能在临时表和永久表之间定义。 被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。 有三种匹配类型:\ ``MATCH FULL``\ 、\ ``MATCH PARTIAL``\ 以及\ ``MATCH SIMPLE``\ (这是默认值)。 ``MATCH FULL``\ 将不允许一个多列外键中的一列为空,除非所有外键列都是空;如果它们都是空,则不要求该行在被引用表中有一个匹配。 ``MATCH SIMPLE``\ 允许任意外键列为空,如果任一为空,则不要求该行在被引用表中有一个匹配。 ``MATCH PARTIAL``\ 现在还没有被实现(当然,\ ``NOT NULL``\ 约束能被应用在引用列上来组织这些情况发生)。 另外,当被引用列中的数据被改变时,在这个表的列中的数据上可以执行特定的动作。\ ``ON DELETE``\ 指定当被引用表中一个被引用行被删除时要执行的动作。同样,\ ``ON UPDATE``\ 指定当被引用表中一个被引用列被更新为新值时要执行的动作。如果该行被更新,但是被引用列并没有被实际改变,不会做任何动作。除了\ ``NO ACTION``\ 检查之外的引用动作不能被延迟,即便该约束被声明为可延迟的。对每一个子句可能有以下动作: .. container:: variablelist ``NO ACTION`` 产生一个错误指示删除或更新将会导致一个外键约束违背。如果该约束被延迟,并且仍存在引用行,这个错误将在约束检查时被产生。这是默认动作。 ``RESTRICT`` 产生一个错误指示删除或更新将会导致一个外键约束违背。这个动作与\ ``NO ACTION``\ 形同,不过该检查不是可延迟的。 ``CASCADE`` 删除任何引用被删除行的行,或者把引用列的值更新为被引用列的新值。 ``SET NULL`` 将引用列设置为空。 ``SET DEFAULT`` 设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认值,否则该操作将会失败)。 如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效地被执行。 ``DEFERRABLE`` \ ``NOT DEFERRABLE`` 这个子句控制该约束是否能被延迟。一个不可延迟的约束将在每一次命令后立刻被检查。可延迟约束的检查将被推迟到事务结束时进行(使用\ `SET CONSTRAINTS `__\ 命令)。\ ``NOT DEFERRABLE``\ 是默认值。当前,只有\ ``UNIQUE``\ 、\ ``PRIMARY KEY``\ 、\ ``EXCLUDE``\ 以及\ ``REFERENCES``\ (外键)约束接受这个子句。\ ``NOT NULL``\ 以及\ ``CHECK``\ 约束是不可延迟的。注意在包括\ ``ON CONFLICT DO UPDATE``\ 子句的\ ``INSERT``\ 语句中,可延迟约束不能被用作冲突裁判者。 ``INITIALLY IMMEDIATE`` \ ``INITIALLY DEFERRED`` 如果一个约束是可延迟的,这个子句指定检查该约束的默认时间。如果该约束是\ ``INITIALLY IMMEDIATE``\ ,它会在每一个语句之后被检查。这是默认值。如果该约束是\ ``INITIALLY DEFERRED``\ ,它只会在事务结束时被检查。约束检查时间可以用\ `SET CONSTRAINTS `__\ 命令修改。 ``USING method`` 如果未指定此选项,则为新表选择默认表访问方法。详见\ `default_table_access_method `__\ 。 ``WITH ( storage_parameter`` [= *``value``*] [, ... ] ) 这个子句为一个表或索引指定可选的存储参数,详见\ `存储参数 `__ 。 为了向后兼容性,表的\ ``WITH``\ 子句还可以包括\ ``OIDS=FALSE``\ 以便指定新表的行不应包含 OIDs (对象标识符),\ ``OIDS=TRUE``\ 不再受支持。 ``WITHOUT OIDS`` 这是向后兼容的语法,用于声明表\ ``WITHOUT OIDS``\ ,不再支持创建表\ ``WITH OIDS``\ 。 ``ON COMMIT`` 临时表在一个事务块结束时的行为由\ ``ON COMMIT``\ 控制。三种选项是: .. container:: variablelist ``PRESERVE ROWS`` 在事务结束时不采取特殊的动作。这是默认行为。 ``DELETE ROWS`` 在每一个事务块结束时将删除临时表中的所有行。 实质上,在每一次提交时会完成一次自动的\ `TRUNCATE `__\ 。 当应用于分区表上时,这不会级联到它的分区。 magmaap表不支持此选项 ``DROP`` 在当前事务块结束时将删除临时表。 当在分区表上使用时,这个操作会删除他的分区,而在具有继承子级的表上使用时,它将删除依赖的子级。 ``TABLESPACE tablespace_name`` *``tablespace_name``*\ 是新表要创建于其中的表空间名称。如果没有指定,将参考\ `default_tablespace <../reference/parameters.html>`__\ ,或者如果表是临时的则参考\ `temp_tablespaces <../reference/parameters.html>`__\ 。 对于分区表,由于表本身不需要存储,指定表空间将 ``default_tablespace``\ 作为默认表空间覆盖,在未显式指定其他表空间时用于任何新创建的分区。 .. container:: refsect2 :name: SQL-CREATETABLE-STORAGE-PARAMETERS .. rubric:: 存储参数 :name: 存储参数 表单的存储参数可以是以下值: ``WITH``\ 子句能够为表或与一个\ ``UNIQUE``\ 、\ ``PRIMARY KEY``\ 或者\ ``EXCLUDE``\ 约束相关的索引指定\ *存储参数*\ 。 用于索引的存储参数已经在\ `CREATE INDEX `__\ 中介绍过。 当前可用于表的存储参数在下文中列出。 如下文所示,对于很多这类参数,都有一个名字带有\ ``toast.``\ 前缀的附加参数,它能被用来控制该表的二级TOAST表(如果存在)的行为。 如果一个表的参数值被设置但是相应的\ ``toast.``\ 参数没有被设置,那么 TOAST 表将使用该表的参数值。 不支持为分区表指定这些参数,但可以为单个叶子分区指定它们。 APPENDONLY={TRUE} BLOCKSIZE={8192-2097152} bucket_number={} ORIENTATION={HORC,magmaap} COMPRESSTYPE={ZLIB | ZSTD | SNAPPY | LZ4 | NONE} OIDS={FALSE} .. container:: refsect1 :name: SQL-CREATETABLE-NOTES .. rubric:: 注解 :name: 注解 OushuDB为每一个唯一约束和主键约束创建一个索引来强制唯一性。因此,没有必要显式地为主键列创建一个索引(详见\ `CREATE INDEX `__\ )。 在当前的实现中,唯一约束和主键不会被继承。这使得继承和唯一约束的组合相当不正常。 一个表不能有超过 1600 列(实际上,由于元组长度限制,有效的限制通常更低)。 .. container:: refsect1 :name: SQL-CREATETABLE-EXAMPLES .. rubric:: 例子 :name: 例子 创建表\ ``films``\ 和表\ ``distributors``\ : .. code:: programlisting CREATE TABLE films ( code char(5) CONSTRAINT firstkey PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10), len interval hour to minute ); CREATE TABLE distributors ( did integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, name varchar(40) NOT NULL CHECK (name <> '') ); 创建有一个二维数组的表: .. code:: programlisting CREATE TABLE array_int ( id int, vector int[][] ); 为表\ ``films``\ 定义一个唯一表约束。唯一表约束能够被定义在表的一列或多列上: .. code:: programlisting CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT production UNIQUE(date_prod) ); 定义一个列检查约束: .. code:: programlisting CREATE TABLE distributors ( did integer CHECK (did > 100), name varchar(40) ); 定义一个表检查约束: .. code:: programlisting CREATE TABLE distributors ( did integer, name varchar(40), CONSTRAINT con1 CHECK (did > 100 AND name <> '') ); 为表\ ``films``\ 定义一个主键表约束: .. code:: programlisting CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT code_title PRIMARY KEY(code,title) ); 为表\ ``distributors``\ 定义一个主键约束。下面的两个例子是等价的,第一个使用表约束语法,第二个使用列约束语法: .. code:: programlisting CREATE TABLE distributors ( did integer, name varchar(40), PRIMARY KEY(did) ); CREATE TABLE distributors ( did integer PRIMARY KEY, name varchar(40) ); 为列\ ``name``\ 赋予一个文字常量默认值,安排列\ ``did``\ 的默认值是从一个序列对象中选择下一个值产生,并且让\ ``modtime``\ 的默认值是该行被插入的时间: .. code:: programlisting CREATE TABLE distributors ( name varchar(40) DEFAULT 'Luso Films', did integer DEFAULT nextval('distributors_serial'), modtime timestamp DEFAULT current_timestamp ); 在表\ ``distributors``\ 上定义两个\ ``NOT NULL``\ 列约束,其中之一被显式给定了一个名称: .. code:: programlisting CREATE TABLE distributors ( did integer CONSTRAINT no_null NOT NULL, name varchar(40) NOT NULL ); 为\ ``name``\ 列定义一个唯一约束: .. code:: programlisting CREATE TABLE distributors ( did integer, name varchar(40) UNIQUE ); 同样的唯一约束用表约束指定: .. code:: programlisting CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) ); 在表空间\ ``diskvol1``\ 中创建表\ ``cinemas``\ : .. code:: programlisting CREATE TABLE cinemas ( id serial, name text, location text ) TABLESPACE diskvol1; 创建一个组合类型以及一个类型化的表: .. code:: programlisting CREATE TYPE employee_type AS (name text, salary numeric); CREATE TABLE employees OF employee_type ( PRIMARY KEY (name), salary WITH OPTIONS DEFAULT 1000 ); 创建一个Value分区表,目前magma表不支持分区,只能在horc表中创建分区: .. code:: programlisting CREATE TABLE measurement ( logdate date not null, peaktemp int, unitsales int ) PARTITION BY VALUE (logdate); 创建在分区键中具有多个列的范围分区表,目前magma表不支持分区,只能在horc表中创建分区: .. code:: programlisting CREATE TABLE measurement_year_month ( year int, logdate date not null, peaktemp int, unitsales int ) PARTITION BY VALUE (year, logdate); 创建列表分区表: .. code:: programlisting CREATE TABLE cities ( city_id bigserial not null, name text not null, population bigint ) PARTITION BY LIST(city_id)(partition pab values('ab'), partition pac values('ac')); .. container:: refsect1 :name: SQL-CREATETABLE-COMPATIBILITY .. rubric:: Compatibility :name: compatibility ``CREATE TABLE``\ 命令遵从SQL标准,除了以下例外。 .. container:: refsect2 :name: id-1.9.3.85.9.3 .. rubric:: 临时表 :name: 临时表 尽管\ ``CREATE TEMPORARY TABLE``\ 的语法很像 SQL 标准的语法,但事实是并不相同。在标准中,临时表只需要被定义一次并且会自动地存在(从空内容开始)于需要它们的每一个会话中。OushuDB则要求每一个会话为每一个要用的临时表发出它自己的\ ``CREATE TEMPORARY TABLE``\ 命令。这允许不同的会话为不同的目的使用相同的临时表名,而标准的方法约束一个给定临时表名的所有实例都必须具有相同的表结构。 标准中对于临时表行为的定义被广泛地忽略了。OushuDB在这一点上的行为和多种其他 SQL 数据库是相似的。 SQL 标准也区分全局和局部临时表,其中一个局部临时表为每一个会话中的每一个 SQL 模块具有一个独立的内容集合,但是它的定义仍然是多个会话共享的。因为OushuDB不支持 SQL 模块,这种区别与OushuDB无关。 为了兼容性目的,OushuDB将在临时表声明中接受\ ``GLOBAL``\ 和\ ``LOCAL``\ 关键词,但是它们当前没有效果。我们不鼓励使用这些关键词,因为未来版本的OushuDB可能采用一种更兼容标准的(对它们含义的)解释。 临时表的\ ``ON COMMIT``\ 子句也和 SQL 标准相似,但是有一些不同。如果忽略\ ``ON COMMIT``\ 子句,SQL 指定默认行为是\ ``ON COMMIT DELETE ROWS``\ 。但是,OushuDB中的默认行为是\ ``ON COMMIT PRESERVE ROWS``\ 。SQL 中不存在\ ``ON COMMIT DROP``\ 选项。 .. container:: refsect2 :name: id-1.9.3.85.9.4 .. rubric:: 非延迟唯一性约束 :name: 非延迟唯一性约束 但一个\ ``UNIQUE``\ 或\ ``PRIMARY KEY``\ 约束是非可延迟的,只要一个行被插入或修改,OushuDB就会立即检查唯一性。SQL 标准指出只有在语句结束时才应该强制唯一性。当一个单一命令更新多个键值时,这两者是不同的。要得到兼容标准的行为,将该约束声明为\ ``DEFERRABLE``\ 但是不延迟(即\ ``INITIALLY IMMEDIATE``\ )。注意这可能要显著地慢于立即唯一性检查。 .. container:: refsect2 :name: id-1.9.3.85.9.5 .. rubric:: 列检查约束 :name: 列检查约束 SQL 标准指出\ ``CHECK``\ 列约束只能引用它们应用到的列,只有\ ``CHECK``\ 表约束能够引用多列。OushuDB并没有强制这个限制,它同样处理列检查约束和表检查约束。 .. container:: refsect2 :name: id-1.9.3.85.9.6 .. rubric:: ``EXCLUDE`` 约束 :name: exclude-约束 ``EXCLUDE``\ 约束类型是一种OushuDB扩展。 .. container:: refsect2 :name: id-1.9.3.85.9.7 .. rubric:: ``NULL`` “约束” :name: null-约束 ``NULL`` “约束”(实际上是一个非约束)是一个OushuDB对 SQL 标准的扩展,它也被包括(以及对称的\ ``NOT NULL``\ 约束)在一些其他的数据库系统中以实现兼容性。因为它是任意列的默认值,它的存在就像噪声一样。 .. container:: refsect2 :name: id-1.9.3.85.9.8 .. rubric:: Constraint Naming :name: constraint-naming SQL标准规定在包含表或域的模式范围内表和域的约束必须具有唯一的名称。 OushuDB是比较宽松的:它只需要约束名称在附加到特定表或域的约束之间是唯一的。 但是,对于基于索引的约束(``UNIQUE``,\ ``PRIMARY KEY``, and ``EXCLUDE``\ constraints), 这个特别的自由度并不存在, 因为关联的索引被命名为与约束相同的名称,并且索引名称在相同模式的所有关系中必须是唯一的。 当前,OushuDB没有记录\ ``NOT NULL``\ 约束的名称, 因此它们不受唯一性限制的影响。这在将来的版本中可能会改变。 .. container:: refsect2 :name: id-1.9.3.85.9.9 .. rubric:: 继承 :name: 继承 通过\ ``INHERITS``\ 子句的多继承是一种OushuDB的语言扩展。SQL:1999 以及之后的标准使用一种不同的语法和不同的语义定义了单继承。SQL:1999-风格的继承还没有被OushuDB。 .. container:: refsect2 :name: id-1.9.3.85.9.11 .. rubric:: 多个标识列 :name: 多个标识列 OushuDB允许一个表拥有多个标识列。 该标准指定一个表最多只能有一个标识列。这主要是为了给模式更改或迁移提供更大的灵活性。 请注意,\ ``INSERT``\ 命令仅支持一个适用于整个语句的覆盖子句, 因此不支持具有不同行为的多个标识列。 .. container:: refsect2 :name: id-1.9.3.85.9.12 .. rubric:: Generated Columns :name: generated-columns ``STORED``\ 选项不是标准,但也用于其他 SQL 实现。 SQL 标准不规定生成列的存储。 .. container:: refsect2 :name: id-1.9.3.85.9.13 .. rubric:: ``LIKE`` 子句 :name: like-子句 虽然 SQL 标准中有一个\ ``LIKE``\ 子句,但是OushuDB接受的很多\ ``LIKE``\ 子句选项却不在标准中,并且有些标准中的选项也没有被OushuDB实现。 .. container:: refsect2 :name: id-1.9.3.85.9.14 .. rubric:: ``WITH``\ 子句 :name: with子句 ``WITH``\ 子句是一个OushuDB扩展,存储参数不在标准中。 .. container:: refsect2 :name: id-1.9.3.85.9.15 .. rubric:: 表空间 :name: 表空间 OushuDB的表空间概念不是标准的一部分。因此,子句\ ``TABLESPACE``\是扩展。 .. container:: refsect2 :name: id-1.9.3.85.9.16 .. rubric:: 类型化的表 :name: 类型化的表 类型化的表实现了 SQL 标准的一个子集。根据标准,一个类型化的表具有与底层组合类型相对应的列,以及其他的“自引用列”。OushuDB不显式支持自引用列。 .. container:: refsect2 :name: id-1.9.3.85.9.17 .. rubric:: ``PARTITION BY`` 子句 :name: partition-by-子句 ``PARTITION BY``\ 子句是OushuDB的一个扩展。 .. container:: refsect1 :name: id-1.9.3.85.10 .. rubric:: 参见 :name: 参见 `ALTER TABLE `__, `DROP TABLE `__, `CREATE TABLE AS `__, `CREATE TABLESPACE `__, `CREATE TYPE `__