16. SQL语句: CREATE SEQUENCE 到 DELETE

本章包含以下SQL语句:

  • CREATE SEQUENCE

  • CREATE SERVER

  • CREATE STATISTICS

  • CREATE SUBSCRIPTION

  • CREATE SYNONYM

  • CREATE TABLE

  • CREATE TABLE AS

  • CREATE TABLESPACE

  • CREATE TEXT SEARCH CONFIGURATION

  • CREATE TEXT SEARCH DICTIONARY

  • CREATE TEXT SEARCH PARSER

  • CREATE TEXT SEARCH TEMPLATE

  • CREATE TRANSFORM

  • CREATE TRIGGER

  • CREATE TYPE

  • CREATE TYPE BODY

  • CREATE USER

  • CREATE USER MAPPING

  • CREATE VIEW

  • DEALLOCATE

  • DECLARE

  • DELETE

16.1. CREATE SEQUENCE

用途

CREATE SEQUENCE创建一个新的序列数 发生器。这涉及到用名称``name``创建并且初始化 一个新的特殊的单行表。该发生器将由发出该命令的用户所拥有。

如果给出一个模式名称,则该序列将将被创建在指定的模式中。否则它会被 创建在当前模式中。临时序列存在于一个特殊的模式中,因此在创建临时序列 时不能给出模式名。序列名称必须与同一模式中任何其他序列、表、索引、 视图或者外部表的名称不同。

在序列被创建后,可以使用函数 nextval、 currval以及 setval来操作该序列。这些函数在 序列操作函数 中有介绍。

尽管无法直接更新一个序列,可以使用这样的查询:

SELECT * FROM name;

来检查一个序列的参数以及当前状态。特别地,序列的 last_value域显示被任意会话最后一次取得的值(当然, 在被打印时该值可能已经过时了,因为可能有其他会话正在执行 nextval调用)。

前置条件

语法

CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] name [ INCREMENT [ BY ] increment ][ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ][ START [ WITH ] start ] [ CACHE cache ] [ NOCACHE ] [ [ NO ] CYCLE ] [ NOCYCLE ][ ORDER ] [ NOORDER ] [ OWNED BY { table_name.column_name | NONE } ]

语义

TEMPORARY or TEMP

如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动 删除它。当临时序列存在时,已有的同名永久序列(在这个会话中) 会变得不可见,不过可以用模式限定的名称来引用同名永久序列。

IF NOT EXISTS

如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的关系与即将创建的序列相似 -- 它甚至可能 都不是一个序列。

name

要创建的序列的名称(可以是模式限定的)。

data_type

可选的子句AS data_type 制定序列的数据类型。有效类型是 smallintinteger、 和bigint。默认是bigint。 数据类型决定了序列的默认最小和最大值。

increment

可选的子句INCREMENT BY increment指定为了 创建新值会把哪个值加到当前序列值上。一个正值将会创造一个上升 序列,负值会创造一个下降序列。默认值是 1。

minvalue NO MINVALUE

可选的子句MINVALUE minvalue决定一个序列 能产生的最小值。如果没有提供这个子句或者指定了 NO MINVALUE,那么会使用默认值。 升序序列的默认值为1。降序序列的默认值为数据类型的最小值。

maxvalue NO MAXVALUE

可选的子句MAXVALUE maxvalue决定该序列 的最大值。如果没有提供这个子句或者指定了 NO MAXVALUE,那么将会使用默认值。 升序序列的默认值是数据类型的最大值。降序序列的默认值是-1。

start

可选的子句START WITH start 允许序列从任何 地方开始。对于上升序列和下降序列来说,默认的开始值分别是 ``minvalue``和 ``maxvalue``

cache NOCYCLE

可选的子句CACHE cache指定要预分配多少 个序列数并且把它们放在内存中以便快速访问。最小值为 1 (一次只生成 一个值,即没有缓存),默认值也是 1。

指定NOCACHE,即没有缓存,缓存值为1。

CYCLE NO CYCLE NOCYCLE

对于上升序列和下降序列,CYCLE选项允许序列 在分别达到``maxvalue````minvalue``时回卷。如果达到 该限制,下一个产生的数字将分别是``minvalue````maxvalue``

如果指定了NO CYCLE,当序列到达其最大值 后任何nextval调用将返回一个错误。如果 CYCLENO CYCLE都没有 被指定,则默认为NO CYCLE

NOCYCLE等价于NO CYCLE

ORDER NOORDER

ORDERNOORDER只在语法层面兼容Oracle数据库,并没有实现相应的功能。

OWNED BY table_name.column_name OWNED BY NONE

OWNED BY选项导致序列被与一个特定的表列关联 在一起,这样如果该列(或者整个表)被删除,该序列也将被自动删除。 指定的表必须和序列具有相同的拥有者并且在同一个模式中。默认选项 OWNED BY NONE指定该序列不与某个列关联。

示例

创建一个称作serial的上升序列,从 101 开始:

CREATE SEQUENCE serial START 101;

从这个序列中选取下一个数字:

SELECT nextval('serial');nextval
---------101

再从这个序列中选取下一个数字:

SELECT nextval('serial');nextval
---------102

在一个INSERT命令中使用这个序列:

INSERT INTO distributors VALUES (nextval('serial'), 'nothing');

在一次COPY FROM后更新新列值:

BEGIN;
COPY distributors FROM 'input_file';
SELECT setval('serial', max(id)) FROM distributors;
END;

兼容性

CREATE SEQUENCE符合SQL 标准,不过下列除外:

  • 使用nextval()而不是标准的NEXT VALUE FOR 表达式获取下一个值。

  • OWNED BY子句是一种KingbaseES扩展。

其他

使用DROP SEQUENCE移除一个序列。

序列是基于bigint算法的,因此范围是不能超过一个八字节 整数的范围(-9223372036854775808 到 9223372036854775807)。

由于nextvalsetval调用绝不会回滚, 如果需要序数的“无间隙”分配,则不能使用序列对象。可以 通过在一个只包含一个计数器的表上使用排他锁来构建无间隙的分配, 但是这种方案比序列对象开销更大,特别是当有很多事务并发请求序数 时。

如果对一个将由多个会话并发使用的序列对象使用了大于 1 的``cache``设置,可能会得到意想不到的结果。 每个会话会在访问该序列对象时分配并且缓存后续的序列值,并且相应地增加 该序列对象的last_value。然后,在该会话中下一次 nextval会做 ``cache``-1,并且简单地 返回预分配的值而不修改序列对象。因此,任何已分配但没有在会话中使用的 数字将会在该会话结束时丢失,导致该序列中的“空洞”。

进一步,尽管多个会话能分配到不同的序列值,这些值可能会在所有会话都被 考虑时生成出来。例如, ``cache``的设置为 10,会话 A 可能储存值 1..10 并且返回nextval=1,然后会话 B 可能储存值 11..20 并且在 A 生成nextval=2 之前返回 nextval=11。因此,如果 ``cache``设置为 1,可以 安全地假设nextval值被顺序地生成。如果``cache``设置大于 1,就只能假定 nextval值都是可区分的,但不能保证它们被完全地顺序生成。 还有,last_value将反映服务于任意会话的最后一个值,不管它 是否已经被nextval返回过。

另一个考虑是,在这样一个序列上执行的setval将不会通知 其他会话,直到它们用尽了任何已缓存的预分配值。

16.2. CREATE SERVER

用途

CREATE SERVER定义一个新的外部服务器。定义该服务器的用户会成为拥有者。

外部服务器通常包装了外部数据包装器用来访问一个外部数据源所需的 连接信息。额外的用户相关的连接信息可以通过用户映射的方式来指定。

服务器名称在数据库中必须唯一。

前置条件

创建服务器要求所使用的外部数据包装器上的USAGE特权。

语法

CREATE SERVER [ IF NOT EXISTS ] server_name [ TYPE 'server_type' ] [ VERSION 'server_version' ]FOREIGN DATA WRAPPER fdw_name[ OPTIONS ( option 'value' [, ... ] ) ]

语义

IF NOT EXISTS

如果已经存在同名的服务器,不要抛出错误。在这种情况下发出一个通知。 请注意,不能保证现有服务器与要创建的服务器类似。

server_name

要创建的外部服务器的名称。

server_type

可选的服务器类型,可能对外部数据包装器有用。

server_version

可选的服务器版本,可能对外部数据包装器有用。

fdw_name

管理该服务器的外部数据包装器的名称。

OPTIONS ( option 'value' [, ... ] )

这个子句为服务器指定选项。这些选项通常定义该服务器的连接细节, 但是实际的名称和值取决于该服务器的外部数据包装器。

示例

创建使用外部数据包装器kingbase_fdw``的服务器\ ``myserver

CREATE SERVER myserver FOREIGN DATA WRAPPER kingbase_fdw OPTIONS (host 'foo', dbname 'foodb', port '54321');

兼容性

CREATE SERVER符合 ISO/IEC 9075-9 (SQL/MED)。

16.3. CREATE STATISTICS

用途

CREATE STATISTICS将创建一个新的扩展统计对象, 追踪指定表、外部表或物化视图的数据。该统计对象将在当前数据库中创建, 被发出该命令的用户所有。

如果给定了模式名(比如,CREATE STATISTICS myschema.mystat ...), 那么在给定的模式中创建统计对象。否则在当前模式中创建。 统计对象的名称必须与相同模式中的任何其他统计对象不同。

前置条件

你必须是表的所有者才能创建读取它的统计对象。不过,一旦创建,统计对象的所有权与基础表无关。

语法

CREATE STATISTICS [ IF NOT EXISTS ] statistics_name[ ( statistics_kind [, ... ] ) ]ON column_name, column_name [, ...]FROM table_name

语义

IF NOT EXISTS

如果具有相同名称的统计对象已经存在,不会抛出一个错误,只会发出一个提示。 请注意,这里只考虑统计对象的名称,不考虑其定义细节。

statistics_name

要创建的统计对象的名称(可以有模式限定)。

statistics_kind

在此统计对象中计算的统计种类。目前支持的种类是启用n-distinct统计的 ndistinct,以及启用功能依赖性统计的 dependenciesmcv启用最常用的值列表。 如果省略该子句,则统计对象中将包含所有支持的统计类型。

column_name

被计算的统计信息包含的表格列的名称。至少必须给出两个列名。列名的顺序无关紧要。

table_name

包含计算统计信息的列的表的名称(可以是模式限定的)。

示例

用两个功能相关的列创建表t1, 即第一列中的值的信息足以确定另一列中的值。然后, 在这些列上构建函数依赖关系统计信息:

CREATE TABLE t1 (a   int,b   int
);INSERT INTO t1 SELECT i/100, i/500FROM generate_series(1,1000000) s(i);ANALYZE t1;-- 匹配行的数量将被大大低估:
EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0);CREATE STATISTICS s1 (dependencies) ON a, b FROM t1;ANALYZE t1;-- 现在行计数估计会更准确:
EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0);

如果没有函数依赖性统计信息,规划器会认为两个WHERE条件是独立的, 并且会将它们的选择性乘以一起来返回满足条件的行,以致得到的行数被低估。 通过这样的统计,规划器认识到WHERE条件是多余的,就不会低估行数。

创建具有两个完全相关的列的表t2(包含相同的数据),并在这些列上创建一个MCV列表:

CREATE TABLE t2 (a   int,b   int
);INSERT INTO t2 SELECT mod(i,100), mod(i,100)FROM generate_series(1,1000000) s(i);CREATE STATISTICS s2 (mcv) ON a, b FROM t2;ANALYZE t2;-- valid combination (found in MCV)
EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 1);-- invalid combination (not found in MCV)
EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 2);

MCV列表为计划者提供了关于表中通常出现的特定值的更详细的信息,以及未出现在表中的值的组合的选择的上限,从而使它能够在两种情况下生成更好的估计值。

兼容性

SQL标准中没有CREATE STATISTICS命令。

16.4. CREATE SUBSCRIPTION

用途

CREATE SUBSCRIPTION为当前数据库添加一个新的订阅。 订阅名称必须与数据库中任何现有的订阅不同。

订阅表示到发布者的复制连接。因此,此命令不仅在本地目录中添加定义, 还会在发布者上创建复制插槽。

在运行此命令的事务提交时,将启动逻辑复制工作器以复制新订阅的数据。

前置条件

创建复制槽时(默认行为), CREATE SUBSCRIPTION不能在事务块内部执行。

如果复制插槽不是作为同一命令的一部分创建的,则创建连接到相同数据库集群的订阅 (例如,在同一集群中的数据库之间进行复制或在同一个数据库中进行复制)只能成功 否则,CREATE SUBSCRIPTION调用将挂起。要做到这一点, 单独创建复制插槽(使用函数sys_create_logical_replication_slot 和插件名称pgoutput),并使用参数create_slot = false 创建订阅。这是一个实施限制,可能会在未来的版本中解除。

语法

CREATE SUBSCRIPTION subscription_nameCONNECTION 'conninfo'PUBLICATION publication_name [, ...][ WITH ( subscription_parameter [= value] [, ... ] ) ]

语义

subscription_name

新订阅的名称。

CONNECTION 'conninfo'

连接发布者的字符串。

PUBLICATION publication_name

要订阅的发布者上的发布名称。

WITH ( subscription_parameter [= value] [, ... ] )

该子句指定订阅的可选参数。支持的参数有:

copy_data (boolean)

指定在复制启动后是否应复制正在订阅的发布中的现有数据。 默认值是true

create_slot (boolean)

指定该命令是否要在发布者上创建复制槽。默认值是true

enabled (boolean)

指定订阅是否应该主动复制,或者是否应该只是设置,但尚未启动。 默认值是true

slot_name (string)

要使用的复制插槽的名称。默认行为是使用订阅名称作为插槽的名称。

slot_name设置为NONE时, 将不会有复制槽与订阅关联。这在需要稍后手动设置复制槽的情况下会使用。 这样的订阅必须同时enabled并且 create_slot设置为false

synchronous_commit (enum)

该参数的值会覆盖synchronous_commit设置。 默认值是off

对于逻辑复制使用off是安全的: 如果订阅者由于缺少同步而丢失事务,数据将从发布者重新发送。

进行同步逻辑复制时,不同的设置可能是合适的。 逻辑复制工作者向发布者报告写入和刷新的位置,当使用同步复制时, 发布者将等待实际刷新。这意味着,当订阅用于同步复制时, 将订阅者的synchronous_commit设置为off 可能会增加发布服务器上COMMIT的延迟。 在这种情况下,将synchronous_commit设置为 local或更高是有利的。

connect (boolean)

指定CREATE SUBSCRIPTION是否应该连接到发布者。 将其设置为false将会改变默认值enabled、 create_slotcopy_datafalse

不允许将connect设置为false的同时将 enabledcreate_slotcopy_data 设置为true

因为该选项设置为false时不会建立连接, 因此表没有被订阅,所以当启用订阅后,不会复制任何内容。 需要运行ALTER SUBSCRIPTION ... REFRESH PUBLICATION才能订阅表。

示例

创建一个到远程服务器的订阅,复制发布mypublication和 insert_only中的表,并在提交时立即开始复制:

CREATE SUBSCRIPTION mysubCONNECTION 'host=192.168.1.50 port=54321 user=foo dbname=foodb'PUBLICATION mypublication, insert_only;

创建一个到远程服务器的订阅,复制insert_only发布中的表, 并且不开始复制直到稍后启用复制。

CREATE SUBSCRIPTION mysubCONNECTION 'host=192.168.1.50 port=54321 user=foo dbname=foodb'PUBLICATION insert_onlyWITH (enabled = false);

兼容性

CREATE SUBSCRIPTION是一个KingbaseES 扩展。

16.5. CREATE SYNONYM

用途

CREATE SYNONYM定义一个同义词。同义词是数据库对象的一个别名,常用于简化对象访问和提高对象访问的安全性。在使用同义词时,数据库将它翻译成对应数据库对象的名字。与视图类似,同义词并不占用实际存储空间,只在数据字典中保存了同义词的定义。用户可以通过访问对象的同义词,来间接访问对象。

CREATE OR REPLACE SYNONYM与之相似,但是如果已经存在一个同名同义词,该同义词会被替换。

如果给定了一个模式名(例如CREATE SYNONYM myschema.mysynonym ...),那么该同义词会被创建在指定的模式中。否则,它会被创建在当前模式中。同义词的名称不能与同一模式中任何其他同义词同名。

前置条件

要创建同义词,必须拥有CREATE SYNONYM 的系统权限。

语法

CREATE [ OR REPLACE ] [ PUBLIC ] SYNONYM syn_name FOR obj_name

语义

PUBLIC

指定创建同义词的类型,指定PUBLIC为公有同义词,公有同义词创建在PUBLIC模式下,用户创建公有同义词时候,可以不用指定模式。创建私有同义词必须指定模式(在当前模式为PUBLIC的时候),模式不可为PUBLIC,同时不可以指定PUBLIC参数。

syn_name

要创建的同义词的名字(可以是模式限定的)。

obj_name

同义词引用对象(可以是模式限定的)。表、视图、物化视图、同义词、序列、存储过程、函数、类型都可以作为同义词引用对象

示例

同义词和引用对象之间没有强依赖关系(不检查引用对象是否存在),同义词也无状态可言,一直是有效。例如引用对象不存在:

CREATE SCHEMA schm;
CREATE SYNONYM schm.syn_tab FOR public.tab; --tab不存在
SELECT * FROM schm.syn_tab;
ERROR:  relation "SCHM.SYN_TAB" does not exist
LINE 1: SELECT * FROM schm.syn_tab;
SELECT * FROM SYS_SYNONYM WHERE synname = 'SYN_TAB'; --同义词定义信息SYNNAME | SYNNAMESPACE | SYNOWNER | REFOBJNSPNAME | REFOBJNAME
---------+--------------+----------+---------------+------------SYN_TAB |        16385 |       10 | PUBLIC        | TAB
SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TAB'; --查看同义词状态STATUS
--------VALID

引用对象存在,删除引用对象(可删除),同义词状态有效:

CREATE TABLE public.tb(id int);
INSERT INTO TB VALUES(1);
CREATE SYNONYM schm.syn_tb FOR public.tb;
SELECT * FROM SYS_SYNONYM WHERE synname = 'SYN_TB';
SYNNAME | SYNNAMESPACE | SYNOWNER | REFOBJNSPNAME | REFOBJNAME
---------+--------------+----------+---------------+------------SYN_TB  |        16385 |       10 | PUBLIC        | TB
(1 row)
SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TB';STATUS
--------VALID
SELECT * FROM schm.syn_tb;ID
----1
DROP TABLE public.tb;
SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TB';STATUS
--------VALID
SELECT * FROM schm.syn_tb;
ERROR:  relation "SCHM.SYN_TB" does not exist
LINE 1: SELECT * FROM schm.syn_tb;

所创建的公有同义词在PUBLIC模式下,公有同义词可以和私有同义词同名。例如:

CREATE PUBLIC SYNONYM syn_tabl FOR tabl;
CREATE SYNONYM schm.syn_tabl FOR tabl;
SELECT syn.synname, sp.nspname FROM SYS_SYNONYM syn, SYS_NAMESPACE sp
WHERE syn.synnamespace = sp.oid;SYNNAME      |  NSPNAME
------------------+------------SYN_TABL         | PUBLICSYN_TABL         | SCHM

创建公有同义词不可指定模式,创建私有同义词必须指定模式(在当前模式为PUBLIC的时候)。例:

CREATE PUBLIC SYNONYM schm.syn_tt FOR public.tab;
ERROR:  PUBLIC can not be used when schema name specified for synonym name
LINE 1: CREATE PUBLIC SYNONYM schm.syn_tt FOR public.tab;
CREATE SYNONYM syn_tt FOR public.tab;
ERROR:  missing or invalid synonym identifier,the current default schema is public
set SEARCH_PATH to schm,public;
CREATE SYNONYM syn_tt FOR public.tab;
CREATE SYNONYM

创建私有同义词不可指定为PUBLIC。

CREATE SYNONYM public.syn_tab1 FOR public.tab1;
ERROR:  missing or invalid synonym identifier
LINE 1: CREATE SYNONYM public.syn_tab1 FOR public.tab1;

同义词的使用,和使用引用对象一样。

CREATE TABLE public.tab1(id int);
INSERT INTO public.tab1 VALUES(1);
CREATE PUBLIC SYNONYM syn_tab1 FOR public.tab1;
SELECT * FROM syn_tab1;ID
----1
CREATE OR REPLACE INTERNAL FUNCTION public.increment(i integer) RETURNS
integer AS $$BEGINRETURN i + 1;END;
$$ LANGUAGE plsql;
CREATE SYNONYM syn_inc FOR public.increment;
CALL syn_inc(3);SYN_INC
---------4

兼容性

CREATE SYNONYM是KingbaseES的一种语言扩展。兼容Oracle同义词语法。

16.6. CREATE TABLE

用途

CREATE TABLE将在当前数据库中创建一个新的、初始为空的表。该表将由发出该命令的用户所拥有。

如果给定了一个模式名(例如CREATE TABLE myschema.mytable ...),那么该表被创建在指定的模式中。否则它被创建在当前模式中。该表的名称必须与同一个模式中的任何其他表、序列、索引、视图或外部表的名称区分开。

CREATE TABLE也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中任何已有数据类型的名称。

可选的约束子句指定一个插入或更新操作要成功,新的或更新过的行必须满足的约束(测试)。一个约束是一个 SQL 对象,它帮助以多种方式定义表中的合法值集合。

有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列时方便书写的记号习惯。

前置条件

要能创建一个表,你必须分别具有所有列类型或OF子句中类型的USAGE特权。

语法

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT
EXISTS ] table_name ( [{ column_name data_type [ INVISIBLE | VISIBLE ] [ COLLATE collation ] [ column_constraint [ ... ] ]| table_constraint| LIKE source_table [ like_option ... ] }[, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [
COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]
[ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] constraint [ ... ] ]
[ ENCRYPTED [BY tablekey ]]CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT
EXISTS ] table_nameOF type_name [ ({ column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]| table_constraint }[, ... ]
) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [
COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]
[ ENCRYPTED [BY tablekey ]]CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT
EXISTS ] table_namePARTITION OF parent_table [ ({ column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]| table_constraint }[, ... ]
) ] { FOR VALUES partition_bound_spec | DEFAULT }
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [
COLLATE collation ] [ opclass ] [, ... ] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]
[ ENCRYPTED [BY tablekey ]]

其中 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 index_parameters |PRIMARY KEY index_parameters |REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCHSIMPLE ][ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
[ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ]

table_constraint 是:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |UNIQUE ( column_name [, ... ] ) index_parameters |PRIMARY KEY ( column_name [, ... ] ) index_parameters |EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] )index_parameters [ WHERE ( predicate ) ] |FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [,... ] ) ][ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action ][ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
[ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ]

like_option 是:

{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED |
IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }

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 )

UNIQUE、PRIMARY KEY以及EXCLUDE约束中的index_parameters是:

[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]

一个EXCLUDE约束中的exclude_element是:

{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST
| LAST } ]

其中 constraint 是:

{ CONSTRAINT constraint_name |UNIQUE ( column_name [, ... ] ) |PRIMARY KEY }

partition_extented_spec 是:

[ INTERVAL ( interval_expr ) [ STORE IN ( tablespace_name [, …]) ]]
[ SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) }[ COLLATE collation ] [ opclass ] [, ... ] )[ { hash_subparts_by_quantity | subpartition_template } ] ]
[ ( PARTITION partition [partition_bound_spec_ex] [ TABLESPACE tablespace_name ][ ( SUBPARTITION subpartition [subpartition_bound_spec][ TABLESPACE tablespace_name ][, ... ]) | SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ] ][, ... ]
) | PARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ] ]

hash_subparts_by_quantity 是:

SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, …] ) ]

subpartition_template 是:

SUBPARTITION TEMPLATE
( SUBPARTITION [subpartition] [subpartition_bound_spec] [ TABLESPACE tablespace_name ][, …] )

partition_bound_spec_ex 是:

VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, …] ) |
VALUES ( partition_bound_expr [, …] | DEFAULT )

subpartition_bound_spec 是:

VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, …] ) |
VALUES ( partition_bound_expr [, …] | DEFAULT )

语义

TEMPORARY or TEMP

如果指定,该表被创建为一个临时表。

自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的SQL命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE

可以选择将GLOBALLOCAL写在TEMPORARYTEMP的前面。创建临时表时若不指定GLOBAL或LOCAL,则默认值指定为LOCAL。

GLOBAL

全局临时表的表定义是持久的,而表数据是临时的。

LOCAL

本地临时表的表定义和表数据都是临时的,会在会话退出后被删除。

本地临时表和全局临时表在各个会话之间数据彼此不影响;表中的数据都可以在事务结束之后删除,或者连接退出之后删除;数据都存在在临时表空间中;临时表都不记录日志。

本地临时表和全局临时表有如下四点区别:

1.本地临时表在临时模式下,用户不可以指定;但是全局临时表创建在用户指定模式下;

2.本地临时表对象本身并不是一直存在,在会话退出后,本地临时表会被删除;全局临时表创建之后,一直存在,除非显示去删除它。

3.删除本地临时表,不受其他会话影响;但是删除全局临时表时,所有会话都不能持有全部临时表的数据。

4.全局临时表不支持外键约束也不支持其他表引用全局临时表作为外键约束,而本地临时表没有这个要求。

UNLOGGED

如果指定,该表被创建为一个不受日志记录的表。被写入到不做日志的表中的数据不会被写到预写式日志中,这让它们比普通表快非常多。不过,它们在崩溃时是不安全的:一个不做日志的表在一次崩溃或非干净关闭之后会被自动地截断。一个不做日志的表中的内容也不会被复制到后备服务器中。在一个不做日志的表上创建的任何索引也会自动地不被日志记录。

IF NOT EXISTS

如果一个同名关系已经存在,不要抛出一个错误。在这种情况下会发出一个提示。注意这不保证现有的关系是和将要被创建的表相似的东西。

table_name

要被创建的表名(可以选择用模式限定)。

OF type_name

创建一个类型化的表,它的结构取自于指定的组合类型(名字可以选择用模式限定)。一个类型化的表和它的类型绑定在一起,例如如果类型被删除,该表也将被删除(用DROP TYPE ... CASCADE)。

当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在CREATE TABLE命令中直接指定。但是CREATE TABLE命令可以对表增加默认值和约束,并且可以指定存储参数。

column_name

要在新表中创建的一列的名称。

data_type

该列的数据类型。这可以包括数组说明符。更多关于KingbaseES支持的数据类型,请参考 数据类型 。

INVISIBLE | VISIBLE

该列的隐含属性,关于隐含列的特征参考Oracle语言兼容特性中关于隐含列的描述, INVISIBLE 表示该列在创建时指定为隐含列,相反地,如果不指定或者指定为VISIBLE 则表示该列是非隐含列。

COLLATE collation

COLLATE子句为该列(必须是一种可排序数据类型)赋予一个排序规则。如果没有指定,将使用该列数据类型的默认排序规则。

INHERITS ( parent_table [, ... ] )

可选的INHERITS子句指定一个表的列表,新表将从其中自动地继承所有列。父表可以是普通表或者外部表。

INHERITS的使用在新的子表和它的父表之间创建一种持久的关系。对于父表的模式修改通常也会传播到子表,并且默认情况下子表的数据会被包括在对父表的扫描中。

如果在多个父表中存在同名的列,除非父表中每一个这种列的数据类型都能匹配,否则会报告一个错误。如果没有冲突,那么重复列会被融合来形成新表中的一个单一列。如果新表中的列名列表包含一个也是继承而来的列名,该数据类型必须也匹配继承的列,并且列定义会被融合成一个。如果新表显式地为列指定了任何默认值,这个默认值将覆盖来自该列继承声明中的默认值。否则,任何父表都必须为该列指定相同的默认值,或者会报告一个错误。

CHECK约束本质上也采用和列相同的方式被融合:如果多个父表或者新表定义中包含相同的命名CHECK约束,这些约束必须全部具有相同的检查表达式,否则将报告一个错误。具有相同名称和表达式的约束将被融合成一份拷贝。一个父表中的被标记为NO INHERIT的约束将不会被考虑。注意新表中一个未命名的CHECK约束将永远不会被融合,因为那样总是会为它选择一个唯一的名字。

列的STORAGE设置也会从父表复制过来。

如果父表中的列是标识列,那么该属性不会被继承。如果需要, 可以将子表中的列声明为标识列。

PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ opclass ] [, ...] )

可选的PARTITION BY子句指定了对表进行分区的策略。 这样创建的表称为分区表。 带括号的列或表达式列表形成表的分区键。 使用范围或哈希分区时,分区键可以包含多个列或表达式(最多32个,但在构建 KingbaseES时可以更改此限制),但对于列表分区, 分区键必须由单个列或表达式组成。

范围和列表分区需要一个btree操作符类,而哈希分区需要一个哈希操作符类。如果没有显式指定运算符类,则使用适当类型的默认运算符类;如果不存在缺省操作符类,则会引发错误。当使用哈希分区时,使用的操作符类必须实现支持函数2

分区表被分成多个子表(称为分区),它们是使用单独的CREATE TABLE命令创建的。 分区表本身是空的。插入到表中的数据行将根据分区键中的列或表达式的值路由到分区。 如果没有现有的分区与新行中的值匹配,则会报告错误。

分区表不支持EXCLUDE约束,但是您可以在各个分区上定义这些约束。

可选的partition_extented_spec子句支持兼容Oracle的分区定义语法,可以在一条语句中定义单层分区表和复合分区表。

分区自动继承分区表的全部列定义、主外键索引和约束、唯一索引和约束、NOT NULL约束和CHECK约束。分区自动继承分区表的全局或者本地临时表属性。

有关表分区的更多讨论,参考 分区 。

PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT }

创建指定父表的分区。可以使用FOR VALUES创建特定值的分区,也可以使用DEFAULT创建默认分区。

``partition_bound_spec``必须对应于父表的分区方法和分区键,并且不能与父表的任何现有分区重叠。IN中的表单用于列表分区,FROMTO中的表单用于范围分区, WITH 中的表单用于哈希分区。

``partition_bound_expr``是任意无变量表达式(使子查询、窗口函数、聚合函数和集返回函数是不允许的)。它的数据类型必须与相应分区键列的数据类型匹配。表达式在表创建时只计算一次,因此它甚至可以包含volatile表达式,比如 CURRENT_TIMESTAMP

在创建列表分区时, NULL能够被指定来表示,允许分区键列为空。但是,对于给定的父表,不能有多个这样的列表分区。NULL 不能指定范围分区。

在创建一个范围分区时,指定的下界FROM是一个包含范围,而指定的上界TO是一个排他界限。也就是说,从FROM列表中指定的值是该分区对应分区键列的有效值,而从TO列表中的值则不是。 注意,这个语句必须根据行比较的规则来理解。 例如,给定 PARTITION BY RANGE (x,y)FROM (1, 2) TO (3, 4)的分区允许x=1绑定任意y>=2x=2 绑定任意非空yx=3 绑定任意y<4.

特殊值MINVALUEMAXVALUE 可以在创建范围分区时使用,以指示列的值没有下限或上限。 例如,使用FROM (MINVALUE) TO (10) 定义的分区允许任何小于10的值, 使用FROM (10) TO (MAXVALUE) 定义的分区允许任何大于或等于10的值。

当创建一个包含多个列的范围分区时,使用MAXVALUE作为下界的一部分,使用MAXVALUE作为上界的一部分,是有意义的。例如,使用FROM (0, MAXVALUE) TO (10, MAXVALUE)定义的分区允许第一个分区键列大于0且小于等于10的任何行。 类似地,使用FROM ('a', MINVALUE) TO ('b', MINVALUE) 定义的分区允许第一个分区键列以“a”开头的任何行。

注意,如果MINVALUEMAXVALUE被用于分区边界的一列,则必须为所有后续列使用相同的值。例如, (10, MINVALUE, 0) 不是有效的边界;应该写(10, MINVALUE, MINVALUE)

还要注意一些元素类型,如timestamp,有“infinity”的概念,它只是另一个可以存储的值。这不同于MINVALUEMAXVALUE, 它们不是可以存储的实际值,而是表示值是无界的。MAXVALUE 可以被认为是比任何其他价值都大,"infinity" 和MINVALUE小于任何其他值,包括"minus infinity"。FROM ('infinity') TO (MAXVALUE) 不是一个空的范围;它只允许存储一个值— "infinity"。

如果指定了DEFAULT,那么该表将被创建为父表的默认分区。此选项不适用于哈希分区表。不适合给定父分区的任何其他分区的分区键值将被路由到默认分区。

当一个表有一个现有的默认的分区,并且添加了一个新的分区时,必须扫描这个默认的分区,以确认它没有包含任何属于这个新分区的行。如果默认分区包含大量的行,那么速度可能会很慢。如果默认分区是一个外表,或者它有一个约束,证明它不能包含应该放在新分区中的行,那么扫描将被跳过。

在创建哈希分区时,必须指定模数和余数。模数必须是正整数,余数必须是小于模数的非负整数。通常,在最初设置哈希分区表时,应该选择与分区数量相等的模量,并为每个表分配相同的模量和不同的余数(参见下面的示例)。但是,并不是要求每个分区都具有相同的模量,只是散列分区表的分区之间出现的每个模量都是下一个较大的模量的因数。这使得分区的数量可以增量地增加,而不需要一次移动所有数据。例如,假设有一个具有8个分区的散列分区表,每个分区的模量为8,但是需要将分区数量增加到16。您可以分离其中一个模数-8分区,创建两个新的模数-16分区,覆盖键空间的相同部分(一个余数等于已分离分区的余数,另一个余数等于该值加上8),然后用数据重新填充它们。然后您可以对每个模数-8分区重复此操作(可能在以后的某个时间),直到没有剩余的分区。虽然在每个步骤中仍然可能涉及大量的数据移动,但是这仍然比创建一个全新的表并一次移动所有数据要好。

分区必须具有与其所属的分区表相同的列名和类型。对分区表的列名或类型的修改将自动传播到所有分区。每个分区都会自动继承CHECK约束 , 但是单个分区可以指定附加的CHECK约束; 具有与父约束相同的名称和条件的附加约束将与父约束合并。默认值可以为每个分区单独指定。

插入分区表中的行将被自动按路线发送到正确的分区。如果没有合适的分区存在,就会发生错误。

通常会影响表及其所有继承子表的TRUNCATE等操作将级联到所有分区,但也可以在单个分区上执行。请注意,删除具有DROP TABLE的分区需要在父表上获取访问独占锁。

INTERVAL ( interval_expr ) [ STORE IN ( tablespace_name [, …]) ]

可选的INTERVAL子句指定创建Interval分区表,Interval分区表是一种特殊的范围分区表。当执行INSERT或者UPDATE时,由数据库根据定义的间隔参数自动创建新的分区。当插入或者更新记录的分区键值大于等于最高分区上限时,以最高分区上限为下边界,以最高分区上限+间隔值倍数为下边界创建一个新的分区。

Interval分区表仅支持指定唯一的分区键列,类型必须是数值型或日期型。其中interval_expr是任何无变量表达式(不允许子查询、窗口函数、聚合函数和集返回函数),它的数据类型必须与唯一分区键列的数据类型相匹配。这里的类型相匹配指的是:可以在分区边界值基础上,加上间隔值(使用+运算符)可以得到一个新的分区边界值,且数据类型不变,例如:date + interval = date。 必须使用PARTITION子句指定至少一个范围分区。不能在VALUES子句中指定MAXVALUE,也不能为分区键列指定NULL值。

使用STORE IN可以为Interval分区表指定表空间,新的分区以轮循方式使用指定的各个表空间,如果省略STORE IN时,则使用分区表的表空间。

如果指定分区表为复合分区表,可选的INTERVAL子句指定创建Interval复合分区表。如果定义了子分区模板,则新的分区将按子分区模板创建下级子分区,否则将根据子分区类型自动创建默认的子分区。

SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ opclass ] [, ...] )

可选的SUBPARTITION BY子句指定了对表进行二级分区的策略。这样创建的表称为复合分区表。带括号的列或表达式列表形成表的子分区键。 使用范围或哈希子分区时,子分区键可以包含多个列或表达式(最多32个,但在构建KingbaseES时可以更改此限制),但对于列表子分区,子分区键必须由单个列或表达式组成。

partition_bound_spec_exsubpartition_bound_spec必须分别与分区和子分区的分区方法和分区键对应,而不能与其他分区和子分区重叠。VALUES用于列表分区和子分区,VALUE LESS THAN用于范围分区和子分区。

VALUE LESS THAN定义了范围分区的上边界(不包含边界值),使用分区键值与子句指定的有序值列表进行比较,满足条件的行将被存储在分区中。使用MAXVALUE可以定义分区键值的最大值,该最大值总是大于其他任何值(包括null)。

如果在VALUES后指定了NULL,表示分区允许分区键列为空。如果在VALUES后指定了DEFAULT,表示分区为默认分区。在列表分区表中仅允许存在一个NULLDEFAULT分区,在每个复合分区表的主分区中也仅允许存在一个这样的子分区。

PARTITIONSSUBPARTITIONS可以通过指定哈希数量方式定义多个哈希分区和子分区,numeric_literal为正整数。数据库为每个哈希分区自动分配table_name_pn的分区名称,为每个哈希子分区自动分配table_name_subpn的分区名称。

使用PARTITION可以按名称指定各个分区,并为每个分区单独指定表空间。使用TABLESPACE可以为分区单独指定表空间,如果省略会则使用分区表的表空间。 使用STORE IN可以为哈希分区或者子分区指定一个或多个表空间。表空间的数量不必等于分区的数量,表空间按顺序指定给各个哈希分区。如果分区数大于表空间数,余下的分区使用分区表的表空间。

可选的SUBPARTITION TEMPLATE子句可以为复合分区表指定子分区模板。子分区模板是默认的复合分区表分区划分方法,如果在主分区定义中指定了子分区定义,则子分区定义优先于子分区模板。

LIKE source_table [ like_option ... ]

LIKE指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。

INHERITS不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表,并且不可能在原始表的扫描中包括新表的数据。

与继承不同的是,类似的复制列和约束不会与类似命名的列和约束合并。如果显式地指定了相同的名称,或者在另一个LIKE子句中,错误就会被通知。

可选的``like_option`` 子句指定所要复制的原始表的附加属性。指定INCLUDING 复制属性,指定EXCLUDING省略属性。 EXCLUDING是默认的。 如果为同一类型的对象制定了多个规范,则使用最后一个规范。可用的选项有:

INCLUDING COMMENTS

复制列、约束和索引的注释将被复制。默认行为是排除注释,导致新表中复制的列和约束没有注释。

INCLUDING CONSTRAINTS

CHECK 约束将被复制。 列约束和表约束之间没有区别。非空约束总是复制到新表中。

INCLUDING DEFAULTS

复制列定义的默认表达式将被复制。否则,将不复制默认表达式,从而导致新表中复制的列具有空默认值。注意,复制调用数据库修改函数(如nextval)的默认值可能会在原始表和新表之间创建功能链接。

INCLUDING GENERATED

复制列定义的任何生成表达式都将被复制。默认情况下,新列将是常规的基本列。

INCLUDING IDENTITY

复制列定义的任何标识规范都将被复制。为新表的每个标识列创建一个新序列,与与旧表关联的序列分离。

INCLUDING INDEXES

原始表上的Indexes、PRIMARY KEYUNIQUE、和EXCLUDE约束将在新表上创建。 新索引和约束的名称是根据默认规则选择的,而不管原始索引和约束是如何命名的。(这种行为可以避免新索引可能出现的重复命名错误。)

INCLUDING STATISTICS

扩展的统计信息被复制到新表中。

INCLUDING STORAGE

STORAGE将复制复制列定义的设置。 默认行为是排除STORAGE设置, 使得新表中复制的列具有类型特定的默认设置。

INCLUDING ALL

INCLUDING ALL是选择所有可用的单独选项的缩写形式。(在INCLUDING ALL之后选择除某些特定选项外的所有选项,编写单独的EXCLUDING子句是有用的。)

LIKE子句也能被用来从视图、外部表或组合类型拷贝列定义。不适合的选项(例如来自视图的INCLUDING INDEXES)会被忽略。

CONSTRAINT constraint_name

一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似列必须为正的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如果没有指定约束名,系统将生成一个。

NOT NULL

该列不允许包含空值。

NULL

该列允许包含空值。这是默认情况。

这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。

CHECK ( expression ) [ NO INHERIT ]

CHECK指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。

当前,CHECK表达式不能包含子查询,也不能引用当前行的列之外的变量。 可以引用系统列tableoid,但不能引用其他系统列。

一个被标记为NO INHERIT的约束将不会传播到子表。

当一个表有多个CHECK约束时,检查完NOT NULL约束后,对于每一行会以它们名称的字母表顺序来进行检查( V8.3 版本之前的KingbaseES对于CHECK约束不遵从任何特定的引发顺序)。

DEFAULT default_expr

DEFAULT子句为出现在其定义中的列赋予一个默认数据。 该值是可以使用变量的表达式(尤其是,不允许对其他列的交叉引用)。子查询也不被允许。 默认值表达式的数据类型必须匹配列的数据类型。

默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。

GENERATED ALWAYS AS ( generation_expr ) STORED

此子句将列创建为函数索引。无法写入该列,读取时将返回指定表达式的结果。

关键字STORED 表示该列将在写时计算并存储在磁盘上。

生成表达式可以引用表中的其他列,但不能引用其他函数索引。所使用的任何函数和操作符都必须是不可变的。不允许引用其他表。

GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]

该子句将列创建为标识列。 它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中获取值。

子句ALWAYSBY DEFAULT确定在 INSERT语句中,序列值如何优先于用户指定的值。 如果指定了ALWAYS,则只有在INSERT 语句指定OVERRIDING SYSTEM VALUE时才接受用户指定的值。 如果指定了BY DEFAULT,则用户指定的值优先。 有关详细信息,请参见 INSERT 。 (在COPY命令中,无论此设置如何,都始终使用用户指定的值。)

可选的``sequence_options``子句可用于覆盖序列的选项。有关详细信息,请参见 CREATE SEQUENCE 。

UNIQUE (列约束) UNIQUE ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束)

UNIQUE约束指定一个表中的一列或多列组成的组包含唯一的值。唯一表约束的行为与列约束的行为相同,只是表约束能够跨越多列。

对于一个唯一约束的目的来说,空值不被认为是相等的。

每一个唯一表约束必须命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不相同(否则它将是一个被列举了两次的约束)。

在为多级分区层次结构建立唯一约束时,必须在约束定义中包含目标分区表的分区键的所有列,以及它的所有子代分区表的列。

添加唯一约束将自动在约束中使用的列或列组上创建唯一的btree索引。可选子句INCLUDE添加到索引的一个或多个列上,在这些列上不强制唯一性。注意,虽然约束没有强制包含在列上,但它仍然依赖于它们。因此,这些列上的某些操作(例如DROP COLUMN)可能导致级联约束和索引删除。

PRIMARY KEY (列约束) PRIMARY KEY ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束)

PRIMARY KEY约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个主键,可以作为列约束或表约束。

主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余的并且会被丢弃)。

PRIMARY KEY强制的数据约束可以看成是UNIQUENOT 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约束,尽管一个普通的唯一约束将更快。不过,排除约束能够指定比简单相等更通用的约束。例如,你可以使用&&操作符指定一个约束,要求表中没有两行包含相互覆盖的圆(见 几何类型 )。

排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法``index_method``的一个适当的操作符类(见 操作符类和操作符族 )相关联。操作符被要求是交换的。每一个``exclude_element``可以选择性地指定一个操作符类或者顺序选项,这些在 CREATE INDEX 中有完整描述。

访问方法必须支持amgettuple,目前这意味着GIN无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是GiST或SP-GiST。

``predicate``允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周围的圆括号是必须的。

REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (列约束) FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (表约束)

这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在被引用列上的值。如果``refcolumn``列表被忽略,将使用``reftable``的主键。被引用列必须是被引用表中一个非可延迟唯一约束或主键约束的列。 用户必须在被引用的表(或整个表或特定的引用列)上拥有REFERENCES 权限。The addition of a foreign key constraint requires a SHARE ROW EXCLUSIVE lock on the referenced table.

被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。有三种匹配类型:MATCH FULLMATCH PARTIAL以及MATCH SIMPLE(这是默认值)。 MATCH FULL将不允许一个多列外键中的一列为空,除非所有外键列都是空;如果它们都是空,则不要求该行在被引用表中有一个匹配。MATCH SIMPLE允许任意外键列为空,如果任一为空,则不要求该行在被引用表中有一个匹配。MATCH PARTIAL现在还没有被实现(当然,NOT NULL约束能被应用在引用列上来组织这些情况发生)。

另外,当被引用列中的数据被改变时,在这个表的列中的数据上可以执行特定的动作。ON DELETE指定当被引用表中一个被引用行被删除时要执行的动作。同样,ON UPDATE指定当被引用表中一个被引用列被更新为新值时要执行的动作。如果该行被更新,但是被引用列并没有被实际改变,不会做任何动作。除了NO ACTION检查之外的引用动作不能被延迟,即便该约束被声明为可延迟的。对每一个子句可能有以下动作:

NO ACTION

产生一个错误指示删除或更新将会导致一个外键约束违背。如果该约束被延迟,并且仍存在引用行,这个错误将在约束检查时被产生。这是默认动作。

RESTRICT

产生一个错误指示删除或更新将会导致一个外键约束违背。这个动作与NO ACTION形同,不过该检查不是可延迟的。

CASCADE

删除任何引用被删除行的行,或者把引用列的值更新为被引用列的新值。

SET NULL

将引用列设置为空。

SET DEFAULT

设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认值,否则该操作将会失败)。

如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效地被执行。

DEFERRABLE NOT DEFERRABLE

这个子句控制该约束是否能被延迟。一个不可延迟的约束将在每一次命令后立刻被检查。可延迟约束的检查将被推迟到事务结束时进行(使用 SET CONSTRAINTS 命令)。NOT DEFERRABLE是默认值。当前,只有UNIQUEPRIMARY KEYEXCLUDE以及REFERENCES(外键)约束接受这个子句。NOT NULL以及CHECK约束是不可延迟的。注意在包括ON CONFLICT DO UPDATE子句的INSERT语句中,可延迟约束不能被用作冲突裁判者。

INITIALLY IMMEDIATE INITIALLY DEFERRED

如果一个约束是可延迟的,这个子句指定检查该约束的默认时间。如果该约束是INITIALLY IMMEDIATE,它会在每一个语句之后被检查。这是默认值。如果该约束是INITIALLY DEFERRED,它只会在事务结束时被检查。约束检查时间可以用 SET CONSTRAINTS 命令修改。

ENABLE VALIDATE/NOVALIDATE DISABLE NOVALIDATE/VALIDATE

这个子句用来设置或修改约束的状态,包括ENABLE/DISABLEVALIDATE/NOVALIDATE两个组合,共四个状态。如果该约束是ENABLE,数据库中输入或者更新数据要进行约束规则检查,不符合约束规则的数据不能输入数据库,这是默认值。相反如果该约束是DISABLE,那么输入或更新数据将不会进行约束规则检查。一个VALIDATE状态的约束表示数据库内已有数据符合约束规则。如果设置或修改约束为ENABLE状态时并未指定有效性状态,VALIDATE是默认值。一个DISABLE VALIDATE状态的约束,为了保证有效性状态不被破坏,会将数据库表设置为只读状态,禁用对表的DML操作。如果为一个存在的表增加VALIDATE状态的约束,将会对表内的数据做约束规则检查。一个NOVALIDATE状态的约束表示数据库表内已有数据未做约束规则检查。设置或修改约束为DISABLE状态时,如果未指定有效性状态,NOVALIDATE是默认值。如果为一个存在的表增加NOVALIDATE状态的约束,将不会对已有数据做有效性检查(ENABLE状态的唯一约束和主键约束依赖于索引,创建索引会检查已有数据的唯一性)。

目前这个子句只支持检查约束、唯一约束、主键和外键约束。

在分区表上创建或修改约束状态时,约束状态会级联应用到分区上的约束。分区表上的父约束与分区上的子约束状态总是保持相同的,不可以单独修改分区表或分区上的有继承关系约束状态,但是对于分区表或者分区上独立的约束可以单独修改约束状态。

USING method

此可选子句指定用于存储新表的内容的表访问方法;该方法需要是类型TABLE的访问方法。

如果未指定此选项,则为新表选择默认的表访问方法。更多信息,参考default_table_access_method。

WITH ( storage_parameter [= value] [, ... ] )

这个子句为一个表或索引指定可选的存储参数 。为了向后兼容,WITH子句可以包含OIDS=FALSE以指定新表的行不应该包含OIDs(对象标识符), OIDS=TRUE不再被支持。

WITHOUT OIDS

这是向后兼容的语法,用于声明一个没有OIDS的表,现在已经不支持创建一个有OIDS的表。

ON COMMIT

临时表在一个事务块结束时的行为由ON COMMIT控制。三种选项是:

PRESERVE ROWS

在事务结束时不采取特殊的动作。是本地临时表采用的默认行为

DELETE ROWS

在每一个事务块结束时将删除临时表中的所有行。实质上,在每一次提交时会完成一次 自动的 TRUNCATE 。 在分区表上使用时,不会将其级联到其分区。这是全局临时表的默认行为。

DROP

在当前事务块结束时将删除临时表。在分区表上使用时,此操作将删除其分区,在具有继承子级的表上使用时,将删除依赖子级。仅本地临时表支持在当前事务块结束时将删除临时表。为兼容Oracle,全局临时表不支持ON COMMIT DROP选项。

TABLESPACE tablespace_name

``tablespace_name``是新表要创建于其中的 表空间名称。如果没有指定,将参考default_tablespace,或者如果 表是临时的则参考temp_tablespaces。对于分区表,由于表本身不需要存储,所以指定的表空间将覆盖default_tablespace,作为在没有显式指定其他表空间的情况下为任何新创建的分区使用的默认表空间。

USING INDEX TABLESPACE tablespace_name

这个子句允许选择与一个UNIQUEPRIMARY KEY或者EXCLUDE约束相关的索引将被创建在哪个表空间中。如果没有指定,将参考default_tablespace,或者如果表是临时的则参考temp_tablespaces。

ENCRYPTED [ BY tablekey ]

如果指定ENCRYPTED,该表被创建为一个加密表,表的子表和索引数据都会被加密保存在磁盘上。加密表的数据有更好的安全性,可以防止物理上的数据泄露。 创建表时可以用tablekey来指定使用的秘钥,如果没有指定会自动生成随机秘钥。

示例

创建表films和表distributors

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 <> '')
);

创建有一个二维数组的表:

CREATE TABLE array_int (vector  int[][]
);

为表films定义一个唯一表约束。唯一表约束能够被定义在表的一列或多列上:

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)
);

定义一个列检查约束:

CREATE TABLE distributors (did     integer CHECK (did > 100),name    varchar(40)
);

定义一个表检查约束:

CREATE TABLE distributors (did     integer,name    varchar(40),CONSTRAINT con1 CHECK (did > 100 AND name <> '')
);

为表films定义一个主键表约束:

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定义一个主键约束。下面的两个例子是等价的,第一个使用表约束语法,第二个使用列约束语法:

CREATE TABLE distributors (did     integer,name    varchar(40),PRIMARY KEY(did)
);CREATE TABLE distributors (did     integer PRIMARY KEY,name    varchar(40)
);

为列name赋予一个文字常量默认值,安排列did的默认值是从一个序列对象中选择下一个值产生,并且让modtime的默认值是该行被插入的时间:

CREATE TABLE distributors (name      varchar(40) DEFAULT 'Luso Films',did       integer DEFAULT nextval('distributors_serial'),modtime   timestamp DEFAULT current_timestamp
);

在表distributors上定义两个NOT NULL列约束,其中之一被显式给定了一个名称:

CREATE TABLE distributors (did     integer CONSTRAINT no_null NOT NULL,name    varchar(40) NOT NULL
);

name列定义一个唯一约束:

CREATE TABLE distributors (did     integer,name    varchar(40) UNIQUE
);

同样的唯一约束用表约束指定:

CREATE TABLE distributors (did     integer,name    varchar(40),UNIQUE(name)
);

创建相同的表,指定表和它的唯一索引指定 70% 的填充因子:

CREATE TABLE distributors (did     integer,name    varchar(40),UNIQUE(name) WITH (fillfactor=70)
)
WITH (fillfactor=70);

创建表circles,带有一个排除约束阻止任意两个圆重叠:

CREATE TABLE circles (c circle,EXCLUDE USING gist (c WITH &&)
);

在表空间diskvol1中创建表cinemas

CREATE TABLE cinemas (id serial,name text,location text
) TABLESPACE diskvol1;

创建一个组合类型以及一个类型化的表:

CREATE TYPE employee_type AS (name text, salary numeric);CREATE TABLE employees OF employee_type (PRIMARY KEY (name),salary WITH OPTIONS DEFAULT 1000
);

创建一个范围分区表:

CREATE TABLE measurement (logdate         date not null,peaktemp        int,unitsales       int
) PARTITION BY RANGE (logdate);

创建在分区键中具有多个列的范围分区表:

CREATE TABLE measurement_year_month (logdate         date not null,peaktemp        int,unitsales       int
) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate));

创建列表分区表:

CREATE TABLE cities (city_id      bigserial not null,name         text not null,population   bigint
) PARTITION BY LIST (left(lower(name), 1));

创建哈希分区表:

CREATE TABLE orders (order_id     bigint not null,cust_id      bigint not null,status       text
) PARTITION BY HASH (order_id);

创建范围分区表的分区:

CREATE TABLE measurement_y2016m07PARTITION OF measurement (unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');

使用分区键中的多个列创建范围分区表的几个分区:

CREATE TABLE measurement_ym_olderPARTITION OF measurement_year_monthFOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);CREATE TABLE measurement_ym_y2016m11PARTITION OF measurement_year_monthFOR VALUES FROM (2016, 11) TO (2016, 12);CREATE TABLE measurement_ym_y2016m12PARTITION OF measurement_year_monthFOR VALUES FROM (2016, 12) TO (2017, 01);CREATE TABLE measurement_ym_y2017m01PARTITION OF measurement_year_monthFOR VALUES FROM (2017, 01) TO (2017, 02);

创建列表分区表的分区:

CREATE TABLE cities_abPARTITION OF cities (CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b');

创建本身是分区的列表分区表的分区,然后向其添加分区:

CREATE TABLE cities_abPARTITION OF cities (CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population);CREATE TABLE cities_ab_10000_to_100000PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);

创建哈希分区表的磁盘分区:

CREATE TABLE orders_p1 PARTITION OF ordersFOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF ordersFOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF ordersFOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF ordersFOR VALUES WITH (MODULUS 4, REMAINDER 3);

创建默认的分区:

CREATE TABLE cities_partdefPARTITION OF cities DEFAULT;

创建范围分区表:

CREATE TABLE sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), state_id varchar2(2), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))
PARTITION BY RANGE (time_id)( PARTITION q1_2006 VALUES LESS THAN ('2006-04-01'), PARTITION q2_2006 VALUES LESS THAN ('2006-07-01'), PARTITION q3_2006 VALUES LESS THAN ('2006-10-01'), PARTITION q4_2006 VALUES LESS THAN ('2007-01-01'));

创建列表分区表:

CREATE TABLE sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), state_id varchar2(2), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))
PARTITION BY LIST (state)( PARTITION northwest VALUES ('OR', 'WA'), PARTITION southwest VALUES ('AZ', 'UT', 'NM'), PARTITION northeast VALUES ('NY', 'VM', 'NJ'), PARTITION southeast VALUES ('FL', 'GA'), PARTITION northcentral VALUES ('SD', 'WI'), PARTITION southcentral VALUES ('OK', 'TX'), PARTITION defaultstate VALUES (DEFAULT));

创建哈希分区表:

CREATE TABLE sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), state_id varchar2(2), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))
PARTITION BY HASH(channel_id)( PARTITION p1, PARTITION p2, PARTITION p3, PARTITION p4);

创建列表-列表复合分区表:

CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY LIST(userlevel)
SUBPARTITION BY LIST(territory)
(PARTITION level1 VALUES (1, 2, 3)(SUBPARTITION eastasia1 VALUES ('CHINA', 'JAPAN'),SUBPARTITION southeastasia1 VALUES ('THAILAND'),SUBPARTITION southasia1 VALUES ('INDIA'),SUBPARTITION centralasia1 VALUES ('KAZAKHSTAN'),SUBPARTITION westasia1 VALUES ('IRAN'),SUBPARTITION rest1 VALUES (DEFAULT)),PARTITION level2 VALUES (4, 5, 6)(SUBPARTITION eastasia2 VALUES ('CHINA', 'JAPAN'),SUBPARTITION southeastasia2 VALUES ('THAILAND'),SUBPARTITION southasia2 VALUES ('INDIA'),SUBPARTITION centralasia2 VALUES ('KAZAKHSTAN'),SUBPARTITION westasia2 VALUES ('IRAN'),SUBPARTITION rest2 VALUES (DEFAULT))
);CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY LIST(userlevel)
SUBPARTITION BY LIST(territory)
SUBPARTITION TEMPLATE
(SUBPARTITION eastasia VALUES ('CHINA', 'JAPAN'),SUBPARTITION southeastasia VALUES ('THAILAND'),SUBPARTITION southasia VALUES ('INDIA'),SUBPARTITION centralasia VALUES ('KAZAKHSTAN'),SUBPARTITION rest VALUES (DEFAULT)
)
(PARTITION level1 VALUES (1, 2, 3),PARTITION level2 VALUES (4, 5, 6)
);

创建列表-哈希复合分区表:

CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY LIST (userlevel)
SUBPARTITION BY HASH (customer_id)
(PARTITION level1 VALUES (1,2,3)(SUBPARTITION level1_hash1,SUBPARTITION level1_hash2,SUBPARTITION level1_hash3,SUBPARTITION level1_hash4),PARTITION level2 VALUES (4,5,6)(SUBPARTITION level2_hash1,SUBPARTITION level2_hash2,SUBPARTITION level2_hash3,SUBPARTITION level2_hash4)
);CREATE TABLE customers
(customer_id  NUMBER(6),name         VARCHAR2(20),regdate      date,email        VARCHAR2(30),territory    VARCHAR2(20),userlevel    NUMBER(2)
)
PARTITION BY LIST (userlevel)
SUBPARTITION BY HASH (customer_id)
SUBPARTITION TEMPLATE
(SUBPARTITION hash1,SUBPARTITION hash2,SUBPARTITION hash3,SUBPARTITION hash4
)
(PARTITION level1 VALUES (1,2,3),PARTITION level2 VALUES (4,5,6)
);

创建列表-范围复合分区表:

CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY LIST(userlevel)
SUBPARTITION BY RANGE(regdate)
(PARTITION level1 VALUES (1, 2, 3)(SUBPARTITION reg1_20_q1 VALUES LESS THAN('2020-04-01'),SUBPARTITION reg1_20_q2 VALUES LESS THAN('2020-07-01'),SUBPARTITION reg1_20_q3 VALUES LESS THAN('2020-10-01'),SUBPARTITION reg1_20_q4 VALUES LESS THAN('2021-01-01'),SUBPARTITION reg1_upper VALUES LESS THAN(MAXVALUE)),PARTITION level2 VALUES (4, 5, 6)(SUBPARTITION reg2_20_q1 VALUES LESS THAN('2020-04-01'),SUBPARTITION reg2_20_q2 VALUES LESS THAN('2020-07-01'),SUBPARTITION reg2_20_q3 VALUES LESS THAN('2020-10-01'),SUBPARTITION reg2_20_q4 VALUES LESS THAN('2021-01-01'),SUBPARTITION reg2_upper VALUES LESS THAN(MAXVALUE))
);CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY LIST(userlevel)
SUBPARTITION BY RANGE(regdate)
SUBPARTITION TEMPLATE
(SUBPARTITION reg2_20_q1 VALUES LESS THAN('2020-04-01'),SUBPARTITION reg2_20_q2 VALUES LESS THAN('2020-07-01'),SUBPARTITION reg2_20_q3 VALUES LESS THAN('2020-10-01'),SUBPARTITION reg2_20_q4 VALUES LESS THAN('2021-01-01'),SUBPARTITION reg_upper VALUES LESS THAN(MAXVALUE)
)
(PARTITION level1 VALUES (1, 2, 3),PARTITION level2 VALUES (4, 5, 6)
);

创建INTERVAL分区表:

CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY RANGE (regdate) INTERVAL ('3 month'::interval)
(PARTITION p0 VALUES LESS THAN(TO_DATE('2020-04-01', 'YYYY-MM-DD'))
);

创建INTERVAL复合分区表:

CREATE TABLE customers
(customer_id     NUMBER(6),name            VARCHAR2(20),regdate         date,email           VARCHAR2(30),territory       VARCHAR2(20),userlevel       NUMBER(2)
)
PARTITION BY RANGE (regdate) INTERVAL ('3 month'::interval)
SUBPARTITION BY HASH (customer_id)
SUBPARTITION TEMPLATE
(SUBPARTITION hash1,SUBPARTITION hash2,SUBPARTITION hash3,SUBPARTITION hash4
)
(PARTITION p0 VALUES LESS THAN(TO_DATE('2020-04-01', 'YYYY-MM-DD'))
);

兼容性

CREATE TABLE命令遵从SQL标准,除了以下例外。

  1. 临时表

    尽管CREATE TEMPORARY TABLE的语法很像 SQL 标准的语法,但事实是并不相同。在标准中,临时表只需要被定义一次并且会自动地存在(从空内容开始)于需要它们的每一个会话中。KingbaseES则要求每一个会话为每一个要用的临时表发出它自己的CREATE TEMPORARY TABLE命令。这允许不同的会话为不同的目的使用相同的临时表名,而标准的方法约束一个给定临时表名的所有实例都必须具有相同的表结构。

    标准中对于临时表行为的定义被广泛地忽略了。KingbaseES在这一点上的行为和多种其他 SQL 数据库是相似的。

    SQL 标准也区分全局和本地临时表,其中一个本地临时表为每一个会话中的每一个 SQL 模块具有一个独立的内容集合,但是它的定义仍然是多个会话共享的。因为KingbaseES不支持 SQL 模块,这种区别与KingbaseES无关。

  2. 非延迟唯一性约束

    但一个UNIQUEPRIMARY KEY约束是非可延迟的,只要一个行被插入或修改,KingbaseES就会立即检查唯一性。SQL 标准指出只有在语句结束时才应该强制唯一性。当一个单一命令更新多个键值时,这两者是不同的。要得到兼容标准的行为,将该约束声明为DEFERRABLE但是不延迟(即INITIALLY IMMEDIATE)。注意这可能要显著地慢于立即唯一性检查。

  3. 列检查约束

    SQL 标准指出CHECK列约束只能引用它们应用到的列,只有CHECK表约束能够引用多列。KingbaseES并没有强制这个限制,它同样处理列检查约束和表检查约束。

  4. EXCLUDE约束

    EXCLUDE约束类型是一种KingbaseES扩展。

  5. NULL约束

    NULL “约束”(实际上是一个非约束)是一个KingbaseES对 SQL 标准的扩展,它也被包括(以及对称的NOT NULL约束)在一些其他的数据库系统中以实现兼容性。因为它是任意列的默认值,它的存在就像噪声一样。

  6. 约束的命名

    SQL标准规定,表和域约束的名称必须在包含表或域的模式中是唯一的。 KingbaseES 是宽松的: 它只要求约束名称在附加到特定表或域的约束之间是唯一的。然而,这种额外的自由对于基于索引的约束并不存在(UNIQUE、 PRIMARY KEY、和EXCLUDE约束),因为关联的索引与约束的名称相同,而且索引名称必须在相同模式中的所有关系中是惟一的。

    当前,KingbaseES不记录NOT NULL约束的名称, 所以它们不受唯一性限制。在将来的版本中可能会有所改变。

  7. 继承

    通过INHERITS子句的多继承是一种KingbaseES的语言扩展。SQL:1999 以及之后的标准使用一种不同的语法和不同的语义定义了单继承。SQL:1999-风格的继承还没有被KingbaseES。

  8. 零列表

    KingbaseES允许创建一个没有列的表(例如CREATE TABLE foo();)。这是一个对于 SQL 标准的扩展,它不允许零列表。零列表本身并不是很有用,但是不允许它们会为ALTER TABLE DROP COLUMN带来奇怪的特殊情况,因此忽略这种规则限制看起来更加整洁。

  9. 多个标识列

    KingbaseES允许一个表拥有多个标识列。 该标准指定一个表最多只能有一个标识列。这主要是为了给模式更改或迁移提供更大的灵活性。 请注意,INSERT命令仅支持一个适用于整个语句的覆盖子句, 因此不支持具有不同行为的多个标识列。

  10. 生成列

    存储的选项不是标准的,但是其他SQL在实践中也使用它。SQL标准没有指定生成列的存储。

  11. LIKE子句

    虽然 SQL 标准中有一个LIKE子句,但是KingbaseES接受的很多LIKE子句选项却不在标准中,并且有些标准中的选项也没有被KingbaseES实现。

  12. WITH子句

    WITH子句是一个KingbaseES扩展, 存储参数不在标准中。

  13. 表空间

    KingbaseES的表空间概念不是标准的一部分。因此,子句TABLESPACEUSING INDEX TABLESPACE是扩展。

  14. 类型化的表

    类型化的表实现了 SQL 标准的一个子集。根据标准,一个类型化的表具有与底层组合类型相对应的列,以及其他的“自引用列”。KingbaseES不显式支持这些自引用列。

  15. PARTITION BY子句

    PARTITION BY子句是KingbaseES的一个扩展。

  16. PARTITION OF子句

    PARTITION OF子句KingbaseES的一个扩展。

其他

由于包中的类型以package.type的格式存储到pg_type中,为防止用户自定义类型(表)与包中类型相冲突,故不支持用户自定义带‘.’的类型或者表。 如果创建表名带 '.' 的普通表,如:create table "Evil.Table"(id serial);会报错 ERROR: type or table name can not include '.'。

16.7. CREATE TABLE AS

用途

CREATE TABLE AS创建一个表,并且用 由一个SELECT命令计算出来的数据填充 该表。该表的列具有和SELECT的输出列 相关的名称和数据类型(不过可以通过给出一个显式的新列名列表来覆 盖这些列名)。

CREATE TABLE AS和创建一个视图有些 相似,但是实际上非常不同:它会创建一个新表并且只计算该查询一次 用来初始填充新表。这个新表将不会跟踪该查询源表的后续变化。相反, 一个视图只要被查询,它的定义SELECT 语句就会被重新计算。

前置条件

你必须要有一个查询结果以使用 CREATE TABLE AS 。还必须要有 CREATE 特权。

语法

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name[ (column_name [, ...] ) ][ USING method ][ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ][ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ][ TABLESPACE tablespace_name ]AS query[ WITH [ NO ] DATA ]

语义

GLOBAL或者LOCAL

KingbaseES支持本地临时表和全局临时表,详见 CREATE TABLE 。

TEMPORARY或者TEMP

如果被指定,该表会被创建为一个临时表。详见 CREATE TABLE 。

UNLOGGED

如果被指定,该表会被创建为一个不做日志的表。详见 CREATE TABLE 。

IF NOT EXISTS

如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。详见 CREATE TABLE 。

table_name

要创建的表的名称(可以被模式限定)。

column_name

新表中一列的名称。如果没有提供列名,会从查询的输出列名中得到。

USING method

此可选子句指定用于存储新表的内容的表访问方法;该方法需要是类型TABLE的访问方法。如果未指定此选项,则为新表选择默认的表访问方法。有关更多信息,参见default_table_access_method。

WITH ( storage_parameter [= value] [, ... ] )

这个子句为新表指定可选的存储参数。 为了向后兼容,表的WITH子句还可以包含OIDS=FALSE,以指定新表的行应该不包含oid(对象标识符),OIDS=TRUE不再被支持。

WITH OIDS WITHOUT OIDS

这是向后兼容的语法,用于声明一个WITHOUT OIDS表,创建一个WITH OIDS表不再受支持。

ON COMMIT

临时表在事务块结束时的行为可以用``ON COMMIT``控制。三个选项是:

PRESERVE ROWS

在事务结束时不采取特殊的动作。这是默认行为。

DELETE ROWS

在每一个事务块结束时临时表中的所有行都将被删除。本质上, 在每次提交时会完成一次自动的 TRUNCATE 。

DROP

在当前事务块结束时将删掉临时表。

TABLESPACE tablespace_name

``tablespace_name`` 是要在其中创建新表的表空间名称。如果没有指定,将会查询default_tablespace,临时表会查询temp_tablespaces 。

query

一个 SELECT 或者 VALUES 命令,或者是一个运行准备好的SELECT、 TABLE或者 VALUES查询的 EXECUTE 命令。

WITH [ NO ] DATA

这个子句指定查询产生的数据是否应该被复制到新表中。如果不是,只有 表结构会被复制。默认是复制数据。

示例

创建一个新表films_recent,它只由表``films``中最近的项组成:

CREATE TABLE films_recent ASSELECT * FROM films WHERE date_prod >= '2002-01-01';

要完全地复制一个表,也可以使用TABLE命令的 简短形式:

CREATE TABLE films2 ASTABLE films;

用一个预备语句创建一个新的临时表films_recent,它仅由表films中最近的项组成。新表将在提交时被删除:

PREPARE recentfilms(date) ASSELECT * FROM films WHERE date_prod > $1;
CREATE TEMP TABLE films_recent ON COMMIT DROP ASEXECUTE recentfilms('2002-01-01');

兼容性

CREATE TABLE AS符合 SQL标准。下面的是非标准扩展:

  • 标准要求在子查询子句周围有圆括号,在KingbaseES中这些圆括号是可选的。

  • 在标准中,WITH [ NO ] DATA子句是必要的,而KingbaseES 中是可选的。

  • KingbaseES处理临时表的方式和标准不同。 详见 CREATE TABLE 。

  • WITH子句是一种 KingbaseES扩展, 标准中没有存储参数。

  • KingbaseES的表空间概念是标准的一部分。因此,子句TABLESPACE是一种扩展。

其他

这个命令在功能上类似于 SELECT INTO ,但是它更好, 因为不太可能被SELECT INTO语法的其他使用混淆。更 进一步,CREATE TABLE AS提供了 SELECT INTO的功能的一个超集。

16.8. CREATE TABLESPACE

用途

CREATE TABLESPACE注册一个新的集簇范围

的表空间。表空间的名称必须与数据库集簇中现有的任何表空间不同。

表空间允许超级用户在文件系统上定义另一个位置,可以把包含数据库对象 (例如表和索引)的数据文件放在那里。

一个具有适当特权的用户可以把 ``tablespace_name``传递给 CREATE DATABASECREATE TABLE、 CREATE INDEX或者ADD CONSTRAINT 来让这些对象的数据文件存储在指定的表空间中。

警告

表空间不能独立于定义它的集簇使用,见 表空间 。表空间指定的directory不能位于数据库集簇目录下。

前置条件

只有在支持符号链接的系统上才支持表空间。

CREATE TABLESPACE不能在一个事务块内被执行。

语法

CREATE TABLESPACE tablespace_name[ OWNER { new_owner | CURRENT_USER | SESSION_USER } ]LOCATION 'directory'[ ONLINE | OFFLINE ][ WITH ( tablespace_option = value [, ... ] ) ]

语义

tablespace_name

要创建的表空间的名称。该名称不能以sys_开头,因为sys_名称是为系统表空间保留的。

user_name

将拥有该表空间的用户名。如果省略,默认为执行该命令的用户。只有 超级用户能创建表空间,但是它们能把表空间的拥有权赋予给非超级 用户。

directory

要被用于表空间的目录。该目录如果存在(CREATE TABLESPACE指定的目录不存在则会创建该目录), 应该为空并且必须由 KingbaseES系统用户拥有。该目录必须用一个绝对路径指定。

tablespace_option

要设置或者重置的表空间参数。当前,唯一可用的参数是 seq_page_costrandom_page_cost 以及effective_io_concurrency为一个特定表空间设定其中一个值将覆盖规划器对该表空间中表页读取的 常规代价估计,常规代价估计是由同名的配置参数所建立(见seq_page_cost、random_page_cost 、effective_io_concurrency )。如果一个表空间位于一个 比其他 I/O 子系统更慢或者更快的磁盘上,这些参数就能发挥作用。

通过指定encryption参数来确定表空间是否加密。通过制定enckey参数来指定用户的表空间密钥

此外还有和表空间模式相关的参数online_mode、 readonly_mode, 以上两个参数均为bool类型, 分别代表表空间的一级模式ONLINE/OFFLINE 和二级模式READONLY /READWRITE。 其中创建表空间只能指定online_modereadonly_mode 的设置可以在表空间创建后通过ALTER 命令实现。如果创建过程中指定了online_mode参数为true表名创建的表空间是在线状态, 此时表空间可提供任何服务。 相反如果参数指定为false, 那么创建的表空间将不能提供任何的读写服务。如果不设置, 默认为在线状态。 备注: 表空间只读或者离线状态设置前,请先关闭参数skip_tablespace_check(仅超级用户有修改和查看权限,默认是开启的),该参数开启状态下不会检查当前操作是否满足表空间状态。

示例

在文件系统位置/data/dbs创建一个表空间dbspace, 首先使用操作系统工具创建目录并设置正确的所有权:

mkdir /data/dbs
chown kingbase:kingbase /data/dbs

然后在KingbaseES内部发出表空间创建命令:

CREATE TABLESPACE dbspace LOCATION '/data/dbs';

创建由不同数据库用户拥有的表空间,使用如下命令:

CREATE TABLESPACE indexspace OWNER genevieve LOCATION '/data/indexes';

创建加密表空间,使用如下命令:

CREATE TABLESPACE encrypt_tsp OWNER genevieve LOCATION '/data/encrypt_tsp'
with (encryption = true, enckey = '123456');

创建表空间指定ONLINE/OFFLINE 模式, 可以使用参数进行设置:

CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' WITH (ONLINE_MODE=TRUE);

也可以通过Oracle 的兼容命令设置:

CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' ONLINE;

如果两者同时设置但值不同,以oracle 语法设置的模式的值为准, 如:

CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' OFFLINE WITH (ONLINE_MODE=TRUE);

此时表空间模式最终为离线。

兼容性

CREATE TABLESPACE是一种 KingbaseES扩展。

16.9. CREATE TEXT SEARCH CONFIGURATION

用途

CREATE TEXT SEARCH CONFIGURATION 创建一个新的文本搜索配置。一个文本搜索配置指定一个文本搜索解析器( 它能把字符串解析成记号),外加一些词典(可被用来决定哪些记号是搜索 感兴趣的)。

如果只指定了解析器,那么新文本搜索配置最初没有从记号类型到词典的映射, 并且因此将忽略所有词。后续的ALTER TEXT SEARCH CONFIGURATION命令必须被用来创建映射以让该配置变得可用。 另一种方式是复制一个现有的文本搜索配置。

如果给定一个模式名称,则文本搜索配置会被创建在指定的模式中。否则它将会 被创建在当前模式中。

定义一个文本搜索配置的用户会成为其拥有者。

进一步的信息请参考 全文搜索 。

前置条件

语法

CREATE TEXT SEARCH CONFIGURATION name (PARSER = parser_name |COPY = source_config
)

语义

name

要创建的文本搜索配置的名称。该名称可以被模式限定。

parser_name

这个配置要使用的文本搜索解析器的名称。

source_config

要复制的已有文本搜索配置的名称。

PARSERCOPY选项是互斥的,因为当 一个已有的配置被复制时,它的解析器选择也会被复制。

示例

CREATE TEXT SEARCH CONFIGURATION zhparsercfg (PARSER = zhparser);

兼容性

在 SQL 标准中没有 CREATE TEXT SEARCH CONFIGURATION语句。

16.10. CREATE TEXT SEARCH DICTIONARY

用途

CREATE TEXT SEARCH DICTIONARY创建一个 新的文本搜索字典。一个文本搜索字典指定一种识别搜索感兴趣或者不感兴趣 的单词的方法。 一个字典依赖于一个文本搜索模板,后者指定了实际执行该工 作的函数。通常该字典提供一些控制该模板函数细节行为的选项。

如果给出了一个模式名称,那么该文本搜索字典会被创建在指定的模式中。 否则它会被创建在当前模式中。

定义文本搜索字典的用户将成为其拥有者。

前置条件

语法

CREATE TEXT SEARCH DICTIONARY name (TEMPLATE = template[, option = value [, ... ]]
)

语义

name

要创建的文本搜索字典的名称。该名称可以是模式限定的。

template

将定义这个字典基本行为的文本搜索模板的名称。

option

要为此字典设置的模板相关选项的名称。

value

用于模板相关选项的值。如果该值不是一个简单标识符或者数字,它必须 被加引用(你可以按照你所希望的总是对它加上引用)。

选项可以以任意顺序出现。

示例

下面的例子命令创建了一个基于 Snowball 的字典,它使用了非标准的 停用词列表。

CREATE TEXT SEARCH DICTIONARY my_russian (template = snowball,language = russian,stopwords = myrussian
);

兼容性

在 SQL 标准中没有 CREATE TEXT SEARCH DICTIONARY语句。

16.11. CREATE TEXT SEARCH PARSER

用途

CREATE TEXT SEARCH PARSER创建一个 新的文本搜索解析器。一个文本搜索解析器定义把文本字符串分解成记号 并且为记号分配类型(分类)的方法。一个解析器本身并不特别有用,但 是必须与一些要用于搜索的文本搜索字典一起被绑定到一个文本搜索配置 中。

如果给出了一个模式名称,那么文本搜索解析器将被创建在指定的模式中。 否则它会被创建在当前模式中。

更多信息可以参考 全文搜索 。

前置条件

只有超级用户才能使用 CREATE TEXT SEARCH PARSER(这是因为 错误的文本搜索定义可能会让服务器混淆甚至崩溃)。

语法

CREATE TEXT SEARCH PARSER name (START = start_function ,GETTOKEN = gettoken_function ,END = end_function ,LEXTYPES = lextypes_function[, HEADLINE = headline_function ]
)

语义

name

要创建的文本搜索解析器的名称。该名称可以是模式限定的。

start_function

用于该解析器的开始函数的名称。

gettoken_function

用于该解析器的取下一个记号的函数名称。

end_function

用于该解析器的结束函数的名称。

lextypes_function

用于该解析器的词法分析器函数(一个返回其产生的记号类型集合信息的函数)的名称。

headline_function

用于该解析器的标题函数(一个对记号集合进行综述的函数)的名称。

如有必要,函数的名称可以被模式限定。参数类型没有给出, 因为函数的每个类型的参数列表无法被预先决定。除了标题函数之外, 所有函数都是必要的。

参数可以以任何顺序出现,而不是必须按照上面所展示的顺序。

示例

CREATE TEXT SEARCH PARSER jieba (START    = jieba_start,GETTOKEN = jieba_gettoken,END      = jieba_end,LEXTYPES = jieba_lextype,HEADLINE = pg_catalog.prsd_headline);

兼容性

在 SQL 标准中没有 CREATE TEXT SEARCH PARSER语句。

16.12. CREATE TEXT SEARCH TEMPLATE

用途

CREATE TEXT SEARCH TEMPLATE创建一个 新的文本搜索模板。文本搜索模板定义实现文本搜索字典的函数。一个模板 本身没什么用处,但是必须被实例化为一个字典来使用。字典通常指定要给 予模板函数的参数。

如果给出了一个模式名,文本搜索模板会被创建在指定模式中。否则它会被 创建在当前模式中。

进一步的信息可以参考 全文搜索

前置条件

必须成为超级用户以使用 CREATE TEXT SEARCH TEMPLATE。做出 这种限制是因为错误的模板定义会让服务器混淆甚至崩溃。将模板与字典 分隔开来的原因是模板中封装了定义字典的“不安全”方面。在 定义字典时可以被设置的参数对非特权用户是可以安全设置的,因此创建 字典不需要拥有特权来操作。

语法

CREATE TEXT SEARCH TEMPLATE name ([ INIT = init_function , ]LEXIZE = lexize_function
)

语义

name

要创建的额文本搜索模板的名称。该名称可以被模式限定。

init_function

用于模板的初始化函数的名称。

lexize_function

用于模板的分词函数的名称。

如有必要,函数名称可以被模式限定。参数类型没有给出,因为每一类 函数的参数列表是预先定义好的。分词函数是必需的,但是初始化函数 是可选的。

参数可以以任何顺序出现,而不是只能按照上文的顺序。

示例

CREATE TEXT SEARCH TEMPLATE intdict_template (LEXIZE = dintdict_lexize,INIT   = dintdict_init);

兼容性

在 SQL 标准中没有 CREATE TEXT SEARCH TEMPLATE语句。

16.13. CREATE TRANSFORM

用途

CREATE TRANSFORM定义一种新的转换。 CREATE OR REPLACE TRANSFORM将 创建一种新的转换或者替换现有的定义。

一种转换指定了如何把一种数据类型适配到一种过程语言。例如,在用 PL/Python 编写一个使用hstore类型的函数时,PL/Python 没有关于如何在 Python 环境中表示hstore值的先验知识。 语言的实现通常默认会使用文本表示,但是在一些时候这很不方便,例如 有时可能用一个联合数组或者列表更合适。

一种转换指定了两个函数:

  • 一个“from SQL”函数负责将类型从 SQL 环境转换到语言。 这个函数将在该语言编写的一个函数的参数上调用。

  • 一个“to SQL”函数负责将类型从语言转换到 SQL 环境。这个函数将在该语言编写的一个函数的返回值上调用。

没有必要同时提供这些函数。如果有一种没有被指定,将在必要时使用与语言相 关的默认行为(为了完全阻止在一个方向上发生转换,你也可以写一个总是报错 的转换函数)。

前置条件

要创建一种转换,你必须拥有该类型并且具有该类型上的 USAGE特权,拥有该语言上的 USAGE特权,并且拥有 from-SQL 和 to-SQL 函数(如果 指定了)及其上的EXECUTE特权。

语法

CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name (FROM SQL WITH FUNCTION from_sql_function_name [ (argument_type [, ...]) ],TO SQL WITH FUNCTION to_sql_function_name [ (argument_type [, ...]) ]
);

语义

type_name

该转换的数据类型的名称。

lang_name

该转换的语言的名称。

from_sql_function_name[(argument_type [, ...])]

将该类型从 SQL 环境转换到该语言的函数名。它必须接受一个 internal类型的参数并且返回类型internal。 实参将是该转换所适用的类型,并且该函数也应该被写成认为它是那种类型( 但是不允许声明一个返回internal但没有至少一个 internal类型参数的 SQL 层函数)。实际的返回值将与 语言的实现相关。如果没有指定参数列表,则函数名在该模式中必须唯一。

to_sql_function_name[(argument_type [, ...])]

将该类型从语言转换到 SQL 环境的函数名。它必须接受一个 internal类型的参数并且返回该转换所适用的类型。实参值 将与语言的实现相关。如果没有指定参数列表,则函数名在该模式中必须唯一。

示例

要为类型hstore和语言 plpythonu创建一种转换,先搞定该类型和语言:

CREATE TYPE hstore ...;CREATE LANGUAGE plpythonu ...;

然后创建需要的函数:

CREATE FUNCTION hstore_to_plpython(val internal) RETURNS internal
LANGUAGE C STRICT IMMUTABLE
AS ...;CREATE FUNCTION plpython_to_hstore(val internal) RETURNS hstore
LANGUAGE C STRICT IMMUTABLE
AS ...;

最后创建转换把它们连接起来:

CREATE TRANSFORM FOR hstore LANGUAGE plpythonu (FROM SQL WITH FUNCTION hstore_to_plpython(internal),TO SQL WITH FUNCTION plpython_to_hstore(internal)
);

实际上,这些命令将被包裹在扩展中。

contrib小节包含了一些提供转换的扩展, 它们可以作为实际的例子。 要为类型hstore和语言 plpythonu创建一种转换,先搞定该类型和语言:

CREATE TYPE hstore ...;CREATE LANGUAGE plpythonu ...;

然后创建需要的函数:

CREATE FUNCTION hstore_to_plpython(val internal) RETURNS internal
LANGUAGE C STRICT IMMUTABLE
AS ...;CREATE FUNCTION plpython_to_hstore(val internal) RETURNS hstore
LANGUAGE C STRICT IMMUTABLE
AS ...;

最后创建转换把它们连接起来:

CREATE TRANSFORM FOR hstore LANGUAGE plpythonu (FROM SQL WITH FUNCTION hstore_to_plpython(internal),TO SQL WITH FUNCTION plpython_to_hstore(internal)
);

实际上,这些命令将被包裹在扩展中。

contrib小节包含了一些提供转换的扩展, 它们可以作为实际的例子。

兼容性

这种形式的CREATE TRANSFORM是一种 KingbaseES扩展。在 SQL标准中有一个CREATE TRANSFORM命令,但是它是用于把数据类型适配到 客户端语言。该用法不受 KingbaseES支持。

16.14. CREATE TRIGGER

用途

CREATE TRIGGER创建一个新触发器。该触发器将被关联到指定的表、视图或者外部表并且在表上发生特定操作时将执行指定的函数``function_name``

该触发器可以被指定为在一行上尝试该操作之前触发(在约束被检查并且INSERTUPDATE或者DELETE被尝试之前);也可以在该操作完成之后触发(在约束被检查并且INSERTUPDATE或者DELETE完成之后);或者取代该操作(在对一个视图插入、更新或删除的情况中)。如果该触发器在事件之前触发或者取代事件,该触发器可以跳过对当前行的操作或者改变正在被插入的行(只对INSERT以及UPDATE操作)。如果该触发器在事件之后触发,所有更改(包括其他触发器的效果)对该触发器“可见”。

一个被标记为FOR EACH ROW的触发器会对该操作修改的每一行都调用一次。例如,一个影响 10 行的DELETE将导致在目标关系上的任何ON DELETE触发器被独立调用 10 次,也就是为每一个被删除的行调用一次。与此相反,一个被标记为FOR EACH STATEMENT的触发器只会为任何给定的操作执行一次,不管该操作修改多少行(特别地,一个修改零行的操作将仍会导致任何可用的FOR EACH STATEMENT触发器被执行)。

被指定为要触发INSTEAD OF触发器事件的触发器必须被标记为FOR EACH ROW,并且只能被定义在视图上。一个视图上的BEFOREAFTER触发器必须被标记为FOR EACH STATEMENT

此外,触发器可以被定义成为TRUNCATE触发,但只能是FOR EACH STATEMENT

下面的表格总结了哪些触发器类型可以被用在表、视图和外部表上:

何时

事件

行级

语句级

BEFORE

INSERT/UPDATE/DELETE

表和外部表

表、视图和外部表

TRUNCATE

AFTER

INSERT/UPDATE/DELETE

表和外部表

表、视图和外部表

TRUNCATE

INSTEAD OF

INSERT/UPDATE/DELETE

视图

TRUNCATE

还有,一个触发器定义可以指定一个布尔的WHEN条件,它将被测试来看看该触发器是否应该被触发。在行级触发器中,WHEN条件可以检查该行的列的新旧值。语句级触发器也可以有WHEN条件,尽管该特性对于它们不是很有用(因为条件不能引用表中的任何值)。

如果有多个同种触发器被定义为相同事件触发,它们将按照名称的字母表顺序被触发。

CONSTRAINT选项被指定,这个命令会创建一个约束触发器。这和一个常规触发器相同,不过触发该触发器的时机可以使用 SET CONSTRAINTS 调整。约束触发器必须是表上的AFTER ROW触发器。它们可以在导致触发器事件的语句末尾被引发或者在包含该语句的事务末尾被引发。在后一种情况中,它们被称作是被延迟。一个待处理的延迟触发器的引发也可以使用SET CONSTRAINTS立即强制发生。当约束触发器实现的约束被违背时,约束触发器应该抛出一个异常。

REFERENCING选项启用对传递关系的收集,传递关系是包括被当前SQL语句插入、删除或者修改的行的行集合。这个特性让触发器能看到该语句做的事情的全局视图,而不是一次只看到一行。仅对非约束触发器的AFTER触发器允许这个选项。此外,如果触发器是一个UPDATE触发器,则它不能指定``column_name``列表。OLD TABLE仅可以被指定一次,并且只能为在UPDATEDELETE事件上引发的触发器指定,它创建的传递关系包含有该语句更新或删除的所有行的前映像。类似地,NEW TABLE仅可以被指定一次,并且只能为在UPDATEINSERT事件上引发的触发器指定,它创建的传递关系包含有该语句更新或插入的所有行的后映像

SELECT不修改任何行,因此你无法创建SELECT触发器。规则和视图可以为需要SELECT触发器的问题提供可行的解决方案。

触发事件可以是多个数据操作的组合,即一个触发器可能既是INSERT触发器,又是 DELETE 或 UPDATE 触发器。当一个触发器可以为多个DML 语句触发时,在这种触发器体内部可以使用三个谓词: INSERTING、DELETING 和 UPDATING 来确定当前执行的是何种操作。

谓词

状态

INSERTING

当触发语句为 INSERT 时为真,否则为假

DELETING

当触发语句为 DELETE 时为真,否则为假

UPDATING[(< 列名 >)]

未指定列名时, 当触发语句为 UPDATE 时为真,否则为 假;指定某一列名时,当触发语句为对该列的 UPDATE 时为真,否则为假。

关于触发器的更多信息请见 触发器 。

前置条件

要在一个表上创建一个触发器,用户必须具有该表上的TRIGGER特权。用户还必须具有在触发器函数上的EXECUTE特权。

语法

CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ] TRIGGER name { BEFORE | AFTER | INSTEAD OF }
{ event [ OR ... ] }ON table_name[ FROM referenced_table_name ][ REFERENCING { { OLD | NEW } [TABLE] [ AS ] { transition_relation_name |  referenced_variable_name }[ ... ] ][ FOR [ EACH ] { ROW | STATEMENT } ][ WHEN ( condition ) ]{ EXECUTE PROCEDURE function_name ( arguments )| [AS | IS] <PlsqlBlock>| CALL function_name ( arguments ) }<PlsqlBlock>:
[{ DECLARE[ variable_declaration ][ cursor_declaration ][<NestfunctionDeclaration>] }]BEGINsequence_of_statementEND [ label_name ]
CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }ON table_name[ FROM referenced_table_name ][ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED] ][ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name }[ ... ] ][ FOR [ EACH ] { ROW | STATEMENT } ][ WHEN ( condition ) ]EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )这里的event可以是下列之一:INSERTUPDATE [ OF column_name [, ... ] ]DELETETRUNCATE

语义

name

给新触发器的名称。这必须与同一个表上的任何其他触发器相区别。名称不能是模式限定的 — 该触发器会继承它所在表的模式。对于一个约束触发器,这也是使用SET CONSTRAINTS修改触发器行为时要用到的名字。

BEFORE AFTER INSTEAD OF

决定该函数是要在事件之前、之后被调用还是会取代该事件。一个约束触发器也能被指定为AFTER

event

INSERTUPDATEDELETE或者TRUNCATE之一,这指定了将要引发该触发器的事件。多个事件可以用OR指定,要求传递关系的时候除外。

对于UPDATE事件,可以使用下面的语法指定一个列的列表:

UPDATE OF column_name1 [, column_name2 ... ]

只有当至少一个被列出的列出现在UPDATE命令的更新目标中时, 该触发器才会触发;或者,列出的列之一是生成的列,该列依赖于UPDATE的目标列。

INSTEAD OF UPDATE事件不允许列的列表。在请求传递关系时,也不能指定列的列表。

table_name

要使用该触发器的表、视图或外部表的名称(可能是模式限定的)。

referenced_table_name

约束引用的另一个表的名称(可能是模式限定的)。这个选项被用于外键约束并且不推荐用于一般的目的。这只能为约束触发器指定。

DEFERRABLE NOT DEFERRABLE INITIALLY IMMEDIATE INITIALLY DEFERRED

该触发器的默认时机。这些约束选项的细节可参考 CREATE TABLE 文档。这只能为约束触发器指定。

REFERENCING

这个关键词紧接在一个或者两个关系名的声明之前,这些关系提供对触发语句的传递关系的访问。

OLD TABLE NEW TABLE

这个子句指示接下来的关系名是用于前映像传递关系还是后映像传递关系。

transition_relation_name

在该触发器中这个传递关系要使用的(未限定)名称。

referenced_variable_name

为触发表上受影响的当前行取别名。可以为new行和old行取别名。

FOR EACH ROW FOR EACH STATEMENT

这指定该触发器函数是应该为该触发器事件影响的每一行被引发一次,还是只为每个 SQL 语句被引发一次。如果都没有被指定,FOR EACH STATEMENT会是默认值。约束触发器只能被指定为FOR EACH ROW

condition

一个决定该触发器函数是否将被实际执行的布尔表达式。如果指定了WHEN,只有``condition``返回true时才会调用该函数。在FOR EACH ROW触发器中,WHEN条件可以分别写OLD.column_name或者NEW.column_name来引用列的新旧行值。当然,INSERT触发器不能引用OLD并且DELETE触发器不能引用NEW

INSTEAD OF触发器不支持WHEN条件。

当前,WHEN表达式不能包含子查询。

注意对于约束触发器,对于WHEN条件的计算不会被延迟,而是直接在行更新操作被执行之后立刻发生。如果该条件计算得不到真,那么该触发器就不会被放在延迟执行的队列中。

function_name

一个用户提供的函数,它被声明为不用参数并且返回类型trigger,当触发器引发时会执行该函数。

一个用户提供的无参数存储过程。

CREATE TRIGGER的语法中,关键词FUNCTIONPROCEDURE是等效的,这里,关键词PROCEDURE的使用是有历史原因的并且已经被废弃。

arguments

一个可选的逗号分隔的参数列表,它在该触发器被执行时会被提供给该函数。参数是字符串常量。简单的名称和数字常量也可以被写在这里,但是它们将全部被转换成字符串。请检查该触发器函数的实现语言的描述来找出在函数内部如何访问这些参数,这可能与普通函数参数不同。

EDITIONABLE NONEDITIONABLE

未设计功能,只为语法兼容。

PlsqlBlock

请参考 存储过程模块

示例

例1:只要表accounts的一行即将要被更新时会执行函数check_account_update

CREATE TRIGGER check_updateBEFORE UPDATE ON accountsFOR EACH ROWEXECUTE FUNCTION check_account_update();

例2:下面的例子与上面一个例子相同,但是只在UPDATE命令指定要更新balance列时才执行该函数:

CREATE TRIGGER check_updateBEFORE UPDATE OF balance ON accountsFOR EACH ROWEXECUTE FUNCTION check_account_update();

例3:这种形式只有列balance具有真正被改变的值时才执行该函数:

CREATE TRIGGER check_updateBEFORE UPDATE ON accountsFOR EACH ROWWHEN (OLD.balance IS DISTINCT FROM NEW.balance)EXECUTE FUNCTION check_account_update();

例4:调用一个函数来记录accounts的更新,但是只在有东西被改变时才调用:

CREATE TRIGGER log_updateAFTER UPDATE ON accountsFOR EACH ROWWHEN (OLD.* IS DISTINCT FROM NEW.*)EXECUTE FUNCTION log_account_update();

例5:为每一个要插入到视图底层表中的行执行函数view_insert_row

CREATE TRIGGER view_insertINSTEAD OF INSERT ON my_viewFOR EACH ROWEXECUTE FUNCTION view_insert_row();

例6:为每个语句执行函数check_transfer_balances_to_zero以确认transfer的行不会有净值增加:

CREATE TRIGGER transfer_insertAFTER INSERT ON transferREFERENCING NEW TABLE AS insertedFOR EACH STATEMENTEXECUTE FUNCTION check_transfer_balances_to_zero();

例7:为每一行执行函数check_matching_pairs以确认(同一个语句)同时对匹配对做了更改:

CREATE TRIGGER paired_items_updateAFTER UPDATE ON paired_itemsREFERENCING NEW TABLE AS newtab OLD TABLE AS oldtabFOR EACH ROWEXECUTE FUNCTION check_matching_pairs();

例8:为每一个要插入到视图底层表中的行执行PLSQL BLOCK:

\set SQLTERM /CREATE TRIGGER view_insertINSTEAD OF INSERT ON my_viewFOR EACH ROWASBEGINRAISE NOTICE 'execute view_insert pl_block';END;
/

例9:为每一个要插入到视图底层表中的行执行PLSQL BLOCK:

\set SQLTERM /CREATE TRIGGER view_insertINSTEAD OF INSERT ON my_viewFOR EACH ROWASBEGINRAISE NOTICE 'execute view_insert pl_block';END;
/

例10:创建一个无参数存储过程后,再创建触发器调用该存储过程

\set SQLTERM /
CREATE TABLE test_trg_table(id int);
/
CREATE OR REPLACE PROCEDURE PRO1 ASBEGINRAISE NOTICE 'execute pro1';END;
/CREATE OR REPLACE TRIGGER test_trgBEFORE INSERT ON test_trg_tableFOR EACH ROWCALL PRO1()
/
INSERT INTO test_trg values(1);
/

例11:为当前触发器影响行取别名

\set SQLTERM ;
drop table if exists t1;
create table t1(id int);
insert into t1 values(10);
\set SQLTERM /
CREATE or replace TRIGGER tg_test_10 beforeupdateOn t1 referencing NEWas new_alias old as "old_alias" for each rowwhen (new_alias.id = 20 and "old_alias".id = 10)
declarea int;
beginraise notice '%',  :new_alias.id;raise notice '%', :old_alias.id;:new_alias.id := 100;
end;
/
\set SQLTERM ;
update t1 set id = 20 where id = 10;
select * from t1;
drop table t1;

兼容性

该部分不是必有的,如有对SQL标准的扩展等兼容性产生影响在这里描述。

其他

当一个列相关的触发器(使用UPDATE OF column_name语法定义的触发器)的列被列为UPDATE命令的SET列表目标时,它会被触发。即便该触发器没有被引发,一个列的值也可能改变,因为BEFORE UPDATE触发器对行内容所作的改变不会被考虑。相反,一个诸如UPDATE ... SET x = x ...的命令将引发一个位于列x上的触发器,即便该列的值没有改变。

在一个BEFORE触发器中,WHEN条件正好在函数被 或者将被执行之前被计算,因此使用WHEN与在触发器函数的开始测试同 一个条件没有实质上的区别。特别注意该条件看到的NEW行是当前值, 虽然可能已被早前的触发器所修改。还有,一个BEFORE触发器 的WHEN条件不允许检查NEW行的系统列 (例如ctid),因为那些列还没有被设置。

在一个AFTER触发器中,WHEN条件正好在行更新发生之后被计算,并且它决定一个事件是否要被放入队列以便在语句的末尾引发该触发器。因此当一个AFTER触发器的WHEN条件不返回真时,没有必要把一个事件放入队列或者在语句末尾重新取得该行。如果触发器只需要为一些行被引发,就能够显著地加快修改很多行的语句的速度。

在一些情况下,单一的SQL命令可能会引发多种触发器。例如,一个带有ON CONFLICT DO UPDATE子句的INSERT可能同时导致插入和更新操作,因此它将根据需要引发这两种触发器。提供给触发器的传递关系与它们的事件类型有关,因此INSERT触发器将只看到被插入的行,而UPDATE触发器将只看到被更新的行。

由外键强制动作导致的行更新或删除(例如ON UPDATE CASCADEON DELETE SET NULL)被当做导致它们的SQL命令的一部分。受影响的表上的相关触发器将被引发,这样就提供了另一种方法让SQL命令引发不直接匹配其类型的触发器。在简单的情况中,请求传递关系的触发器将在一个传递关系中看到由原始SQL命令在其表中做出的所有改变。不过,有些情况中一个请求传递关系的AFTER ROW触发器的存在将导致由单个SQL命令触发的外键强制动作被分成多步,每一步都有其自己的传递关系。在这种情况下,没创建一个传递关系集合都会引发存在的所有语句级触发器,确保那些触发器能够在一个传递关系中看到每个受影响的行一次,并且只看到一次。

只有当视图上的动作被一个行级INSTEAD OF触发器处理时才会引发视图上的语句级触发器。如果动作被一个INSTEAD规则处理,那么该语句发出的任何语句都会代替提及该视图的原始语句执行,这样将被引发的触发器是替换语句中提及的表上的那些触发器。类似地,如果视图是自动可更新的,则该动作将被处理为把该语句自动重写成在视图基表上的一个动作,这样基表的语句级触发器就是要被引发的。

在分区表上创建一个行级触发器将导致在它所有的现有分区上创建相同的触发器,并且以后创建或者挂接的任何分区也将包含一个相同的触发器。分区表上的触发器只能是AFTER

修改分区表或者带有继承子表的表会引发挂接到显式提及表的语句级触发器,但不会引发其分区或子表的语句级触发器。相反,行级触发器会在受影响的分区或子表上引发,即便它们在查询中没有被明确提及。如果一个语句级触发器用REFERENCING子句定义有传递关系,则来自所有受影响分区或子表中的行的前后映像都是可见的。在继承子表的情况中,行映像仅包括该触发器所附属的表中存在的列。当前,不能在分区或继承子表上定义带有传递关系的行级触发器。

在KingbaseES V7以前的版本中,必须要声明触发器函数为返回占位符类型opaque而不是trigger。要支持载入旧的转储文件,CREATE TRIGGER将接受一个被声明为返回opaque的函数,但是它会发出一个通知并且会把该函数的声明返回类型改为trigger

16.15. CREATE TYPE

用途

CREATE TYPE在当前数据库中注册一种新的 数据类型。定义数据类型的用户将成为它的拥有者。

如果给定一个模式名,那么该类型将被创建在指定的模式中。否则它会被 创建在当前模式中。类型名称必须与同一个模式中任何现有的类型或者域 相区别(因为表具有相关的数据类型,类型名称也必须与同一个模式中任 何现有表的名字不同)。

如上面的语法所示,有八种形式的CREATE TYPE。 它们分别创建组合类型枚举类型、 范围类型基础类型shell 类型嵌套表类型可变数组类型对象类型。下文将依次讨论这些形式。

  1. 组合类型

    第一种形式的CREATE TYPE创建组合类型。 组合类型由一个属性名和数据类型的列表指定。如果属性的数据类型是可 排序的,也可以指定该属性的排序规则。组合类型本质上和表的行类型相 同,但是如果只想定义一种类型,使用 CREATE TYPE避免了创建一个实际的表。单 独的组合类型也是很有用的,例如可以作为函数的参数或者返回类型。

    为了能够创建组合类型,必须拥有在其所有属性类型上的 USAGE特权。

  2. 枚举类型

    如 枚举类型 中所述,第二种形式的 CREATE TYPE创建枚举类型。枚举类型需要 一个带引号的标签构成的列表,每一个标签长度必须不超过 NAMEDATALEN字节(在标准的 KingbaseES编译中是 64 字节)。 可以创建具有零个标签的枚举类型,但是在使用 ALTER TYPE语句 添加至少一个标签之前,不能使用这种类型来保存值。

  3. 范围类型

    如 范围类型 中所述,第三种形式的 CREATE TYPE创建范围类型。

    范围类型的``subtype``可以 是任何带有一个相关的 B 树操作符类(用来决定该范围类型值的顺序)的类型。 通常,子类型的默认 B 树操作符类被用来决定顺序。要使用一种非默认操作符 类,可以用 ``subtype_opclass``指定它 的名字。如果子类型是可排序的并且希望在该范围的顺序中使用一种非默认的 排序规则,可以用``collation``选项来指定。

    可选的``canonical``函数 必须接受一个所定义的范围类型的参数,并且返回同样类型的一个值。在适 用时,它被用来把范围值转换成一种规范的形式。更多信息请见 定义新的范围类型 。创建一个 ``canonical``函数有点棘 手,因为必须在声明范围类型之前定义它。要这样做,必须首先创建一种 shell 类型,它是一种没有属性只有名称和拥有者的占位符类型。这可以通过 发出不带额外参数的命令CREATE TYPE name来完成。然后可以使用该 shell 类型作为 参数和结果来声明该函数,并且最终用同样的名称来声明范围类型。这会自动 用一种合法的范围类型替换 shell 类型项。

    可选的``subtype_diff``函数 必须接受两个``subtype``类型 的值作为参数,并且返回一个double precision值表示两个给定 值之间的差别。虽然这是可选的,但是提供这个函数会让该范围类型列上 GiST 索 引效率更高。详见 定义新的范围类型 。

  4. 基础类型

    第四种形式的CREATE TYPE创建一种新的 基本类型(标量类型)。为了创建一种新的基本类型,你必须是一个超级 用户(做这种限制的原因是一种错误的类型定义可能让服务器混淆甚至 崩溃)。

    参数可以以任意顺序出现(而不仅是按照上面所示的顺序),并且大部分 是可选的。在定义类型前,必须注册两个或者更多函数(使用 CREATE FUNCTION)。支持函数 ``input_function``以及 ``output_function`` 是必需的,而函数 ``receive_function``、 ``send_function``、 ``type_modifier_input_function``、 ``type_modifier_output_function``和 ``analyze_function`` 是可选的。通常来说这些函数必须是用 C 或者另外一种低层语言编写的。

    ``input_function``将 类型的外部文本表达转换成为该类型定义的操作符和函数所使用的内部 表达。 ``output_function`` 执行反向的转换。输入函数可以被声明为有一个cstring 类型的参数,或者有三个类型分别为cstring、 oidinteger的参数。第一个参数是 以 C 字符串存在的输入文本,第二个参数是该类型自身的 OID(对于 数组类型则是其元素类型的 OID),第三个参数是目标列的 typmod(如果知道,不知道则将传递 -1)。输入函数必须 返回一个该数据类型本身的值。通常,一个输入函数应该被声明为 STRICT。 如果不是这样,在读到一个 NULL 输入值时,调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误( 这种情况主要是想支持域输入函数,它们可能需要拒绝 NULL 输入)。 输出函数必须被声明为有一个新数据类型的参数。输出函数必须返回类型 cstring。对于 NULL 值不会调用输出函数。

    T可选的``receive_function`` 会把类型的外部二进制表达转换成内部表达。如果没有提供这个函数, 该类型不能参与到二进制输入中。二进制表达转换成内部形式代价更低, 然而却更容易移植(例如,标准的整数数据类型使用网络字节序作为外 部二进制表达,而内部表达是机器本地的字节序)。接收函数应该执行 足够的检查以确保该值是有效的。接收函数可以被声明为有一个 internal类型的参数,或者有三个类型分别为 internaloidinteger 的参数。第一个参数是一个指向StringInfo缓冲区的 指针,其中保存着接收到的字节串。其余可选的参数和文本输入函数的 相同。接收函数必须返回一个该数据类型本身的值。通常,一个接收函 数应该被声明为 STRICT。如果不是这样,在读到一个 NULL 输入值时, 调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误(这种情况主要是想支持域接收函数,它们 可能需要拒绝 NULL 输入)。类似地,可选的 ``send_function``将 内部表达转换成外部二进制表达。如果没有提供这个函数,该类型将不 能参与到二进制输出中。发送函数必须被声明为有一个新数据类型的参 数。发送函数必须返回类型bytea。对于 NULL 值不 会调用发送函数。

    到这里你应该在疑惑输入和输出函数是如何能被声明为具有新类型的 结果或参数的?因为必须在创建新类型之前创建这两个函数。这个问题 的答案是,新类型应该首先被定义为一种shell type, 它是一种占位符类型,除了名称和拥有者之外它没有其他属性。这可以 通过不带额外参数的命令CREATE TYPE name做到。然后用 C 写的 I/O 函数可以 被定义为引用这种 shell type。最后,用带有完整定义的 CREATE TYPE把该 shell type 替换为一个完全的、合 法的类型定义,之后新类型就可以正常使用了。

    如果该类型支持修饰符(附加在类型声明上的可选约束,例如 char(5)或者numeric(30,2)),则需要可选的 ``type_modifier_input_function`` 以及``type_modifier_output_function``。 KingbaseES允许用户定义的类型有一个或者 多个简单常量或者标识符作为修饰符。不过,为了存储在系统目录中,该信息必须 能被打包到一个非负整数值中。所声明的修饰符会被以cstring数组的形式 传递给 ``type_modifier_input_function``。 它必须检查该值的合法性(如果值错误就抛出一个错误),如果值正确,要返回 一个非负integer值,它将被存储在“typmod”列中。如果 类型没有 ``type_modifier_input_function`` 则类型修饰符将被拒绝。 ``type_modifier_output_function`` 把内部的整数 typmod 值转换回正确的形式用于用户显示。它必须返回一个 cstring值,该值就是追加到类型名称后的字符串。例如 numeric的函数可能会返回(30,2)。如果默认的显示格式 就是只把存储的 typmod 整数值放在圆括号内,则允许省略 ``type_modifier_output_function``

    可选的``analyze_function`` 为该数据类型的列执行与类型相关的统计信息收集。默认情况下,如果 该类型有一个默认的 B-树操作符类,ANALYZE将尝试用 类型的“equals”和“less-than”操作符来收集统计信息。 这种行为对于非标量类型并不合适,因此可以通过指定一个自定义分析函数来 覆盖这种行为。分析函数必须被声明为有一个类型为internal的参 数,并且返回一个boolean结果。分析函数的详细 API 请见 src/include/commands/vacuum.h

    虽然只有 I/O 函数和其他为该类型创建的函数才知道新类型的内部表达的细节, 但是内部表达的一些属性必须被向 KingbaseES声明。其中最重要的是 ``internallength``。基本数据 类型可以是定长的(这种情况下 ``internallength``是一个正 整数)或者是变长的(把 ``internallength``设置为 VARIABLE,在内部通过把typlen设置为 -1 表示)。 所有变长类型的内部表达都必须以一个 4 字节整数开始,它给出了这个值的总长度。

    可选的标志PASSEDBYVALUE表示这种数据类型的值需要 被传值而不是传引用。传值的类型必须是定长的,并且它们的内部表达不能超 过Datum类型(某些机器上是 4 字节,其他机器上是 8 字节)的 尺寸。

    ``alignment``参数指定数据 类型的存储对齐要求。允许的值等同于以 1、2、4 或 8 字节边界对齐。注意 变长类型的 alignment 参数必须至少为 4,因为它们需要包含一个 int4作为它们的第一个组成部分。

    ``storage``参数允许 为变长数据类型选择存储策略(对定长类型只允许 plain)。plain指定该类型的数 据将总是被存储在线内并且不会被压缩。extended 指定系统将首先尝试压缩一个长的数据值,并且将在数据仍然太长的情 况下把值移出主表行。external允许值被移出主表, 但是系统将不会尝试对它进行压缩。main允许压缩, 但是不鼓励把值移出主表(如果没有其他办法让行的大小变得合适,具有 这种存储策略的数据项仍将被移出主表,但比起 extended以及external项来, 这种存储策略的数据项会被优先考虑保留在主表中)。

    如 用户定义的类型 TOAST 所述,除plain之外所有的 ``storage``值都暗示该数据类型的函数能处理被TOAST 过的值。指定的值 仅仅是决定一种可 TOAST 数据类型的列的默认 TOAST 存储策略,用户 可以使用ALTER TABLE SET STORAGE为列选取其他策略。

    ``like_type``参数提供 了另一种方法来指定一种数据类型的基本表达属性:从某种现有的类型中 拷贝。``internallength``、 ``passedbyvalue``、 ``alignment``和 ``storage``的值会从指 定的类型中复制而来(也可以通过在LIKE子句中指定这些属 性的值来覆盖复制过来的值,不过通常并不这么做)。当新类型的低层 实现是以一种现有的类型为“载体”时,用这种方式指定表达特别有用。

    ``category``和 ``preferred``参数可以被用来 帮助控制在混淆的情况下应用哪一种隐式造型。每一种数据类型都属于一个用 单个 ASCII 字符命名的分类,并且每一种类型可以是其所属分类中的 “首选”。当有助于解决重载函数或操作符时,解析器将优先 造型到首选类型(但是只能从同类的其他类型造型)。更多细节请见 类型转换 。 对于没有隐式造型到任意其他类型或者 从任意其他类型造型的类型,让这些设置保持默认即可。不过,对于一组 具有隐式造型的相关类型,把它们都标记为属于同一个类别并且选择一种 或两种“最常用”的类型作为该类别的首选通常是很有用的。在 把一种用户定义的类型增加到一个现有的内建类别(例如数字或者字符串 类型)中时, ``category``参数特别 有用。不过,也可以创建新的全部是用户定义类型的类别。对这样的类别, 可选择除大写字母之外的任何 ASCII 字符。

    如果用户希望该数据类型的列被默认为某种非空值,可以指定一个默认值。 默认值可以用DEFAULT关键词指定(这样一个默认值 可以被附加到一个特定列的显式DEFAULT子句覆盖)。

    要指定一种类型是数组,用ELEMENT关键词指定该数组元素 的类型。例如,要定义一个 4 字节整数的数组(int4), 应指定ELEMENT = int4。更多有关数组类型的细节请 见下文。

    要指定在这种类型数组的外部表达中分隔值的定界符,可以把``delimiter``设置为一个特定字符。默认 的定界符是逗号(,)。注意定界符是与数组元素类型相 关的,而不是数组类型本身相关。

    如果可选的布尔参数 ``collatable``为真,这种 类型的列定义和表达式可能通过使用COLLATE子句携带 有排序规则信息。在该类型上操作的函数的实现负责真正利用这些信息,仅 把类型标记为可排序的并不会让它们自动地去使用这类信息。

  5. shell类型

    shell 类型仅仅是一种用于后面要定义的类型的占位符,通过发出一个不带除类型名 之外其他参数的CREATE TYPE命令可以创建这种类型。在创建范围类型和基础类型时, 需要 shell 类型作为一种向前引用。

  6. 嵌套表类型

    如 集合类型 中所述,第六种形式的CREATE TYPE用于创建嵌套表类型。 其中datatype支持基本数据类型、用户自定义数据数据类型和集合类型。 NOT NULL 指定嵌套表内元素的值不能为空。

  7. 可变数组类型

    如 集合类型 中所述,第七种形式的CREATE TYPE用于创建可变数组类型。 其中datatype支持基本数据类型、用户自定义数据数据类型和集合类型。 size_limit指定元素个数的最大限制值。NOT NULL 指定可变数组内元素得值不能为空。

  8. 对象类型

    如 对象类型 中所述,第八种形式的 CREATE TYPE 用于创建一个对象类型。

    对象类型在使用上与组合类型基本一致。不同于组合类型,对象类型在创建时可以 创建类型声明和类型体( CREATE TYPE BODY语句 ), 在创建对象类型声明时除了指定与组合类型相同的属性(列)外, 还可以声明静态函数(存储过程)、成员函数(存储过程)、构造函数三种内部方法。 并在相应的类型体内分别为声明的内部方法创建完整的方法定义。

    对象类型在创建时总会创建一个默认的构造函数,默认构造函数的参数列表与对象 类型的列成员一致,默认构造函数会将作为参数传入的列成员构造成对应的对象返回, 当默认构造函数与用户自定义构造函数参数相同时,将优先调用用户自定义的构造函数。

前置条件

为了能够创建组合类型,必须拥有在其所有属性类型上的USAGE特权。创建范围类型,必须在声明范围之前进行定义。要创建一种新的数据类型,你必须是一个超级用户。

语法

CREATE TYPE name AS( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] )CREATE TYPE name AS ENUM( [ 'label' [, ... ] ] )CREATE TYPE name AS RANGE (SUBTYPE = subtype[ , SUBTYPE_OPCLASS = subtype_operator_class ][ , COLLATION = collation ][ , CANONICAL = canonical_function ][ , SUBTYPE_DIFF = subtype_diff_function ]
)CREATE TYPE name (INPUT = input_function,OUTPUT = output_function[ , RECEIVE = receive_function ][ , SEND = send_function ][ , TYPMOD_IN = type_modifier_input_function ][ , TYPMOD_OUT = type_modifier_output_function ][ , ANALYZE = analyze_function ][ , INTERNALLENGTH = { internallength | VARIABLE } ][ , PASSEDBYVALUE ][ , ALIGNMENT = alignment ][ , STORAGE = storage ][ , LIKE = like_type ][ , CATEGORY = category ][ , PREFERRED = preferred ][ , DEFAULT = default ][ , ELEMENT = element ][ , DELIMITER = delimiter ][ , COLLATABLE = collatable ]
)CREATE TYPE nameCREATE TYPE name AS TABLE OF datatype [NOT NULL]CREATE TYPE name AS VARRAY(size_limit) OF datatype [NOT NULL]CREATE [ OR REPLACE ] TYPE name [ FORCE ] [ AUTHID { CURRENT_USER | DEFINER } ]
{ AS | IS } OBJECT (attribute_name data_type [, ... ][, subprogram_spec [, ... ] ][, constructor_spec [, ... ] ]
)
这里 subprogram_spec 是以下之一:{ STATIC | MEMBER } FUNCTION function_name[ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ]{ RETURNS | RETURN } rettype ]{ STATIC | MEMBER } PROCEDURE procedure_name[ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ]constructor_spec 是:CONSTRUCTOR FUNCTION name[ ( [ SELF IN OUT name ] [, argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ]{ RETURNS | RETURN } SELF AS RESULT

语义

name

要创建的类型的名称(可以被模式限定)。

attribute_name

组合类型的一个属性(列)的名称。

data_type

要成为组合类型的一个列的现有数据类型的名称。

collation

要关联到组合类型的一列或者范围类型的现有排序规则的名称。

label

一个字符串,它表达与枚举类型的一个值相关的文本标签。

subtype

范围类型的元素类型的名称,范围类型表示的范围属于该类型。

subtype_operator_class

用于 subtype 的 B 树操作符类的名称。

canonical_function

范围类型的规范化函数的名称。

subtype_diff_function

用于 subtype 的差函数的名称。

input_function

将数据从类型的外部文本形式转换为内部形式的函数名。

output_function

将数据从类型的内部形式转换为外部文本形式的函数名。

receive_function

将数据从类型的外部二进制形式转换成内部形式的函数名。

send_function

将数据从类型的内部形式转换为外部二进制形式的函数名。

type_modifier_input_function

将类型的修饰符数组转换为内部形式的函数名。

type_modifier_output_function

将类型的修饰符的内部形式转换为外部文本形式的函数名。

analyze_function

为该数据类型执行统计分析的函数名。

internallength

一个数字常量,它指定新类型的内部表达的字节长度。默认的假设是 它是变长的。

alignment

该数据类型的存储对齐需求。如果被指定,它必须是 charint2、 int4或者double。默认是 int4

storage

该数据类型的存储策略。如果被指定,必须是 plainexternal、 extended或者main。 默认是plain

like_type

与新类型具有相同表达的现有数据类型的名称。会从这个类型中复制 ``internallength``、 ``passedbyvalue``、 ``alignment``以及 ``storage``的值( 除非在这个CREATE TYPE命令的其他地方用显式说 明覆盖)。

category

这种类型的分类码(一个 ASCII 字符)。 默认是 “用户定义类型”的'U'。为了创建自定义分类, 你也可以选择其他 ASCII 字符。

preferred

如果这种类型是其类型分类中的优先类型则为真,否则为假。默认 为假。在一个现有类型分类中创建一种新的优先类型要非常小心, 因为这可能会导致行为上令人惊奇的改变。

default

数据类型的默认值。如果被省略,默认值是空。

element

被创建的类型是一个数组,这指定了数组元素的类型。

delimiter

在由这种类型组成的数组中值之间的定界符。

collatable

如果这个类型的操作可以使用排序规则信息,则为真。默认为假。

FORCE

FORCE作为一个与OR REPLACE配合使用的选项参数, 当使用CREATE TYPE语句创建一个对象类型替换一个已有类型时, FORCE选项可以决定如何处理被替换类型的依赖关系。

含有FORCE选项的替换创建语句(CREATE OR REPLACE TYPE) 会级联删除所有对原类型有依赖的对象,并成功创建新的对象类型。不含 有FORCE选项的替换创建语句则会在检测到原有类型处于被依赖 状态时进行提示并阻止新类型成功创建。

只有对象类型的创建语句支持FORCE选项,由于FORCE选 项会级联删除所有依赖对象,请谨慎使用。

AUTHID { CURRENT_USER | DEFINER }

AUTHID CURRENT_USER表示在调用该类型内部方法时,使用调用方法的用户的权限来执行。这是默认值。

AUTHID DEFINER指定要用类型的属主的权限来执行该类型的内部方法。

STATIC

标志该对象类型的内部函数(存储过程)为一个静态函数(存储过程)。

MEMBER

标志该对象类型的内部函数(存储过程)为一个成员函数(存储过程)。

CONSTRUCTOR FUNCTION

标志该方法作为该对象类型的构造函数被创建。

示例

这个例子创建了一种组合类型并且将其用在了一个函数定义中:

CREATE TYPE compfoo AS (f1 int, f2 text);CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$SELECT fooid, fooname FROM foo
$$ LANGUAGE SQL;

这个例子创建了一个枚举类型并且将其用在一个表定义中:

CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed');CREATE TABLE bug (id serial,description text,status bug_status
);

这个例子创建了一个范围类型:

CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);

创建一个INT类型的嵌套表,并且元素的值不能NULL:

CREATE TYPE int_table AS TABLE OF INT NOT NULL;

创建一个最大长度为10的INT类型的可变数组:

CREATE TYPE int_varray AS VARRAY(10) OF INT;

这个例子创建了基本数据类型box然后将它用在一个表定义中:

CREATE TYPE box;CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ;
CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ;CREATE TYPE box (INTERNALLENGTH = 16,INPUT = my_box_in_function,OUTPUT = my_box_out_function
);CREATE TABLE myboxes (id integer,description box
);

如果box的内部结构是四个 float4元素的一个数组,我们可能会使用:

CREATE TYPE box (INTERNALLENGTH = 16,INPUT = my_box_in_function,OUTPUT = my_box_out_function,ELEMENT = float4
);

这将允许用下标来访问一个 box 值的组件编号。否则该类型的行为和 前面的一样。

这个例子创建了一个大对象类型并且将它用在了一个表定义中:

CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout,INTERNALLENGTH = VARIABLE
);
CREATE TABLE big_objs (id integer,obj bigobj
);

创建一个对象类型声明:

CREATE OR REPLACE TYPE objtype FORCE AUTHID CURRENT_USER AS OBJECT(f1 INT,f2 TEXT,MEMBER FUNCTION memfunc(i INT) RETURN INT,STATIC PROCEDURE staproc(),CONSTRUCTOR FUNCTION objtype(self inout objtype) RETURN SELF AS RESULT
);

更多例子(包括配套的输入和输出函数)请见: 用户定义的类型 。

兼容性

创建组合类型的第一种形式的CREATE TYPE命令符合 SQL 标准。 其他的形式都是 KingbaseES 扩展。SQL 标准中的CREATE TYPE语 句也定义了其他 KingbaseES 中没有实现的形式。

创建一个具有零个属性的组合类型的能力是一种 KingbaseES 对 SQL 标准 的衍生(类似于 CREATE TABLE中相同的情况)。

其他

由于一旦数据类型被创建,对该数据类型的使用就没有限制,创建一种基本类型 或者范围类型就等同于在类型定义中提到的函数上授予公共执行权限。对于在类 型定义中有用的函数来说这通常不是问题。但是如果设计一种类型时要求在转换 到外部形式或者从外部形式转换时使用“秘密”信息,你就应该三思而 后行。

在KingbaseESV7版本之前,自动生成的 数组类型的名称总是正好为元素类型的名称外加一个前置的下划线字符( _)。因此类型名称的长度限制比其他名称还要少一个字符。 虽然现在这仍然是通常情况,但如果名称达到最大长度或者与其他下划线开头 的用户类型名称冲突,数组类型的名称也可以不同于这种规则。因此依靠这种 习惯编写代码现在已经不适用了。现在,可以使用 sys_type.typarray来定位与给定类型相关 的数组类型。

建议避免使用以下划线开始的类型名和表名。虽然服务器会改变生成的数组 类型名称以避免与用户给定的名称冲突,仍然有混淆的风险,特别是对旧的 客户端软件来说,它们可能会假定以下划线开始的类型名总是表示数组。

在KingbaseES V7版本之前, shell-type 的创建语法 CREATE TYPE name不存在。创建 一种新基本类型的方法是先创建它的输入函数。在这种方法中, KingbaseES 将首先把新数据类型的名 称看做是输入函数的返回类型。在这种情况下 shell type 会被隐式地创建, 并且能在剩余的 I/O 函数的定义中引用。这种方法现在仍然有效,但是已经 被弃用并且可能会在未来的某个发行中被禁止。还有,为了避免由于函数定 义中的打字错误导致 shell type 弄乱系统目录,当输入函数用 C 编写时, 将只能用这种方法创建一种 shell type。

在KingbaseES V7以前的版本中, 常常为了完全避免创建 shell type 而把函数对该类型名的向前引用用占位符 伪类型opaque替换。在V7以前,cstring参数和 结果也必须被声明为opaque。为了支持载入旧的转储文件, CREATE TYPE将接受使用opaque声明的 I/O 函数,但是它将发出一个提示并且把函数的声明改成使用正确的类型。

静态函数(存储过程)不能创建含有名为SELF的参数,在调用时 需要以类型名做前缀修饰,如type_name.method()。

成员函数(存储过程)的第一个参数必须是名为SELF且类型为当 前对象类型的参数,若未显式创建SELF参数,那么该参数会被隐 式创建为IN参数。在调用成员函数(存储过程)时需要以类型定 义的具体对象名做前缀修饰,如object_expression.method()。且不需要 为SELF参数传值,成员函数(存储过程)会自动接收对其进行修 饰的对象作为SELF参数传入。

成员函数(存储过程)的SELF参数可以是IN参数或者IN OUT参数。

一个对象类型可以创建多个构造函数,所有构造函数都必须与类型同名。 与成员方法一样,自定义构造函数的第一个参数必须是SELF参数, 若SELF参数未被显式创建,也会被隐式创建。不同于成员方法的是, 自定义构造函数的SELF参数只能是IN OUT参数。

16.16. CREATE TYPE BODY

用途

CREATE TYPE BODY完善一个对象类型的所有内部函数(存储过程)的定义。 CREATE OR REPLACE TYPE BODY 将完善一个新的或者替换一个已有的对象类型的所有子函数(存储过程)的定义。

在 CREATE TYPE BODY 语句中,必须一次性为所有对象类型声明中声明的内部函数(存储过程)的定义进行完善,否则 CREATE TYPE BODY 语句无法执行成功。

前置条件

如果给定一个模式名,那么该类型体将被创建在指定的模式中。否则它会被创建在当前模式中。类型体名称必须与对应模式中对应的对象类型声明相同。

语法

CREATE [ OR REPLACE ] TYPE BODY name { AS | IS }[ { STATIC | MEMBER } FUNCTION function_name[ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ][, ...] ] ) ]{ RETURNS | RETURN } rettype{ AS | IS }plsql_block ][ { STATIC | MEMBER } PROCEDURE procedure_name[ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ][, ...] ] ) ]{ AS | IS }plsql_block ][ CONSTRUCTOR FUNCTION name[ ( [ SELF IN OUT name ] [, argname [ argmode ] argtype [ { DEFAULT| := } default_expr ] [, ...] ] ) ]{ RETURNS | RETURN } SELF AS RESULT { AS | IS }[ variable_declaration ][ cursor_declaration ][ type_declaration ][ exception_declaration ][ nestfunction_declaration ]BEGINsequence_of_statementRETURN ;END; ][ ... ]
END;

语义

name

对象类型的名称(可以被模式限定)。

STATIC

对象类型内部函数(存储过程)的类型为 STATIC

MEMBER

对象类型内部函数(存储过程)的类型为 MEMBER

function_name

对象类型的内部函数的名称。

argmode

函数(存储过程)的参数的模式:INOUT 或者 INOUT。如果省略,默认为IN

argname

函数(存储过程)的参数的名称。

argtype

该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、对象类型或者域类型,或者可以引用一个表列的类型。

根据实现语言,也可以允许指定cstring之类的"伪类型"。伪类型表示实际参数类型没有被完整指定或者不属于普通 SQL 数据类型集合。

可以写table_name.column_name%TYPE来引用一列的类型。使用这种特性有时可以帮助创建一个不受表定义更改影响的函数。

default_expr

如果参数没有被指定值时要用作默认值的表达式。该表达式的值必须能被强制转为对应参数的类型。只有输入(包括INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默认值。CREATE TYPE BODY 语句中的内部函数(存储过程)定义中参数的默认值必须保持与 CREATE TYPE 语句中内部函数(存储过程)声明时指定的默认值相同(如果有的话)。

rettype

返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、对象类型或者域类型,也可以引用一个表列的类型。如果该函数不会返回一个值,可以指定返回类型为void

可以写table_name.column_name%TYPE来引用一列的类型。

plsql_block

包括变量、常量、游标和类型的定义以及PL/SQL语句组成的块结构。

procedure_name

对象类型的内部存储过程的名称。

示例

创建一个完整的对象类型:

CREATE OR REPLACE TYPE objtype FORCE AUTHID CURRENT_USER AS OBJECT(f1 int,f2 varchar2(10),MEMBER FUNCTION memfunc(i int) RETURN INT,STATIC PROCEDURE staproc,CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT
);\set SQLTERM /
CREATE OR REPLACE TYPE BODY objtype ASMEMBER FUNCTION memfunc(i int) RETURN INT ASBEGINRAISE NOTICE 'self.f1 is %', self.f1;RAISE NOTICE 'self.f2 is %', f2;RETURN i;END;STATIC PROCEDURE staproc ASBEGINRAISE NOTICE 'this is a static procedure in object type';END;CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT ASBEGINf1 := 1;self.f2 := 'a';RETURN ;END;
END;
/
\set SQLTERM ;

对象类型成员函数及构造函数的使用:

CREATE TABLE tb1(i objtype);
INSERT INTO tb1 VALUES(objtype()); -- 自定义构造函数
INSERT INTO tb1 VALUES(objtype(2, 'b')); -- 默认构造函数
SELECT * FROM tb1;i
-------(1,a)(2,b)
(2 rows)SELECT t.i.memfunc(1) FROM tb1 t;
NOTICE:  self.f1 is 1
NOTICE:  self.f2 is a
NOTICE:  self.f1 is 2
NOTICE:  self.f2 is bobjtype.memfunc
-----------------11
(2 rows)

对象类型静态存储过程的使用:

CALL objtype.staproc();
NOTICE:  this is a static procedure in object type
CALL

其他

静态函数(存储过程)不能创建含有名为SELF的参数,在调用时需要以类型名做前缀修饰,如type_name.method()。

成员函数(存储过程)的第一个参数必须是名为SELF且类型为当前对象类型的参数,若未显式创建SELF参数,那么该参数会被隐式创建为IN参数。在调用成员函数(存储过程)时需要以类型定义的具体对象名做前缀修饰,如object_expression.method()。且不需要为SELF参数传值,成员函数(存储过程)会自动接收对其进行修饰的对象作为SELF参数传入。

成员函数(存储过程)的SELF参数可以是IN参数或者IN OUT参数。

一个对象类型可以创建多个构造函数,所有构造函数都必须与类型同名。与成员方法一样,自定义构造函数的第一个参数必须是SELF参数,若SELF参数未被显式创建,也会被隐式创建。

不同于成员方法的是,自定义构造函数的SELF参数只能是IN OUT参数。

不同于普通函数,自定义构造函数的RETURN子句不能带有任何表达式,构造函数总会自动把SELF参数作为返回值进行返回。

16.17. CREATE USER

用途

CREATE USER现在是 CREATE ROLE 的一个别名。唯一的区别是``CREATE USER``中LOGIN 被作为默认值,而NOLOGIN是``CREATE ROLE``的默认值。

前置条件

你必须具有 CREATE ROLE 特权或者成为一个数据库超级用户。

语法

CREATE USER name [ [ WITH ] option [ ... ] ]这里 option 可以是:SUPERUSER | NOSUPERUSER| CREATEDB | NOCREATEDB| CREATEROLE | NOCREATEROLE| INHERIT | NOINHERIT| LOGIN | NOLOGIN| ACCOUNT { LOCK | UNLOCK }| REPLICATION | NOREPLICATION| BYPASSRLS | NOBYPASSRLS| CONNECTION LIMIT connlimit| [ ENCRYPTED ] PASSWORD 'password'| VALID UNTIL 'timestamp'| IN ROLE role_name [, ...]| IN GROUP role_name [, ...]| ROLE role_name [, ...]| ADMIN role_name [, ...]| USER role_name [, ...]| SYSID uid

语义

参见 CREATE ROLE

示例

参见 CREATE ROLE

16.18. CREATE USER MAPPING

用途

CREATE USER MAPPING定义一个用户 到一个外部服务器的新映射。一个用户映射通常会包含连接信息,外部数据包装器 会使用连接信息和外部服务器中包含的信息一起来访问一个外部数据源。

前置条件

一个外部服务器的拥有者可以为任何服务器任何用户创建用户映射。还有, 如果一个用户被授予了服务器上的USAGE特权,该用户可以 为他们自己的用户名创建用户映射。

语法

CREATE USER MAPPING [IF NOT EXISTS] FOR { user_name | USER | CURRENT_USER |
PUBLIC }SERVER server_name[ OPTIONS ( option 'value' [ , ... ] ) ]

语义

IF NOT EXISTS

如果给定用户到给定外部服务器的映射已经存在,则不要抛出错误。 在这种情况下发出通知。请注意,不能保证现有的用户映射与要创建的映射完全相同。

user_name

要映射到外部服务器的一个现有用户的名称。 CURRENT_USERUSER匹配当前用户的名称。 当PUBLIC被指定时,一个所谓的公共映射会被创建,当没有 特定用户的映射可用时将会使用它。

server_name

将为其创建用户映射的现有服务器的名称。

OPTIONS ( option 'value' [, ... ] )

这个子句指定用户映射的选项。这些选项通常定义该映射实际的用户名和 口令。选项名必须唯一。允许的选项名和值与该服务器的外部数据包装器 有关。

示例

为用户bob、服务器foo创建一个用户映射:

CREATE USER MAPPING FOR bob SERVER foo OPTIONS (user 'bob', password 'secret');

兼容性

CREATE USER MAPPING符合 ISO/IEC 9075-9 (SQL/MED)

16.19. CREATE VIEW

用途

CREATE VIEW定义一个查询的视图。该视图不会被物理上物质化。相反,在每一次有查询引用该视图时,视图的查询都会被运行。

CREATE OR REPLACE VIEW与之相似,但是如果已经存在一个同名视图,该视图会被替换。当原视图被其他对象依赖,在被替换前,将依赖对象更新为无效状态。如果依赖原视图的对象不是视图,在更新其状态时会出错;如果依赖原视图的对象是视图,则将该对象更新为无效状态。

如果给定了一个模式名(例如CREATE VIEW myschema.myview ...),那么该视图会被创建在指定的模式中。否则,它会 被创建在当前模式中。临时视图存在于一个特殊模式中,因此创建临时视图时不能 给定一个模式名。视图的名称不能与同一模式中任何其他视图、表、序列、索引或 外部表同名。

前置条件

如果给定了一个模式名,那么该视图会被创建在指定的模式中。否则,它会被创建在当前模式中。临时视图存在于一个特殊模式中,因此创建临时视图时不能给定一个模式名。

语法

CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] [ FORCE ] VIEW name [ ( column_name [, ...] ) ][ WITH ( view_option_name [= view_option_value] [, ... ] ) ]AS query[ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

语义

TEMPORARY或者TEMP

如果被指定,视图被创建为一个临时视图。在当前会话结束时会自动 删掉临时视图。当临时视图存在时,具有相同名称的已有永久视图对 当前会话不可见,除非用模式限定的名称引用它们。

如果视图引用的任何表是临时的,视图将被创建为临时视图(不管有 没有指定TEMPORARY)。

RECURSIVE

创建一个递归视图。语法

CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS
SELECT ...;

等效于

CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name
(column_names) AS (SELECT ...) SELECT column_names
FROM view_name;

对于一个递归视图必须指定一个视图列名列表。

FORCE

创建一个FORCE视图。语法

CREATE FORCE VIEW [ schema . ] view_name (column_names) AS
SELECT ...;

创建一个FORCE视图,无论视图依赖检查是否成功都能创建视图。依赖检查(编译)成功,那么创建为一个有效视图,否则为一个无效视图。

name

要创建的视图的名字(可以是模式限定的)。

column_name

要用于视图列的名称列表,可选。如果没有给出,列名会根据查询 推导。

WITH ( view_option_name [= view_option_value] [, ... ] )

这个子句为视图指定一些可选的参数,支持下列参数:

check_option (string)

这个参数可以是local或者cascaded,并且它 等效于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(见下文)。 可以使用 ALTER VIEW 在一个现有视图上修改这个选项。

security_barrier (boolean)

如果希望视图提供行级安全性,应该使用这个参数。详见 规则和权限 。

query

提供视图的行和列的一个 SELECT 或者 VALUES 命令。

WITH [ CASCADED | LOCAL ] CHECK OPTION

这个选项控制自动可更新视图的行为。这个选项被指定时,将检查该视图上的 INSERTUPDATE命令以确保新行满足 视图的定义条件(也就是,将检查新行来确保通过视图能看到它们)。如果新行 不满足条件,更新将被拒绝。如果没有指定CHECK OPTION, 会允许该视图上的INSERTUPDATE命令 创建通过该视图不可见的行。支持下列检查选项:

LOCAL

只根据直接定义在该视图本身的条件检查新行。任何定义在底层基视图上的 条件都不会被检查(除非它们也指定了CHECK OPTION)。

CASCADED

会根据该视图和所有底层基视图上的条件检查新行。如果 CHECK OPTION被指定,并且没有指定 LOCALCASCADED,则会假定为 CASCADED

CHECK OPTION不应该和RECURSIVE视图一起使用。

注意,只有在自动可更新的、没有INSTEAD OF触发器或者 INSTEAD规则的视图上才支持CHECK OPTION。 如果一个自动可更新的视图被定义在一个具有INSTEAD OF 触发器的基视图之上,那么LOCAL CHECK OPTION可以被 用来检查该自动可更新的视图之上的条件,但具有INSTEAD OF 触发器的基视图上的条件不会被检查(一个级联检查选项将不会级联到一个 触发器可更新的视图,并且任何直接定义在一个触发器可更新视图上的检查 选项将被忽略)。如果该视图或者任何基础关系具有导致 INSERTUPDATE命令被重写的 INSTEAD规则,那么在被重写的查询中将忽略所有检查选项, 包括任何来自于定义在带有INSTEAD规则的关系之上的自动 可更新视图的检查。

示例

创建一个由所有喜剧电影组成的视图:

CREATE VIEW comedies ASSELECT *FROM filmsWHERE kind = 'Comedy';

创建的视图包含创建时film表中的列。尽管`` *``被用来创建该视图,后来被加入到该表中的列不会成为该视图的组成部分。

创建带有LOCAL CHECK OPTION的视图:

CREATE VIEW universal_comedies ASSELECT *FROM comediesWHERE classification = 'U'WITH LOCAL CHECK OPTION;

这将创建一个基于comedies视图的视图,只显示 kind = 'Comedy'classification = 'U'的电影。 如果新行没有classification = 'U',在该视图中的任何 INSERTUPDATE尝试将被拒绝, 但是电影的kind将不会被检查。

CASCADED CHECK OPTION创建一个视图:

CREATE VIEW sys_comedies ASSELECT *FROM comediesWHERE classification = 'PG'WITH CASCADED CHECK OPTION;

这将创建一个检查新行的kindclassification 的视图。

创建一个由可更新列和不可更新列混合而成的视图:

CREATE VIEW comedies ASSELECT f.*,country_code_to_name(f.country_code) AS country,(SELECT avg(r.rating)FROM user_ratings rWHERE r.film_id = f.id) AS avg_ratingFROM films fWHERE f.kind = 'Comedy';

这个视图将支持INSERTUPDATE 以及DELETE。所有来自于films表的列都 将是可更新的,而计算列countryavg_rating 将是只读的。

创建一个由数字 1 到 100 组成的递归视图:

CREATE RECURSIVE VIEW public.nums_1_100 (n) ASVALUES (1)
UNION ALLSELECT n+1 FROM nums_1_100 WHERE n < 100;

注意在这个CREATE中尽管递归的视图名称是方案限定的,但它内部的自引用不是方案限定的。这是因为隐式创建的CTE的名称不能是方案限定的。

兼容性

CREATE OR REPLACE VIEW是一种 KingbaseES的语言扩展。临时 视图的概念也是这样。WITH ( ... )子句也是一种扩展。

其他

  1. 使用 DROP VIEW 语句删除视图。

    要小心视图列的名称和类型将会按照你想要的方式指定。例如:

    CREATE VIEW vista AS SELECT 'Hello World';
    

    是不好的形式,因为列名默认为?column?,而且列的数据类型默认为text,这可能不是用户想要的。视图结果中一个字符串更好的风格类似于这样:

    CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
    

    对视图中引用的表的访问由视图拥有者的权限决定。在某些情况下,这可以 被用来提供安全但是受限的底层表访问。不过,并非所有视图都对篡改是安 全的,详见 规则和权限 。在视图中调用的函数会被 同样对待,就好像是直接在使用该视图的查询中调用它们一样。因此,一个 视图的用户必须具有调用视图所使用的全部函数的权限。

    CREATE OR REPLACE VIEW被用在一个现有视图上时, 只有该视图的定义 SELECT 规则被改变。其他包括拥有关系、权限和非 SELECT 规则在内的视图属性不会被更改。要替换视图,你必须拥有它(包括 作为拥有角色的一个成员)。

  2. 可更新视图

    简单视图是自动可更新的:系统将允许在这类视图上以在常规表上相同的方式 使用INSERTUPDATE以及 DELETE语句。如果一个视图满足以下条件,它就是自动 可更新的:

    • 在该视图的FROM列表中刚好只有一项,并且它必须是一个 表或者另一个可更新视图。

    • 视图定义的顶层不能包含WITHDISTINCT、 GROUP BYHAVING、 LIMIT或者OFFSET子句。

    • 视图定义的顶层不能包含集合操作(UNION、 INTERSECT或者EXCEPT)。

    • 视图的选择列表不能包含任何聚集、窗口函数或者集合返回函数。

    一个自动可更新的视图可以混合可更新列以及不可更新列。如果一个列是对底层 基本关系中一个可更新列的简单引用,则它是可更新的。否则该列是只读的,并 且在一个INSERT或者UPDATE语句尝试对 它赋值时会报出一个错误。

    如果视图是自动可更新的,系统将把视图上的任何INSERT、 UPDATE或者DELETE语句转换成在底层 基本关系上的对应语句。带有ON CONFLICT UPDATE子句的 INSERT语句已经被完全支持。

    如果一个自动可更新视图包含一个WHERE条件,该条件会限制 基本关系的哪些行可以被该视图上的UPDATE以及 DELETE语句修改。不过,一个允许被UPDATE 修改的行可能让该行不再满足WHERE条件,并且因此也不再能 从视图中可见。类似地,一个INSERT命令可能插入不满足 WHERE条件的基本关系行,并且因此从视图中也看不到这些行 (ON CONFLICT UPDATE可能会类似地影响无法通过该视图见 到的现有行)。 CHECK OPTION可以被用来阻止INSERT和 UPDATE命令创建这类从视图中无法看到的行。

    如果一个自动可更新视图被标记了security_barrier属性,那么 所有该属性的WHERE条件(以及任何使用标记为 LEAKPROOF的操作符的条件)将在该视图使用者的任何条件 之前计算。详见 规则和权限 。由于它们不会通过 用户的WHERE条件,所以,最终不会返回的行可能 仍会结束被锁定的状态。可以用EXPLAIN来查看 哪些条件被应用在关系层面(并且因此不锁定行)以及哪些不会被应用在关系 层面。

    一个更加复杂的不满足所有这些条件的视图默认是只读的:系统将不允许在 该视图上的插入、更新或者删除。可以通过在该视图上创建一个 INSTEAD OF触发器来获得可更新视图的效果,该触发器必须 把该视图上的尝试的插入等转换成其他表上合适的动作。更多信息请见 CREATE TRIGGER语句 。另一种可能性是创建规则(见 CREATE RULE ),不过实际中触发器更容易理解和正确使用。

    注意在视图上执行插入、更新或删除的用户必须具有该视图上相应的插入、 更新或删除特权。此外,视图的拥有者必须拥有底层基本关系上的相关特权, 但是执行更新的用户并不需要底层基本关系上的任何权限(见 规则和权限 )。

16.20. DEALLOCATE

用途

DEALLOCATE被用来释放一个之前 准备好的 SQL 语句。如果不显式地释放一个预备语句,会话结束 时会释放它。

更多关于预备语句的信息请见 PREPARE 。

前置条件

语法

DEALLOCATE [ PREPARE ] { name | ALL }

语义

PREPARE

这个关键词会被忽略。

name

要释放的预备语句的名称。

ALL

释放所有预备语句。

示例

DEALLOCATE ALL;

兼容性

SQL 标准包括一个DEALLOCATE语句, 但是只用于嵌入式 SQL。

16.21. DECLARE

用途

DECLARE允许用户创建游标, 游标可以被用来在大型查询暂停时检索少量的行。游标被创建后, 可以用 FETCH 从中取得行。

注意

这个页面描述在 SQL 命令层面上游标的用法。如果想要在 PL/SQL函数中使用游标,其规则是不同的。

前置条件

语法

DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ]CURSOR [ { WITH | WITHOUT } HOLD ] FOR query

语义

name

要创建的游标的名称。

BINARY

让游标返回二进制数据而不是返回文本格式数据。

INSENSITIVE

指示从游标中检索数据的过程不受游标创建之后在其底层表上发生的更新的 影响。在KingbaseES中,这是默认的 行为。因此这个关键词没有实际效果,仅仅被用于兼容 SQL 标准。

SCROLL NO SCROLL

SCROLL指定游标可以用非顺序(例如,反向) 的方式从中检索行。根据查询的执行计划的复杂度,指定 SCROLL可能导致查询执行时间上的性能损失。 NO SCROLL指定游标不能以非顺序的方式从中检索 行。默认是允许在某些情况下滚动,但这和指定 SCROLL不完全相同。

WITH HOLD WITHOUT HOLD

WITH HOLD指定该游标在创建它的事务提交 之后还能被继续使用。WITHOUT HOLD指定该游标 不能在创建它的事务之外使用。如果两者都没有指定,则默认为 WITHOUT HOLD

query

用于提供该游标返回的行的 SELECT 或者 VALUES 命令。

关键词 BINARY 、 INSENSITIVE 和 SCROLL 可以以任意顺序出现。

示例

声明一个游标:

DECLARE liahona CURSOR FOR SELECT * FROM films;

更多游标的例子请见 FETCH 。

兼容性

SQL 标准认为游标是否默认对底层数据的并发更新敏感是与实现相关的。在 KingbaseES中,默认游标对此是不敏 感的,并且可以通过指定FOR UPDATE让它变得对此敏感。其他 产品的行为可能有所不同。

SQL 标准只允许在嵌入式SQL和模块中使用游标。 KingbaseES允许以交互的方式使用游标。

二进制游标是一种KingbaseES 扩展。

其他

普通游标以文本格式返回数据,这和SELECT产生的数据一样。 BINARY选项指定游标应该以二进制格式返回数据。这减少了服务 器和客户端的转换负担,但程序员需要付出更多工作来处理与平台相关的二进制 数据格式。例如,如果一个查询从一个整数列中返回一个值一,用一个默认游标 将得到一个字符串1,而使用一个二进制游标将得到该值的四字节 内部表示(big-endian 大端字节顺序)。

使用二进制游标时应该小心。很多应用(包括 ksql)还没有准备好处理二进制游标, 它们仍然期待数据以文本格式到来。

注意

当客户端应用使用“扩展查询”协议发出一个 FETCH命令,绑定协议消息会指定使用文本还是 二进制格式检索数据。这种选择会覆盖定义游标时指定的方式。因此 在使用扩展查询协议时,这样一个二进制游标的概念实际是被废弃的 — 任何游标都可以被视作文本或者二进制。

除非指定了WITH HOLD,这个命令创建的游标 只能在当前事务中使用。因此,没有WITH HOLD 的DECLARE在事务块外是没有用的:游标只会生存 到该语句结束。因此如果这种命令在事务块之外被使用, KingbaseES会报告一个错误。 定义事务块需要使用 BEGIN 和 COMMIT (或者 ROLLBACK )。

如果指定了WITH HOLD并且创建游标的事务 成功提交,在同一个会话中的后续事务中还能够继续访问该游标( 但是如果创建事务被中止,游标会被移除)。一个用 WITH HOLD创建的游标可以用一个显式的 CLOSE命令关闭,或者会话结束时它 也会被关闭。在当前的实现中,由一个被保持游标表示的行会被复 制到一个临时文件或者内存区域中,这样它们才会在后续事务中保 持可用。

当查询包括FOR UPDATEFOR SHARE时, 不能指定WITH HOLD

在定义一个将被反向取元组的游标时,应该指定SCROLL 选项。这是 SQL 标准所要求的。不过,为了和早期版本兼容, 如果游标的查询计划足够简单到支持它不需要额外的开销, KingbaseES会允许在没有 SCROLL的情况下反向取元组。不过,建议应用开发者 不要依赖于从没有用SCROLL创建的游标中反向取 元组。如果指定了NO SCROLL,那么任何情况下都不 允许反向取元组。

当查询包括FOR UPDATEFOR SHARE时, 也不允许反向取元组。因此在这种情况下不能指定 SCROLL

Caution

如果可滚动和WITH HOLD游标调用了任何不稳定的 函数(见 函数易变性分类 ),它们可能给出预期之外 的结果。当重新取得一个之前取得过的行时,那些函数会被重新执行,这 可能导致得到与第一次不同的结果。对这类情况的一种变通方法是,声明 游标为WITH HOLD并且在从其中读取任何行之前提交 事务。这将强制该游标的整个输出被物化在临时存储中,这样针对每一行 只会执行一次不稳定函数。

如果游标的查询包括FOR UPDATE或者FOR SHARE,那么被返回的行会在它们第一次被取得时被锁定,这和带有 这些选项的常规 SELECT 命令一样。此外,被返回的 行将是最新的版本,因此这些选项提供了被 SQL 标准称为 “敏感游标”的等效体(把INSENSITIVE与 FOR UPDATE或者FOR SHARE一起指定是错误)。

Caution

如果游标要和UPDATE ... WHERE CURRENT OF或者 DELETE ... WHERE CURRENT OF一起使用,通常推荐 使用FOR UPDATE。使用FOR UPDATE可以 阻止其他会话在行被取得和被更新之间修改行。如果没有 FOR UPDATE,当行在游标创建后被更改后,一个后续的 WHERE CURRENT OF命令将不会产生效果。

另一个使用FOR UPDATE的原因是,如果没有它,当游标查询不符合 SQL 标准的“简单可更新”规则时,后续的 WHERE CURRENT OF可能会失败(特别地,该游标必须只引用一个 表并且没有使用分组或者ORDER BY)。不是简单可更新的游标可能 成功也可能不成功,这取决于计划选择的细节。因此在最坏的情况下,应用可能会 在测试时成功但是在生产中失败。

不把FOR UPDATEWHERE CURRENT OF一起用的 主要原因是,需要游标时可滚动的或者对于后续更新不敏感(也就是说,继续显示 旧的数据)。如果这是你的需求,应密切关注安上述警示。

SQL 标准只对嵌入式SQL中的游标做出了规定。 KingbaseES服务器没有为游标实现 OPEN语句。当游标被声明时就被认为已经 被打开。不过,ESQL( KingbaseES的嵌入式 SQL 预处理器) 支持标准 SQL 游标习惯,包括那些DECLARE 和OPEN语句。

你可以通过查询 sys_cursors 系统视图可以看到所有可用的游标。

16.22. DELETE

用途

DELETE从指定表中删除满足 WHERE子句的行。如果WHERE 子句没有出现,效果将会是删除表中的所有行。结果是一个合法的空表。

TRUNCATE 提供移除表中所有行的快速机制。

有两种方式可以使用数据库中其他表中包含的信息来删除一个表的行: 使用子选择或者在USING子句中指定额外的表。 哪种技术更合适取决于特定的环境。

可选的RETURNING子句导致DELETE 基于实际被删除的每一行计算并且返回值。任何使用被删除表列或者 USING中提到的其他表的列的表达式都可以被计算。 RETURNING列表的语法和SELECT的 输出列表语法相同。

前置条件

要从表中删除行,你必须具有其上的DELETE特权, 以及USING子句中任何表以及其值在``condition``中被读取的表上的 SELECT特权。

语法

[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ][ USING using_list ][ WHERE condition | WHERE CURRENT OF cursor_name ][ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

语义

with_query

WITH子句允许你指定一个或者多个子查询,在 DELETE查询中可以用子查询的名字来引用它们。 详见 WITH查询 和 SELECT 。

table_name

要从其中删除行的表名(可以是模式限定的)。如果在表名前指定 ONLY,只会从提到的表中删除匹配的行。如果没有指定 ONLY,还会删除该表的任何继承表中的匹配行。可选地, 可以在表名后面指定*来显式指定要包括继承表。

alias

目标表的一个别名。提供别名时,它会完全隐藏该表的真实名称。例如, 对于DELETE FROM foo AS f, DELETE语句的剩余部分都会用 f而不是 foo来引用该表。

using_list

一个表表达式的列表,它允许在WHERE条件中出现 来自其他表的列。这和SELECT语句 的`FROM 子句中指定 的表列表相似。例如,可以指定表的别名。除非想要进行自连接, 否则不要在``using_list`` 再写上目标表。

condition

一个返回boolean类型值的表达式。只有让这个 表达式返回true的行才将被删除。

cursor_name

要在WHERE CURRENT OF情况中使用的游标 的名称。最近一次从这个游标中取出的行将被删除。该游标 必须是DELETE的目标表上的非分组查询。 注意不能在使用WHERE CURRENT OF的同时 指定一个布尔条件。有关将游标用于 WHERE CURRENT OF的更多信息请见 DECLARE 。

output_expression

在每一行被删除后,会被DELETE计算并且返回的表达式。 该表达式可以使用``table_name`` 以及USING中的表的任何列。写成*可以返回所有列。

output_name

被返回列的名称。

示例

删除所有电影,但音乐剧除外:

DELETE FROM films WHERE kind <> 'Musical';

清空表films

DELETE FROM films;

删除已完成的任务,返回被删除行的明细:

DELETE FROM tasks WHERE status = 'DONE' RETURNING *;

删除tasks中游标c_tasks 当前位于其上的行:

DELETE FROM tasks WHERE CURRENT OF c_tasks;

兼容性

这个命令符合SQL标准,不过 USINGRETURNING子句是 KingbaseES扩展,在 DELETE中使用WITH也是扩展。

其他

  1. 输出

    在成功完成时,一个DELETE命令会返回以下形式 的命令标签:

    DELETE count
    

    ``count``是被删除行的数目。 注意如果有一个BEFORE DELETE触发器抑制删除,那么该数目 可能小于匹配``condition`` 的行数。如果``count``为 0, 表示查询没有删除行(这并非一种错误)。

    如果DELETE命令包含RETURNING子句, 则结果会与包含有RETURNING列表中定义的列和值的 SELECT语句结果相似,这些结果是在被该命令删除的 行上计算得来。

  2. 注解

    通过在USING子句中指定其他的表, KingbaseES允许在 WHERE条件中引用其他表的列。例如,要 删除有一个给定制片人制作的所有电影,可以这样做:

    DELETE FROM films USING producersWHERE producer_id = producers.id AND producers.name = 'foo';
    

    这里实际发生的事情是在films和 producers之间进行连接,然后删除 所有成功连接的films行。这种语法不 属于标准。更标准的方式是:

    DELETE FROM filmsWHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');
    

    在一些情况下,连接形式比子查询形式更容易书写或者执行更快。

金仓数据库 KingbaseES SQL 语言参考手册 (16. SQL语句: CREATE SEQUENCE 到 DELETE)相关推荐

  1. 金仓数据库 KingbaseES SQL 语言参考手册 (11. SQL语句:ABORT 到 ALTER INDEX)

    11. SQL语句:ABORT 到 ALTER INDEX 本章描述各种类型的SQL语句,由于类型较多,将按字母顺序排列分组.这是第一组SQL语句. 包含以下章节: SQL语句类型 SQL语句各章节是 ...

  2. 金仓数据库 KingbaseES SQL 语言参考手册 (13. SQL语句:ALTER SYNONYM 到 COMMENT)

    13. SQL语句:ALTER SYNONYM 到 COMMENT 本章包含以下SQL语句: ALTER SYNONYM ALTER SYSTEM ALTER TABLE ALTER TABLESPA ...

  3. 金仓数据库KingbaseES数据库参考手册(服务器配置参数14. 版本和平台兼容性)

    目录 14.1. KingbaseES老版本 ¶ 14.2. 平台和客户端兼容性 ¶ 14.3. 一般特性兼容性 ¶ 14.1. KingbaseES老版本 ¶ array_nulls 属性 描述 类 ...

  4. 金仓数据库KingbaseES行列转换

    概述 行列转换是在数据分析中经常用到的一项功能,金仓数据库KingbaseES从V8R6C3B0071版本开始通过扩展插件(kdb_utils_function)支持pivot和unpivot功能.在 ...

  5. 金仓数据库KingbaseES数据库开发指南(2. 开发基础)

    目录 2.1. 设计基础 ¶ 2.1.1. 数据库部署模式 ¶ 2.1.2. 数据库环境规划 ¶ 2.1.3. 可扩展性设计 ¶ 2.1.4. 安全设计 ¶ 2.1.5. 可移植性设计 ¶ 2.1.6 ...

  6. 金仓数据库KingbaseES函数的管理

    关键字 kingbase,函数 问题描述 如何管理金仓数据库KingbaseES函数? 解决方案 a.创建一个函数 create or repalce function CREATE FUNCTION ...

  7. 解决金仓数据库KingbaseES创建serial列并将其设置为主键约束,同时copy两条及以上数据时报错的问题

    ​  关键字 人大金仓.金仓数据库.KingbaseES.KES.serial.copy.PRIMARY KEY 问题描述 使用KingbaseES V8R3数据库的客户端工具ksql执行copy - ...

  8. 金仓数据库KingbaseES ORACLE_FDW常见问题

    ​  1. OCIEnvCreate错误 错误信息:error:error connecting to Oracle: OCIEnvCreate failed to create environmen ...

  9. 金仓数据库KingbaseES表空间(tablespace)知多少

    金仓数据库KingbaseES表空间定义 金仓数据库KingbaseES中的表空间允许在文件系统里定义那些代表数据库对象的文件存放位置,比如表和索引等.一旦表空间被创建,那么就可以在创建数据库对象时通 ...

最新文章

  1. python03-异常处理
  2. Android开发 常用命令
  3. Android缓存学习入门(二)
  4. Git和GitHub快速入门
  5. 使用 store 来优化 React 组件
  6. MySQL_运算符与函数
  7. python 安装包的默认路径与更改
  8. 美媒:软银售ARM中国子公司51%股权,暴露美国痛处
  9. cl.nd77.pw index.php,Loop in template
  10. 如何用HTML制作一个3行3列的表格,如何利用表格制作网页
  11. 马化腾:创建生物型组织,让企业组织自我进化
  12. 传奇手游漏洞获取gm权限_传奇私服漏洞获取gm权限
  13. 必须记住这几种庄家洗盘的形态
  14. 使用pgadmin3操作数据库 简介,误删数据表格后用Django重新生成表
  15. k8s NoSchedule k8s 设置污点 NoExecute有点复杂 移除节点 drain和不可调度cordon
  16. Word论文公式的两个格式问题
  17. 红警战网地图下载 红警地图库下载 红警战网客户端地图库地图下载
  18. vlan高级配置之基于IP子网划分
  19. 万众瞩目,谷歌的反击来了!全新PaLM 2反超GPT-4,办公全家桶炸裂升级,Bard史诗进化...
  20. 产销平衡的运输问题上机实验matlab_MATLAB编程(运筹学之运输问题)

热门文章

  1. 实例编程iPhone 录音和播放
  2. c语言编程非线性方程求解,c语言计算机编程三种方法求解非线性方程.doc
  3. 微信自助辅助验证机器人_机器学习辅助构想的进步
  4. My Ninetieth Page - 最长递增子序列 - By Nicolas
  5. 木字楠后台管理系统开发(4):SpringSecurity引入并编写登陆接口
  6. mysql 查看登陆记录_查看用户登录记录
  7. 如何低成本实现酒店地图导航室内导航
  8. Surfer13 自动实现网格化
  9. [拓扑排序]旅行计划
  10. 体验迅雷看看HD3.3“远程视频”功能