SQL命令
一般来说,“SQL”指的是语言;有关每个命令的标准符合性和兼容性的信息可以在相应的参考页面中找到。
ABORT
ABORT — 中止当前事务
概要
ABORT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
描述
ABORT回滚当前事务并丢弃事务所做的所有更改。此命令的行为与标准的SQL命令ROLLBACK相同,仅出于历史原因而存在。
参数
-
WORK
TRANSACTION
可选关键字。它们没有任何影响。 -
AND CHAIN
如果指定了AND CHAIN,则会立即启动一个新事务,其事务特性(参见SET TRANSACTION)与刚刚完成的事务相同。否则,不会启动新事务。
注意事项
使用COMMIT成功终止事务。
在事务块外发出ABORT会发出警告,否则没有任何影响。
示例
中止所有更改:
ABORT;
兼容性
此命令是为历史原因而存在的UXsinoDB扩展。等效的标准SQL命令是ROLLBACK。
另请参阅
ALTER AGGREGATE
ALTER AGGREGATE — 更改聚合函数的定义
概要
ALTER AGGREGATE name ( aggregate_signature ) RENAME TO new_name
ALTER AGGREGATE name ( aggregate_signature )
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER AGGREGATE name ( aggregate_signature ) SET SCHEMA new_schema
其中 aggregate_signature 是:
* |
[ argmode ] [ argname ] argtype [ , ... ] |
[ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ]
描述
ALTER AGGREGATE更改聚合函数的定义。
您必须拥有该聚合函数才能使用ALTER AGGREGATE。要更改聚合函数的模式,您还必须对新模式具有CREATE权限。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对聚合函数的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建聚合函数来执行的任何操作。但是,超级用户可以更改任何聚合函数的所有权。)
参数
-
name
现有聚合函数的名称(可选模式限定符)。 -
argmode
参数的模式:IN或VARIADIC。如果省略,则默认为IN。 -
argname
参数的名称。请注意,ALTER AGGREGATE实际上不会关注参数名称,因为只需要参数数据类型即可确定聚合函数的标识。 -
argtype
聚合函数操作的输入数据类型。要引用零参数聚合函数,请在参数规范列表的位置写入*。要引用有序集聚合函数,请在直接和聚合参数规范之间写入ORDER BY。 -
new_name
聚合函数的新名称。 -
new_owner
聚合函数的新所有者。 -
new_schema
聚合函数的新模式。
注释
引用有序集聚合的推荐语法是在直接和聚合参数规范之间写入ORDER BY,与CREATE AGGREGATE中的样式相同。但是,省略ORDER BY并将直接和聚合参数规范直接运行到单个列表中也可以工作。在这种简写形式中,如果在直接和聚合参数列表中都使用了VARIADIC "any",则只需写入一次VARIADIC "any"。
示例
将类型为integer的聚合函数myavg重命名为my_average:
ALTER AGGREGATE myavg(integer) RENAME TO my_average;
将类型为integer的聚合函数myavg的所有者更改为joe:
ALTER AGGREGATE myavg(integer) OWNER TO joe;
将直接参数类型为float8,聚合参数类型为integer的有序集聚合mypercentile移动到模式myschema:
ALTER AGGREGATE mypercentile(float8 ORDER BY integer) SET SCHEMA myschema;
这也可以工作:
ALTER AGGREGATE mypercentile(float8, integer) SET SCHEMA myschema;
兼容性
SQL标准中没有ALTER AGGREGATE语句。
另请参阅
CREATE AGGREGATE,DROP AGGREGATE
ALTER COLLATION
ALTER COLLATION — 更改排序规则的定义
概要
ALTER COLLATION name REFRESH VERSION
ALTER COLLATION name RENAME TO new_name
ALTER COLLATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER COLLATION name SET SCHEMA new_schema
描述
ALTER COLLATION更改排序规则的定义。
您必须拥有排序规则才能使用ALTER COLLATION。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须具有对排序规则模式的CREATE权限。(这些限制强制执行更改所有者不会执行通过删除和重新创建排序规则无法执行的任何操作。但是,超级用户可以随意更改任何排序规则的所有权。)
参数
-
name
现有排序规则的名称(可选模式限定符)。 -
new_name
排序规则的新名称。 -
new_owner
排序规则的新所有者。 -
new_schema
排序规则的新模式。 -
REFRESH VERSION
更新排序规则的版本。请参见下面的ALTER COLLATION 注释。
注释
创建排序规则对象时,将在系统目录中记录特定于提供程序的排序规则版本。使用排序规则时,当前版本为检查与记录版本是否匹配,并在不匹配时发出警告,例如:
WARNING: collation "xx-x-icu" has version mismatch
DETAIL: The collation in the database was created using version 1.2.3.4, but the operating system provides version 2.3.4.5.
HINT: Rebuild all objects affected by this collation and run ALTER COLLATION ux_catalog."xx-x-icu" REFRESH VERSION, or build UXsinoDB with the right library version.
排序规则定义的更改可能会导致索引损坏和其他问题,因为数据库系统依赖于存储对象具有特定的排序顺序。通常应避免这种情况,但在合法情况下可能会发生,例如升级操作系统到新的主要版本或使用ux_upgrade升级到与新版本ICU链接的服务器二进制文件。当发生这种情况时,应重建所有依赖于排序规则的对象,例如使用REINDEX。完成后,可以使用命令ALTER COLLATION ... REFRESH VERSION刷新排序规则版本。这将更新系统目录以记录当前排序规则版本,并使警告消失。请注意,这实际上并不检查所有受影响的对象是否已正确重建。
在使用由libc提供的排序规则时,版本信息记录在使用GNU C 库(大多数 Linux 系统)、FreeBSD 和 Windows的系统上。在使用ICU提供的排序规则时,版本信息由ICU库提供,并在所有平台上都可用。
注意
在使用GNU C库进行排序规则时,C库的版本用作排序规则版本的代理。许多Linux发行版仅在升级C库时更改排序规则定义,但这种方法并不完美,因为维护者可以将更新的排序规则定义回溯到旧的C库版本。
在使用Windows进行排序规则时,仅对使用BCP 47语言标记定义的排序规则(例如en-US)提供版本信息。
对于数据库默认排序规则,有一个类似的命令ALTER DATABASE ... REFRESH COLLATION VERSION。
以下查询可用于识别当前数据库中需要刷新的所有排序规则以及依赖于它们的对象:
SELECT ux_describe_object(refclassid, refobjid, refobjsubid) AS "Collation",
ux_describe_object(classid, objid, objsubid) AS "Object"
FROM ux_depend d JOIN ux_collation c
ON refclassid = 'ux_collation'::regclass AND refobjid = c.oid
WHERE c.collversion <> ux_collation_actual_version(c.oid)
ORDER BY 1, 2;
示例
将排序规则de_DE重命名为german:
ALTER COLLATION "de_DE" RENAME TO german;
将排序规则en_US的所有者更改为joe:
ALTER COLLATION "en_US" OWNER TO joe;
兼容性
SQL标准中没有ALTER COLLATION语句。
另请参阅
CREATE COLLATION,DROP COLLATION
ALTER CONVERSION
ALTER CONVERSION — 更改转换的定义
概要
ALTER CONVERSION name RENAME TO new_name
ALTER CONVERSION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER CONVERSION name SET SCHEMA new_schema
描述
ALTER CONVERSION更改转换的定义。
您必须拥有该转换才能使用ALTER CONVERSION。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对转换的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行删除和重新创建转换所不能执行的操作。但是,超级用户可以随意更改任何转换的所有权。)
参数
-
name
现有转换的名称(可选模式限定)。 -
new_name
转换的新名称。 -
new_owner
转换的新所有者。 -
new_schema
转换的新模式。
示例
将转换iso_8859_1_to_utf8重命名为latin1_to_unicode:
ALTER CONVERSION iso_8859_1_to_utf8 RENAME TO latin1_to_unicode;
将转换iso_8859_1_to_utf8的所有者更改为joe:
ALTER CONVERSION iso_8859_1_to_utf8 OWNER TO joe;
兼容性
SQL标准中没有ALTER CONVERSION语句。
另请参阅
CREATE CONVERSION,DROP CONVERSION
ALTER DATABASE
ALTER DATABASE — 更改数据库
概要
ALTER DATABASE name [ [ WITH ] option [ ... ] ]
其中 option 可以是:
ALLOW_CONNECTIONS allowconn
CONNECTION LIMIT connlimit
IS_TEMPLATE istemplate
ALTER DATABASE name RENAME TO new_name
ALTER DATABASE name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER DATABASE name SET TABLESPACE new_tablespace
ALTER DATABASE name REFRESH COLLATION VERSION
ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER DATABASE name SET configuration_parameter FROM CURRENT
ALTER DATABASE name RESET configuration_parameter
ALTER DATABASE name RESET ALL
描述
ALTER DATABASE更改数据库的属性。
第一种形式更改特定的数据库设置。(有关详细信息,请参见下文。)只有数据库所有者或超级用户才能更改这些设置。
第二种形式更改数据库的名称。只有数据库所有者或超级用户才能重命名数据库;非超级用户所有者还必须具有CREATEDB特权。当前数据库不能被重命名。(如果需要执行此操作,请连接到其他数据库。)
第三种形式更改数据库的所有者。要更改所有者,您必须拥有数据库,并且还必须是新拥有角色的直接或间接成员,并且必须具有CREATEDB特权。
第四种形式更改数据库的表空间。只有数据库所有者或超级用户才能更改表空间。
第五种形式刷新数据库的排序规则版本。
第六种形式更改数据库的配置参数。只有数据库所有者或超级用户才能更改配置参数。
ALTER DATABASE不能在事务块中使用。
参数
-
name
要更改属性的数据库的名称。 -
allowconn
如果为false,则无法连接到此数据库。 -
connlimit
可以同时连接到此数据库的并发连接数。-1表示无限制。 -
istemplate
如果为true,则任何具有CREATEDB权限的用户都可以克隆此数据库;如果为false,则只有超级用户或数据库所有者可以克隆它。 -
new_name
数据库的新名称。 -
new_owner
数据库的新所有者。 -
new_tablespace
数据库的新默认表空间。
此命令的此形式无法在事务块内执行。
-
REFRESH COLLATION VERSION
更新数据库排序规则版本。有关背景,请参见ALTER COLLATION中的“注释”。 -
configuration_parameter
value
将此数据库的会话默认值设置为指定配置参数的给定值。如果value为DEFAULT或等效地使用RESET,则会删除数据库特定设置,因此新会话将继承系统范围的默认设置。使用RESET ALL清除所有数据库特定设置。SET FROM CURRENT将会话的当前值保存为数据库特定值。
有关允许的参数名称和值的更多信息,请参见SET。
注释
还可以将会话默认值与特定角色绑定。与其针对数据库,不如针对角色进行设置;请参见ALTER ROLE。如果存在冲突,角色特定设置将覆盖数据库特定设置。
示例
要在数据库test中默认禁用索引扫描:
ALTER DATABASE test SET enable_indexscan TO off;
另请参阅
CREATE DATABASE,DROP DATABASE,SET,CREATE TABLESPACE
ALTER DEFAULT PRIVILEGES
ALTER DEFAULT PRIVILEGES — 定义默认访问权限
概要
ALTER DEFAULT PRIVILEGES
[ FOR { ROLE | USER } target_role [, ...] ]
[ IN SCHEMA schema_name [, ...] ]
abbreviated_grant_or_revoke
其中 abbreviated_grant_or_revoke 是以下之一:
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON TABLES
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON SEQUENCES
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
ON { FUNCTIONS | ROUTINES }
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON TYPES
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] }
ON SCHEMAS
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON TABLES
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON SEQUENCES
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ EXECUTE | ALL [ PRIVILEGES ] }
ON { FUNCTIONS | ROUTINES }
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON TYPES
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | CREATE | ALL [ PRIVILEGES ] }
ON SCHEMAS
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
描述
ALTER DEFAULT PRIVILEGES允许您设置将应用于未来创建的对象的权限。(它不影响已存在对象分配的权限。)目前,只能更改模式、表(包括视图和外部表)、序列、函数和类型(包括域)的权限。对于此命令,函数包括聚合和过程。在此命令中,单词FUNCTIONS和ROUTINES是等效的。(ROUTINES是将函数和过程一起称为标准术语。在早期的UXsinoDB版本中,只允许使用单词FUNCTIONS。无法分别为函数和过程设置默认权限。)
您只能更改由您或您是其成员的角色创建的对象的默认权限。权限可以全局设置(即针对在当前数据库中创建的所有对象),也可以仅针对在指定模式中创建的对象。
任何对象类型的默认权限通常授予对象所有者所有可授权的权限,并可能向PUBLIC授予一些权限。但是,可以通过更改全局默认权限来更改此行为,使用ALTER DEFAULT PRIVILEGES。
针对模式指定的默认权限将添加到特定对象类型的全局默认权限。这意味着如果全局授予了权限(默认情况下或根据以前的ALTER DEFAULT PRIVILEGES命令授予了权限),则无法按模式撤销权限。针对模式的REVOKE仅有助于撤销先前针对模式的GRANT的影响。
参数
-
target_role
现有角色的名称,当前角色是其成员。如果省略FOR ROLE,则假定为当前角色。 -
schema_name
现有模式的名称。如果指定,则将更改稍后在该模式中创建的对象的默认权限。如果省略IN SCHEMA,则更改全局默认权限。在设置模式的权限时,不允许使用IN SCHEMA,因为模式不能嵌套。 -
role_name
授予或撤销权限的现有角色的名称。此参数和abbreviated_grant_or_revoke中的所有其他参数均按照GRANT或REVOKE中所述的方式进行操作,只是一个设置整个对象类别的权限,而不是具体命名的对象。
注释
使用uxsql的\ddp命令获取有关默认权限的现有分配的信息。权限显示的含义与解释为请参见“权限”中的\dp。如果您希望删除已更改默认权限的角色,则需要撤销其默认权限中的更改,或使用DROP OWNED BY来删除角色的默认权限条目。
示例
为所有在模式myschema中随后创建的表(和视图)授予每个人的SELECT权限,并允许角色webuser也进行INSERT:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO PUBLIC;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT INSERT ON TABLES TO webuser;
撤销上述更改,以便随后创建的表不会比正常情况下多具有任何权限:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE SELECT ON TABLES FROM PUBLIC;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE INSERT ON TABLES FROM webuser;
为角色admin随后创建的所有函数删除通常授予的公共EXECUTE权限:
ALTER DEFAULT PRIVILEGES FOR ROLE admin REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
但请注意,您无法通过限制到单个模式的命令来实现该效果。该命令没有效果,除非它正在撤销匹配的GRANT:
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
这是因为每个模式的默认权限只能向全局设置添加权限,而不能删除由其授予的权限。
兼容性
SQL标准中没有ALTER DEFAULT PRIVILEGES语句。
另请参见
ALTER DOMAIN
ALTER DOMAIN — 更改域的定义
概要
ALTER DOMAIN name
{ SET DEFAULT expression | DROP DEFAULT }
ALTER DOMAIN name
{ SET | DROP } NOT NULL
ALTER DOMAIN name
ADD domain_constraint [ NOT VALID ]
ALTER DOMAIN name
DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ]
ALTER DOMAIN name
RENAME CONSTRAINT constraint_name TO new_constraint_name
ALTER DOMAIN name
VALIDATE CONSTRAINT constraint_name
ALTER DOMAIN name
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER DOMAIN name
RENAME TO new_name
ALTER DOMAIN name
SET SCHEMA new_schema
描述
ALTER DOMAIN更改现有域的定义。有几种子形式:
-
SET/DROP DEFAULT
这些形式设置或删除域的默认值。请注意,默认值仅适用于后续的INSERT命令;它们不影响已经使用该域的表中的行。 -
SET/DROP NOT NULL
这些形式更改域是否标记为允许NULL值或拒绝NULL值。只有在使用该域的列不包含null值时,才能SET NOT NULL。 -
ADD domain_constraint[ NOT VALID ]
此形式使用与CREATE DOMAIN相同的语法向域添加新约束。当向域添加新约束时,所有使用该域的列都将根据新添加的约束进行检查。可以通过使用NOT VALID选项添加新约束来抑制这些检查;稍后可以使用ALTER DOMAIN ... VALIDATE CONSTRAINT使约束有效。新插入或更新的行始终会根据所有约束进行检查,即使这些约束标记为NOT VALID也是如此。只有CHECK约束才接受NOT VALID。 -
DROP CONSTRAINT [ IF EXISTS ]
此形式删除域上的约束。如果指定了IF EXISTS并且约束不存在,则不会抛出错误。在这种情况下,会发出通知。 -
RENAME CONSTRAINT
此形式更改域上约束的名称。 -
VALIDATE CONSTRAINT
此形式验证以前添加为NOT VALID的约束,即验证域类型的表列中的所有值是否满足指定的约束。 -
OWNER
此形式将域的所有者更改为指定的用户。 -
RENAME
此形式更改域的名称。 -
SET SCHEMA
此形式更改域的模式。与域相关联的任何约束也将移动到新模式中。
必须拥有该域才能使用ALTER DOMAIN。要更改域的模式,还必须具有新模式的CREATE特权。要更改所有者,您还必须是新拥有角色的直接或间接成员,并且该角色必须具有域模式的CREATE特权。(这些限制强制执行更改所有者不会执行您通过删除和重新创建域无法执行的任何操作。但是,超级用户可以随意更改任何域的所有权。)
参数
-
name
要更改的现有域的名称(可能带有模式)。 -
domain_constraint
域的新约束。 -
constraint_name
要删除或重命名的现有约束的名称。 -
NOT VALID
不验证约束有效性的现有存储数据。 -
CASCADE
自动删除依赖于约束的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果存在任何依赖对象,则拒绝删除约束。这是默认行为。 -
new_name
域的新名称。 -
new_constraint_name
约束的新名称。 -
new_owner
域的新所有者的用户名。 -
new_schema
域的新模式。
注释
尽管ALTER DOMAIN ADD CONSTRAINT尝试验证现有存储的数据是否满足新约束,但这种检查并不是绝对可靠的,因为该命令无法“看到”新插入或更新但尚未提交的表行。如果存在并发操作可能插入错误数据的风险,则应使用NOT VALID选项添加约束,提交该命令,等待在该提交之前启动的所有事务完成,然后发出ALTER DOMAIN VALIDATE CONSTRAINT来搜索违反约束的数据。这种方法是可靠的,因为一旦约束被提交,所有新事务都保证针对域类型的新值执行它。
目前,如果命名域或任何派生域在数据库中的任何表的容器类型列(复合、数组或范围列)中使用,ALTER DOMAIN ADD CONSTRAINT、ALTER DOMAIN VALIDATE CONSTRAINT 和 ALTER DOMAIN SET NOT NULL将失败。它们应该最终改进为能够验证这些嵌套值的新约束。
示例
添加NOT NULL约束到域:
ALTER DOMAIN zipcode SET NOT NULL;
从域中删除NOT NULL约束:
ALTER DOMAIN zipcode DROP NOT NULL;
向域添加检查约束:
ALTER DOMAIN zipcode ADD CONSTRAINT zipchk CHECK (char_length(VALUE) = 5);
从域中删除检查约束:
ALTER DOMAIN zipcode DROP CONSTRAINT zipchk;
重命名域上的检查约束:
ALTER DOMAIN zipcode RENAME CONSTRAINT zipchk TO zip_check;
将域移动到不同的模式中:
ALTER DOMAIN zipcode SET SCHEMA customers;
兼容性
ALTER DOMAIN符合SQL标准,但OWNER、RENAME、SET SCHEMA和VALIDATE CONSTRAINT变体是UXsinoDB扩展。ADD CONSTRAINT变体的NOT VALID子句也是UXsinoDB扩展。
另请参阅
ALTER EVENT TRIGGER
ALTER EVENT TRIGGER — 更改事件触发器的定义
概要
ALTER EVENT TRIGGER name DISABLE
ALTER EVENT TRIGGER name ENABLE [ REPLICA | ALWAYS ]
ALTER EVENT TRIGGER name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER EVENT TRIGGER name RENAME TO new_name
描述
ALTER EVENT TRIGGER更改现有事件触发器的属性。
您必须是超级用户才能更改事件触发器。
参数
-
name
要更改的现有触发器的名称。 -
new_owner
事件触发器的新所有者的用户名。 -
new_name
事件触发器的新名称。 -
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER
这些形式配置事件触发器的触发。禁用的触发器仍然为系统所知,但在其触发事件发生时不会执行。
兼容性
SQL标准中没有ALTER EVENT TRIGGER语句。
另请参阅
CREATE EVENT TRIGGER,DROP EVENT TRIGGER
ALTER EXTENSION
ALTER EXTENSION — 更改扩展的定义
概要
ALTER EXTENSION name UPDATE [ TO new_version ]
ALTER EXTENSION name SET SCHEMA new_schema
ALTER EXTENSION name ADD member_object
ALTER EXTENSION name DROP member_object
其中 member_object 是:
ACCESS METHOD object_name |
AGGREGATE aggregate_name ( aggregate_signature ) |
CAST (source_type AS target_type) |
COLLATION object_name |
CONVERSION object_name |
DOMAIN object_name |
EVENT TRIGGER object_name |
FOREIGN DATA WRAPPER object_name |
FOREIGN TABLE object_name |
FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
MATERIALIZED VIEW object_name |
OPERATOR operator_name (left_type, right_type) |
OPERATOR CLASS object_name USING index_method |
OPERATOR FAMILY object_name USING index_method |
[ PROCEDURAL ] LANGUAGE object_name |PROCEDURE procedure_name [([ [argmode] [argname] argtype[,...]])] |
ROUTINE routine_name [([ [argmode] [argname] argtype[,...]])] |
SCHEMA object_name |
SEQUENCE object_name |
SERVER object_name |
TABLE object_name |
TEXT SEARCH CONFIGURATION object_name |
TEXT SEARCH DICTIONARY object_name |
TEXT SEARCH PARSER object_name |
TEXT SEARCH TEMPLATE object_name |
TRANSFORM FOR type_name LANGUAGE lang_name |
TYPE object_name |
VIEW object_name
并且aggregate_signature是:
* |
[argmode] [argname] argtype[,...] |
[[argmode] [argname] argtype[,...]] ORDER BY [argmode] [argname] argtype[,...]
描述
ALTER EXTENSION改变已安装扩展的定义。有几个子形式:
-
UPDATE
此形式将扩展更新为新版本。扩展必须提供适当的更新脚本(或一系列脚本),可以将当前安装的版本修改为请求的版本。 -
SET SCHEMA
此形式将扩展的对象移动到另一个模式中。扩展必须是可重定位的才能成功执行此命令。 -
ADD member_object
此形式将现有对象添加到扩展中。这在扩展更新脚本中非常有用。随后,该对象将被视为扩展的成员;特别是,只能通过删除扩展来删除它。 -
DROP member_object
此形式从扩展中删除成员对象。这在扩展更新脚本中非常有用。该对象不会被删除,只是与扩展解除关联。
您必须拥有该扩展才能使用ALTER EXTENSION。ADD/DROP形式还需要拥有添加/删除对象的所有权。
参数
-
name
已安装扩展的名称。 -
new_version
扩展的期望新版本。可以写成标识符或字符串字面量。如果未指定,则ALTER EXTENSION UPDATE尝试更新为扩展控制文件中显示的默认版本。 -
new_schema
扩展的新模式。 -
object_name
aggregate_name
function_name
operator_name
procedure_name
routine_name
要添加到或从扩展中删除的对象的名称。可以为表、聚合、域、外部表、函数、运算符、运算符类、运算符族、过程、例程、序列、文本搜索对象、类型和视图的名称加上模式。 -
source_type
转换的源数据类型的名称。 -
target_type
转换的目标数据类型的名称。 -
argmode
函数、过程或聚合参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。请注意,ALTER EXTENSION实际上不会关注OUT参数,因为只需要输入参数即可确定函数的标识。因此,列出IN、INOUT和VARIADIC参数即可。 -
argname
函数、过程或聚合参数的名称。请注意,ALTER EXTENSION实际上不会关注参数名称,因为只需要参数数据类型即可确定函数的标识。 -
argtype
函数、过程或聚合参数的数据类型。 -
left_type
right_type
运算符参数的数据类型(可选模式)。对于前缀运算符的缺失参数,请写NONE。 -
PROCEDURAL
这是一个噪声词。 -
type_name
转换的数据类型的名称。 -
lang_name
转换的语言的名称。
示例
将hstore扩展更新到版本2.0:
ALTER EXTENSION hstore UPDATE TO '2.0';
将hstore扩展的模式更改为utils:
ALTER EXTENSION hstore SET SCHEMA utils;
要将现有函数添加到hstore扩展名中:
ALTER EXTENSION hstore ADD FUNCTION populate_record(anyelement, hstore);
兼容性
ALTER EXTENSION是UXsinoDB扩展。
另请参阅
CREATE EXTENSION,DROP EXTENSION
ALTER FOREIGN DATA WRAPPER
ALTER FOREIGN DATA WRAPPER — 更改外部数据封装器的定义
概述
ALTER FOREIGN DATA WRAPPER name
[ HANDLER handler_function | NO HANDLER ]
[ VALIDATOR validator_function | NO VALIDATOR ]
[ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ]
ALTER FOREIGN DATA WRAPPER name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER FOREIGN DATA WRAPPER name RENAME TO new_name
描述
ALTER FOREIGN DATA WRAPPER更改外部数据封装器的定义。命令的第一种形式更改外部数据封装器的支持函数或通用选项(至少需要一个子句)。第二种形式更改外部数据封装器的所有者。
只有超级用户可以更改外部数据封装器。此外,只有超级用户可以拥有外部数据封装器。
参数
-
name
现有外部数据封装器的名称。 -
HANDLER handler_function
为外部数据封装器指定新的处理程序函数。 -
NO HANDLER
用于指定外部数据封装器不再具有处理程序函数。
请注意,使用没有处理程序的外部数据封装器的外部表无法访问。
VALIDATOR validator_function
为外部数据封装器指定新的验证器函数。
请注意,外部数据封装器的预先存在的选项可能会受到影响。
-
NO VALIDATOR
用于指定外部数据封装器不再具有验证器函数。 -
OPTIONS ( [ ADD | SET | DROP ] option['value'] [, ...])
为外部数据封装器指定新的选项。可以使用ADD、SET或DROP子句添加、设置或删除选项。 -
OWNER TO { new_owner| CURRENT_ROLE | CURRENT_USER | SESSION_USER }
将外部数据封装器的所有权转移给新所有者、当前角色、当前用户或会话用户。 -
RENAME TO new_name
将外部数据封装器重命名为新名称。 -
new_owner
外部数据包装器的新所有者的用户名。 -
new_name
外部数据包装器的新名称。
示例
更改外部数据包装器dbi,添加选项foo,删除bar:
ALTER FOREIGN DATA WRAPPER dbi OPTIONS (ADD foo '1',DROP 'bar');
更改外部数据包装器dbi的验证器为bob.myvalidator:
ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator;
兼容性
ALTER FOREIGN DATA WRAPPER符合ISO/IEC 9075-9(SQL/MED)标准,但HANDLER、VALIDATOR、OWNER TO和RENAME子句是扩展功能。
参见
CREATE FOREIGN DATA WRAPPER,DROP FOREIGN DATA WRAPPER
ALTER FOREIGN TABLE
ALTER FOREIGN TABLE — 更改外部表的定义
概要
ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]
ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
RENAME [ COLUMN ] column_name TO new_column_name
ALTER FOREIGN TABLE [ IF EXISTS ] name
RENAME TO new_name
ALTER FOREIGN TABLE [ IF EXISTS ] name
SET SCHEMA new_schema
其中 action 是以下之一:
ADD [ COLUMN ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ]
ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
ALTER [ COLUMN ] column_name SET STATISTICS integer
ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
ALTER [ COLUMN ] column_name OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ])
ADD table_constraint [ NOT VALID ]
VALIDATE CONSTRAINT constraint_name
DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ]
DISABLE TRIGGER [ trigger_name | ALL | USER ]
ENABLE TRIGGER [ trigger_name | ALL | USER ]
ENABLE REPLICA TRIGGER trigger_name
ENABLE ALWAYS TRIGGER trigger_name
SET WITHOUT OIDS
INHERIT parent_table
NO INHERIT parent_table
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ])
描述
ALTER FOREIGN TABLE用于更改现有外部表的定义。有几种子形式:
-
ADD COLUMN
此形式向外部表添加新列,使用与CREATE FOREIGN TABLE相同的语法。与向常规表添加列的情况不同,底层存储不会发生任何变化:此操作仅声明现在可以通过外部表访问某些新列。 -
DROP COLUMN [ IF EXISTS ]
此形式从外部表中删除列。如果表外有任何依赖于该列的内容,则需要使用CASCADE;例如,视图。如果指定了IF EXISTS并且该列不存在,则不会抛出错误。在这种情况下,会发出通知。 -
SET DATA TYPE
此形式更改外部表的列的类型。同样,这对任何底层存储没有影响:此操作仅更改UXsinoDB认为该列具有的类型。 -
SET/DROP DEFAULT
这些形式为列设置或删除默认值。默认值仅适用于后续的INSERT或UPDATE命令;它们不会导致表中已有的行发生更改。 -
SET/DROP NOT NULL
将列标记为允许或不允许空值。 -
SET STATISTICS
此形式设置后续ANALYZE操作的每列统计信息收集目标。有关详细信息,请参见ALTER TABLE的类似形式。 -
SET ( attribute_option = value [, ... ] )RESET ( attribute_option [, ... ] )
此形式设置或重置每个属性选项。查看ALTER TABLE的类似形式以获取更多详细信息。 -
SET STORAGE
此形式设置列的存储模式。查看ALTER TABLE的类似形式以获取更多详细信息。请注意,存储模式没有任何效果,除非表的外部数据包装器选择关注它。 -
ADD table_constraint [ NOT VALID ]
此形式使用与CREATE FOREIGN TABLE相同的语法向外部表添加新约束。目前仅支持CHECK约束。
与向常规表添加约束的情况不同,不会执行任何操作来验证约束是否正确;相反,此操作仅声明应假定某些新条件适用于外部表中的所有行。(请参见CREATE FOREIGN TABLE中的讨论。)如果将约束标记为NOT VALID,则不会假定其成立,而仅记录可能将来使用的约束。
-
VALIDATE CONSTRAINT
此形式将先前标记为NOT VALID的约束标记为有效。不会执行任何操作来验证约束,但是将来的查询将假定它成立。 -
DROP CONSTRAINT [ IF EXISTS ]
此形式删除外部表上指定的约束。如果指定了IF EXISTS并且约束不存在,则不会抛出错误。在这种情况下,会发出通知。 -
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER
这些形式配置属于外部表的触发器的触发。有关更多详细信息,请参见ALTER TABLE的类似形式。 -
SET WITHOUT OIDS
用于删除oid系统列的向后兼容性语法。由于无法再添加oid系统列,因此这永远不会产生影响。 -
INHERIT parent_table
此形式将目标外部表作为指定父表的新子项添加。查看ALTER TABLE的类似形式以获取更多详细信息。 -
NO INHERIT parent_table
此形式将目标外部表从指定父表的子项列表中删除。 -
OWNER
此形式将外部表的所有者更改为指定的用户。 -
OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] )
更改外部表或其某个列的选项。ADD、SET和DROP如果未明确指定操作,则默认为ADD。不允许重复的选项名称(尽管表选项和列选项可以具有相同的名称)。选项名称和值也使用外部数据包装库进行验证。 -
RENAME
表单更改外部表的名称或外部表中单个列的名称。 -
SET SCHEMA
此表单将外部表移动到另一个模式中。
除RENAME和SET SCHEMA之外的所有操作都可以组合成要并行应用的多个更改列表。例如,可以在单个命令中添加多个列或更改多个列的类型。
如果命令写为ALTER FOREIGN TABLE IF EXISTS ...,并且外部表不存在,则不会引发错误。在这种情况下发出通知。
您必须拥有表才能使用ALTER FOREIGN TABLE。要更改外部表的模式,您还必须对新模式具有CREATE特权。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对表的模式具有CREATE特权。(这些限制强制执行更改所有者不会执行您通过删除和重新创建表无法执行的任何操作。但是,超级用户可以更改任何表的所有权。)要添加列或更改列类型,您还必须对数据类型具有USAGE特权。
参数
-
name
要更改的现有外部表的名称(可能带有模式)。如果在表名之前指定了ONLY,则仅更改该表。如果未指定ONLY,则更改表及其所有后代表(如果有)。可以在表名后面显式指定*,以明确指示包括后代表。 -
column_name
新列或现有列的名称。 -
new_column_name
现有列的新名称。 -
new_name
表的新名称。 -
data_type
新列的数据类型,或现有列的新数据类型。 -
table_constraint
外部表的新表约束。 -
constraint_name
要删除的现有约束的名称。 -
CASCADE
自动删除依赖于删除的列或约束的对象(例如,引用该列的视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果存在任何依赖对象,则拒绝删除列或约束。这是默认行为。 -
trigger_name
要禁用或启用的单个触发器的名称。 -
ALL
禁用或启用属于外部表的所有触发器。(如果任何触发器是内部生成的触发器,则需要超级用户权限。核心系统不会将此类触发器添加到外部表中,但是附加代码可以这样做。) -
USER
禁用或启用属于外部表的所有触发器,但不包括内部生成的触发器。 -
parent_table
要与此外部表关联或取消关联的父表。 -
new_owner
表的新所有者的用户名。 -
new_schema
要将表移动到的模式的名称。
注释
关键字COLUMN是噪音,可以省略。
使用ADD COLUMN或DROP COLUMN添加或删除列,添加NOT NULL或CHECK约束,或使用SET DATA TYPE更改列类型时,不会检查与外部服务器的一致性。用户有责任确保表定义与远程端匹配。
有关有效参数的进一步说明,请参见CREATE FOREIGN TABLE。
示例
将列标记为非空:
ALTER FOREIGN TABLE distributors ALTER COLUMN street SET NOT NULL;
更改外部表的选项:
ALTER FOREIGN TABLE myschema.distributors OPTIONS (ADD opt1 'value', SET opt2 'value2', DROP opt3 'value3');
兼容性
ADD,DROP和SET DATA TYPE的形式符合SQL标准。其他形式是SQL的UXsinoDB扩展。此外,在单个ALTER FOREIGN TABLE命令中指定多个操作的能力是一种扩展。
ALTER FOREIGN TABLE DROP COLUMN可用于删除外部表的唯一列,从而留下一个零列表。这是SQL的扩展,它不允许零列外部表。
另请参阅
CREATE FOREIGN TABLE, DROP FOREIGN TABLE
ALTER FUNCTION
ALTER FUNCTION — 更改函数的定义
概要
ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
action [ ... ] [ RESTRICT ]
ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
RENAME TO new_name
ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
SET SCHEMA new_schema
ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
[ NO ] DEPENDS ON EXTENSION extension_name
其中 action 是以下之一:
CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
IMMUTABLE | STABLE | VOLATILE
[ NOT ] LEAKPROOF
[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
PARALLEL { UNSAFE | RESTRICTED | SAFE }
COST execution_cost
ROWS result_rows
SUPPORT support_function
SET configuration_parameter { TO | = } { value | DEFAULT }
SET configuration_parameter FROM CURRENT
RESET configuration_parameter
RESET ALL
描述
ALTER FUNCTION更改函数的定义。
您必须拥有该函数才能使用ALTER FUNCTION。要更改函数的模式,您还必须在新模式上拥有CREATE权限。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须在函数模式上拥有CREATE权限。(这些限制强制执行更改所有者不会执行您通过删除和重新创建函数无法执行的任何操作。但是,超级用户可以随意更改任何函数的所有权。)
参数
-
name
现有函数的名称(可选模式限定)。如果未指定参数列表,则名称必须在其模式中是唯一的。 -
argmode
参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。请注意,ALTER FUNCTION实际上不会注意到OUT参数,因为只需要输入参数即可确定函数的标识。因此,列出IN、INOUT和VARIADIC参数就足够了。 -
argname
参数的名称。请注意,ALTER FUNCTION实际上不会注意到参数名称,因为只需要参数数据类型即可确定函数的标识。 -
argtype
函数参数的数据类型(可选模式限定),如果有的话。 -
new_name
函数的新名称。 -
new_owner
函数的新所有者。请注意,如果函数标记为SECURITY DEFINER,则它将随后作为新所有者执行。 -
new_schema
函数的新模式。 -
DEPENDS ON EXTENSION extension_name
NO DEPENDS ON EXTENSION extension_name
此形式将函数标记为依赖于扩展,或者如果指定了NO,则不再依赖于该扩展。标记为依赖于扩展的函数在扩展被删除时被删除,即使未指定CASCADE。函数可以依赖于多个扩展,并且将在删除其中任何一个扩展时被删除。 -
CALLED ON NULL INPUT
RETURNS NULL ON NULL INPUT
STRICT
CALLED ON NULL INPUT更改函数,使其在某些或所有参数为空时被调用。RETURNS NULL ON NULL INPUT或STRICT更改函数,使其不会在任何参数为空时被调用。 如果函数的任何参数为空,则会自动假定为空结果,而不会引发错误。有关详细信息,请参见CREATE FUNCTION。 -
IMMUTABLE
STABLE
VOLATILE
更改函数的不稳定性设置。有关详细信息,请参见CREATE FUNCTION。 -
[ EXTERNAL ] SECURITY INVOKER
[ EXTERNAL ] SECURITY DEFINER
更改函数是否为安全定义者。关键字EXTERNAL在SQL符合性中被忽略。有关此功能的更多信息,请参见CREATE FUNCTION。 -
PARALLEL
更改函数是否被认为是安全的并行执行。有关详细信息,请参见CREATE FUNCTION。 -
LEAKPROOF
更改函数是否被认为是不可泄漏的。有关此功能的更多信息,请参见CREATE FUNCTION。 -
COSTexecution_cost
更改函数的预估执行成本。有关详细信息,请参见CREATE FUNCTION。 -
ROWSresult_rows
更改集合返回函数返回的预估行数。有关详细信息,请参见CREATE FUNCTION。 -
SUPPORTsupport_function
设置或更改此函数使用的规划器支持函数。您必须是超级用户才能使用此选项。此选项不能用于完全删除支持函数,因为它必须命名一个新的支持函数。如果需要这样做,请使用CREATE OR REPLACE FUNCTION。 -
configuration_parameter
value
在调用函数时添加或更改要对配置参数进行的赋值。如果value为DEFAULT或等效地使用RESET,则会删除函数本地设置,以便函数使用其环境中存在的值执行。使用RESET ALL清除所有函数本地设置。SET FROM CURRENT将当前ALTER FUNCTION执行时的参数值保存为进入函数时要应用的值。有关允许的参数名称和值的更多信息,请参见SET。 -
RESTRICT
为符合SQL标准而被忽略。
示例
将类型为integer的函数sqrt重命名为square_root:
ALTER FUNCTION sqrt(integer) RENAME TO square_root;
将类型为integer的函数sqrt的所有者更改为joe:
ALTER FUNCTION sqrt(integer) OWNER TO joe;
将类型为integer的函数sqrt的模式更改为maths:
ALTER FUNCTION sqrt(integer) SET SCHEMA maths;
将类型为integer的函数sqrt标记为依赖于扩展mathlib:
ALTER FUNCTION sqrt(integer) DEPENDS ON EXTENSION mathlib;
调整自动设置的函数搜索路径:
ALTER FUNCTION check_password(text) SET search_path = admin, ux_temp;
禁用函数的自动设置search_path:
ALTER FUNCTION check_password(text) RESET search_path;
函数现在将使用其调用者使用的任何搜索路径执行。
兼容性
此语句部分与SQL标准中的ALTER FUNCTION语句兼容。标准允许修改函数的更多属性,但不提供将函数重命名、使函数成为安全定义者、附加配置参数值到函数或更改函数的所有者、模式或不稳定性的能力。标准还要求使用RESTRICT关键字,该关键字在UXsinoDB中是可选的。
另请参阅
CREATE FUNCTION、DROP FUNCTION、ALTER PROCEDURE、ALTER ROUTINE
ALTER GROUP
ALTER GROUP — 更改角色名称或成员资格
概要
ALTER GROUP role_specification ADD USER user_name [, ... ]
ALTER GROUP role_specification DROP USER user_name [, ... ]
其中 role_specification 可以是:
role_name
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
ALTER GROUP group_name RENAME TO new_name
描述
ALTER GROUP 更改用户组的属性。这是一个已过时的命令,尽管仍然被接受以实现向后兼容性,因为组(以及用户)已被更一般的角色概念所取代。
前两个变体将用户添加到组或从组中删除它们。(任何角色都可以扮演“用户”或“组”的角色。)这些变体实际上等同于授予或撤销在命名为“组”的角色中的成员资格;因此,最好使用GRANT或REVOKE来执行此操作。
第三个变体更改组的名称。这与使用ALTER ROLE重命名角色完全相同。
参数
-
group_name
要修改的组(角色)的名称。 -
user_name
要添加到或从组中删除的用户(角色)。用户必须已经存在;ALTER GROUP不会创建或删除用户。 -
new_name
组的新名称。
示例
将用户添加到组:
ALTER GROUP staff ADD USER karl, john;
从组中删除用户:
ALTER GROUP workers DROP USER beth;
兼容性
SQL标准中没有ALTER GROUP语句。
另请参阅
ALTER INDEX
ALTER INDEX — 更改索引的定义
概要
ALTER INDEX [ IF EXISTS ] name RENAME TO new_name
ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name
ALTER INDEX name ATTACH PARTITION index_name
ALTER INDEX name [ NO ] DEPENDS ON EXTENSION extension_name
ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter [= value] [, ... ] )
ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] )
ALTER INDEX [ IF EXISTS ] name ALTER [ COLUMN ] column_number
SET STATISTICS integer
ALTER INDEX ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
SET TABLESPACE new_tablespace [ NOWAIT ]
描述
ALTER INDEX 更改现有索引的定义。下面描述了几种子形式。请注意,每个子形式所需的锁级别可能不同。除非明确说明,否则将持有ACCESS EXCLUSIVE 锁。当列出多个子命令时,所持有的锁将是从任何子命令所需的最严格的锁。
RENAME
RENAME形式更改索引的名称。如果索引与表约束(UNIQUE、PRIMARY KEY或EXCLUDE)相关联,则约束也将被重命名。对存储的数据没有影响。
重命名索引会获取 SHARE UPDATE EXCLUSIVE 锁。
-
SET TABLESPACE
此形式将索引的表空间更改为指定的表空间,并将与索引关联的数据文件移动到新表空间中。要更改索引的表空间,必须拥有该索引并在新表空间上具有CREATE特权。可以使用ALL INTABLESPACE形式移动当前数据库中表空间中的所有索引,该形式将锁定要移动的所有索引,然后移动每个索引。此形式还支持OWNED BY,它只会移动由指定角色拥有的索引。如果指定了NOWAIT选项,则如果无法立即获取所需的所有锁,则命令将失败。请注意,此命令不会移动系统目录,如果需要,请改用ALTER DATABASE或显式ALTER INDEX调用。另请参见CREATE TABLESPACE。 -
ATTACH PARTITION
使指定的索引附加到更改的索引。指定的索引必须在包含要更改的索引的表的分区上,并具有等效的定义。附加的索引不能单独删除,并且如果其父索引被删除,则将自动删除它。 -
DEPENDS ON EXTENSION extension_name
NO DEPENDS ON EXTENSION extension_name
此形式将索引标记为依赖于扩展,或者如果指定了NO,则不再依赖于该扩展。标记为依赖于扩展的索引在扩展被删除时会自动删除。 -
SET ( storage_parameter[=value] [, ... ] )
此形式更改一个或多个索引方法特定的存储参数。有关可用参数的详细信息,请参见CREATE INDEX。请注意,此命令不会立即修改索引内容;根据参数,您可能需要使用REINDEX重建索引以获得所需的效果。 -
RESET ( storage_parameter[, ... ] )
此形式将一个或多个索引方法特定的存储参数重置为其默认值。与SET一样,可能需要使用REINDEX来完全更新索引。 -
ALTER [ COLUMN ] column_number SET STATISTICSinteger
此形式为随后的ANALYZE操作设置每列统计信息收集目标,但只能用于定义为表达式的索引列。由于表达式缺少唯一名称,因此我们使用索引列的序数来引用它们。目标可以设置在0到10000的范围内;或者,将其设置为-1以恢复使用系统默认统计信息目标(default_statistics_target)。
参数
-
IF EXISTS
如果索引不存在,则不会引发错误。在这种情况下会发出通知。 -
column_number
序数号指的是索引列的序数(从左到右)位置。 -
name
要更改的现有索引的名称(可能带模式限定)。 -
new_name
索引的新名称。 -
tablespace_name
索引将移动到的表空间。 -
extension_name
索引要依赖的扩展名。 -
storage_parameter
索引方法特定存储参数的名称。 -
value
索引方法特定存储参数的新值。这可能是一个数字或一个单词,具体取决于参数。
注意事项
这些操作也可以使用ALTER TABLE。实际上,ALTER INDEX只是适用于索引的ALTER TABLE形式的别名。
以前有一个ALTER INDEX OWNER变体,但现在已被忽略(带有警告)。索引的所有者不能与其表的所有者不同。更改表的所有者会自动更改索引。
不允许更改系统目录索引的任何部分。
示例
要重命名现有索引:
ALTER INDEX distributors RENAME TO suppliers;
将索引移动到不同的表空间:
ALTER INDEX distributors SET TABLESPACE fasttablespace;
更改索引的填充因子(假设索引方法支持它):
ALTER INDEX distributors SET (fillfactor = 75);
REINDEX INDEX distributors;
设置表达式索引的统计信息收集目标:
CREATE INDEX coord_idx ON measured (x, y, (z + t));
ALTER INDEX coord_idx ALTER COLUMN 3 SET STATISTICS 1000;
兼容性
ALTER INDEX是UXsinoDB的扩展。
另请参阅
ALTER LANGUAGE
ALTER LANGUAGE — 更改过程语言的定义
概要
ALTER [ PROCEDURAL ] LANGUAGE name RENAME TO new_name
ALTER [ PROCEDURAL ] LANGUAGE name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
描述
ALTER LANGUAGE更改过程语言的定义。唯一的功能是重命名语言或分配一个新的所有者。要使用ALTER Language,您必须是该语言的超级用户或所有者。
参数
-
name
语言的名称 -
new_name
语言的新名称。 -
new_owner
语言的所有者。
兼容性
SQL 标准中没有ALTER LANGUAGE语句。
另请参阅
ALTER LARGE OBJECT
ALTER LARGE OBJECT —更改大对象的定义
概要
ALTER LARGE OBJECT large_object_oid OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
描述
ALTER LARGE OBJECT更改大对象的定义。
您必须拥有该大对象才能使用ALTER LARGE OBJECT。要更改所有者,您还必须是新所有角色的直接或间接成员。(但是,超级用户可以随意更改任何大对象。)目前,唯一的功能是分配新所有者,因此两个限制始终适用。
参数
-
large_object_oid
要更改的大对象的 OID -
new_owner
大对象的新所有者
兼容性
SQL 标准中没有 ALTER LARGE OBJECT 语句。
ALTER MATERIALIZED VIEW
ALTER MATERIALIZED VIEW — 更改物化视图的定义
概要
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
action [, ... ]
ALTER MATERIALIZED VIEW name
[ NO ] DEPENDS ON EXTENSION extension_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
RENAME [ COLUMN ] column_name TO new_column_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
RENAME TO new_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
SET SCHEMA new_schema
ALTER MATERIALIZED VIEW ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
SET TABLESPACE new_tablespace [ NOWAIT ]
其中 action 是以下之一:
ALTER [ COLUMN ] column_name SET STATISTICS integer
ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
CLUSTER ON index_name
SET WITHOUT CLUSTER
SET ACCESS METHOD new_access_method
SET TABLESPACE new_tablespace
SET ( storage_parameter [= value] [, ... ] )
RESET(storage_parameter [, ...])
OWNER TO {new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER}
描述
ALTER MATERIALIZED VIEW更改现有物化视图的各种辅助属性。
您必须拥有物化视图才能使用ALTER MATERIALIZED VIEW。要更改物化视图的模式,您还必须在新模式上具有CREATE特权。要更改所有者,您还必须是新拥有角色的直接或间接成员,并且该角色必须在物化视图的模式上具有CREATE特权。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建物化视图执行的任何操作。但是,超级用户可以更改任何视图的所有权。)
ALTER MATERIALIZED VIEW可用的语句子形式和操作是ALTER TABLE可用的子形式和操作的子集,并且在用于物化视图时具有相同的含义。有关详细信息,请参见ALTER TABLE的描述。
参数
-
name
现有物化视图的名称(可选模式限定)。 -
column_name
新列的名称或现有列的名称。 -
extension_name
物化视图要依赖的扩展名(如果指定了NO,则不再依赖)。标记为依赖于扩展名的物化视图在删除扩展名时会自动删除。 -
new_column_name
现有列的新名称。 -
new_owner
物化视图的新所有者的用户名。 -
new_name
物化视图的新名称。 -
new_schema
物化视图的新模式。
示例
将物化视图foo重命名为bar:
ALTER MATERIALIZED VIEW foo RENAME TO bar;
兼容性
ALTER MATERIALIZED VIEW是UXsinoDB的扩展。
另请参阅
CREATE MATERIALIZED VIEW、DROP MATERIALIZED VIEW、REFRESH MATERIALIZED VIEW
ALTER OPERATOR
ALTER OPERATOR — 更改运算符的定义
概要
ALTER OPERATOR name ( { left_type | NONE } , right_type )
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER OPERATOR name ( { left_type | NONE } , right_type )
SET SCHEMA new_schema
ALTER OPERATOR name ( { left_type | NONE } , right_type )
SET ( { RESTRICT = { res_proc | NONE }
|JOIN = { join_proc | NONE }
} [, ... ] )
描述
ALTER OPERATOR更改运算符的定义。
您必须拥有该运算符才能使用ALTER OPERATOR。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对运算符的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建运算符来执行的任何操作。但是,超级用户可以随意更改任何运算符的所有权。)
参数
-
name
现有运算符的名称(可选模式限定)。 -
left_type
运算符左操作数的数据类型;如果运算符没有左操作数,则写入NONE。 -
right_type
运算符右操作数的数据类型。 -
new_owner
运算符的新所有者。 -
new_schema
操作符的新模式。 -
res_proc
此操作符的限制选择性估计函数;写入NONE以删除现有的选择性估计器。 -
join_proc
此操作符的连接选择性估计函数;写入NONE以删除现有的选择性估计器。
示例
更改类型为text的自定义操作符a @@ b的所有者:
ALTER OPERATOR @@ (text, text) OWNER TO joe;
更改类型为int[]的自定义操作符a && b的限制和连接选择性估计函数:
ALTER OPERATOR && (_int4, _int4) SET (RESTRICT = _int_contsel, JOIN = _int_contjoinsel);
兼容性
SQL标准中没有ALTER OPERATOR语句。
另请参阅
ALTER OPERATOR CLASS
ALTER OPERATOR CLASS — 更改操作符类的定义
概要
ALTER OPERATOR CLASS name USING index_method
RENAME TO new_name
ALTER OPERATOR CLASS name USING index_method
O WNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER OPERATOR CLASS name USING index_method
SET SCHEMA new_schema
描述
ALTER OPERATOR CLASS 更改操作符类的定义。
您必须拥有操作符类才能使用ALTER OPERATOR CLASS。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须在操作符类的模式上具有CREATE权限。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建操作符类来执行的任何操作。但是,超级用户可以更改任何操作符类的所有权。)
参数
-
name
现有操作符类的名称(可选模式限定)。 -
index_method
此操作符类所用的索引方法的名称。 -
new_name
操作符类的新名称。 -
new_owner
操作符类的新所有者。 -
new_schema
操作符类的新模式。
兼容性
SQL 标准中没有 ALTER OPERATOR CLASS 语句。
另请参阅
CREATE OPERATOR CLASS、DROPOPERATOR CLASS、ALTER OPERATOR FAMILY
ALTER OPERATOR FAMILY
ALTER OPERATOR FAMILY — 更改操作符族的定义
概要
ALTER OPERATOR FAMILY name USING index_method ADD
{ OPERATOR strategy_number operator_name ( op_type, op_type )
[ FOR SEARCH | FOR ORDER BY sort_family_name ]
| FUNCTION support_number [ ( op_type [ , op_type ] ) ]
function_name [ ( argument_type [, ...] ) ]
} [, ... ]
ALTER OPERATOR FAMILY name USING index_method DROP
{ OPERATOR strategy_number ( op_type [ , op_type ] )
| FUNCTION support_number ( op_type [ , op_type ] )
} [, ... ]
ALTER OPERATOR FAMILY name USING index_method
RENAME TO new_name
ALTER OPERATOR FAMILY name USING index_method
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER OPERATOR FAMILY name USING index_method
SET SCHEMA new_schema
描述
ALTER OPERATOR FAMILY更改操作符族的定义。您可以向该族添加操作符和支持函数,从该族中删除它们,或更改该族的名称或所有者。
ALTER OPERATOR FAMILY,它们不是家族内任何特定操作符类的一部分,而只是在家族内“松散”的。这表示这些操作符和函数与家族的语义兼容,但不是任何特定索引的正确功能所必需的。(这样必需的操作符和函数应该作为操作符类的一部分声明,参见CREATE OPERATOR CLASS)。UXsinoDB允许随时从家族中删除松散成员,但不能删除操作符类的成员,否则将导致整个类和依赖于它的任何索引一起被删除。通常,单数据类型的操作符和函数是操作符类的一部分,因为它们需要支持特定数据类型的索引,而跨数据类型的操作符和函数则成为家族的松散成员。
您必须是超级用户才能使用ALTER OPERATOR FAMILY。(这个限制是因为错误的操作符家族定义可能会混淆甚至崩溃服务器。)
ALTER OPERATOR FAMILY目前不检查操作符家族定义是否包括索引方法所需的所有操作符和函数,也不检查操作符和函数是否形成自洽集合。用户有责任定义一个有效的操作符家族。
参数
-
name
现有操作符家族的名称(可选模式限定符)。 -
index_method
此操作符家族所用的索引方法的名称。 -
strategy_number
与操作符家族相关联的操作符的索引方法策略编号。 -
operator_name
与操作符家族相关联的操作符的名称(可选模式限定符)。 -
op_type
在OPERATOR子句中,操作符的操作数数据类型,或NONE表示前缀操作符。与CREATE OPERATOR CLASS中的可比语法不同,操作数数据类型必须始终指定。
在ADD FUNCTION子句中,如果函数的操作数数据类型与函数的输入数据类型不同,则指定函数要支持的操作数数据类型。对于B树比较函数和哈希函数,不需要指定op_type,因为函数的输入数据类型始终是正确的。对于B树排序支持函数、B-Tree等效图像函数以及GiST、SP-GiST和GIN操作符类中的所有函数,必须指定函数要使用的操作数数据类型。
在DROP FUNCTION子句中,必须指定函数要支持的操作数数据类型。
sort_family_name
描述与排序操作符相关联的排序顺序的现有btree操作符家族的名称(可选模式限定符)。
如果未指定FOR SEARCH或FOR ORDER BY,则FOR SEARCH是默认值。
-
support_number
与运算符族相关联的函数的索引方法支持函数号。 -
function_name
运算符族的索引方法支持函数的名称(可选模式限定)。如果未指定参数列表,则名称必须在其模式中唯一。 -
argument_type
函数的参数数据类型。 -
new_name
运算符族的新名称。 -
new_owner
运算符族的新所有者。 -
new_schema
运算符族的新模式。
OPERATOR和FUNCTION子句可以以任何顺序出现。
注释
请注意,DROP语法仅指定运算符族中的“slot”,即策略或支持号和输入数据类型。未提及占用槽的运算符或函数的名称。此外,对于DROP FUNCTION,要指定的类型是函数旨在支持的输入数据类型;对于GiST、SP-GiST和GIN索引,这可能与函数的实际输入参数类型无关。
因为索引机制在使用函数之前不检查访问权限,所以在运算符族中包含函数或运算符等同于授予公共执行权限。这通常不是运算符族中有用的函数类型的问题。
不应使用SQL函数定义运算符。SQL函数可能会被内联到调用查询中,这将防止优化器识别查询与索引匹配。
在UXsinoDB之前版本中,OPERATOR子句可以包括RECHECK选项。这不再受支持,因为现在在运行时动态确定索引运算符是否有损失。这允许有效处理可能有损失或可能没有损失的运算符的情况。
示例
以下示例命令将跨数据类型的运算符和支持函数添加到已包含数据类型int4和int2的B-tree运算符类的运算符族中。
ALTER OPERATOR FAMILY integer_ops USING btree ADD
-- int4 vs int2
OPERATOR 1 < (int4, int2) ,
OPERATOR 2 <= (int4, int2) ,
OPERATOR 3 = (int4, int2) ,
OPERATOR 4 >= (int4, int2) ,
OPERATOR 5 > (int4, int2) ,
FUNCTION 1 btint42cmp(int4, int2) ,
-- int2 vs int4
OPERATOR 1 < (int2, int4) ,
OPERATOR 2 <= (int2, int4) ,
OPERATOR 3 = (int2, int4) ,
OPERATOR 4 >= (int2, int4) ,
OPERATOR 5 > (int2, int4) ,
FUNCTION 1 btint24cmp(int2, int4) ;
要再次删除这些条目:
ALTER OPERATOR FAMILY integer_ops USING btree DROP
-- int4 vs int2
OPERATOR 1 (int4, int2) ,
OPERATOR 2 (int4, int2) ,
OPERATOR 3 (int4, int2) ,
OPERATOR 4 (int4, int2) ,
OPERATOR 5 (int4, int2) ,
FUNCTION 1 (int4, int2) ,
-- int2 vs int4
OPERATOR 1 (int2, int4),
OPERATOR 2 (int2, int4),
OPERATOR 3 (int2, int4),
OPERATOR 4 (int2, int4),
OPERATOR 5 (int2, int4),
FUNCTION 1 (int2, int4);
兼容性
SQL 标准中没有 ALTER OPERATOR FAMILY语句。
另请参阅
CREATE OPERATOR FAMILY、DROP OPERATOR FAMILY、CREATE OPERATOR CLASS、ALTER OPERATOR CLASS、DROPOPERATOR CLASS
ALTER POLICY
ALTER POLICY — 更改行级安全策略的定义
概要
ALTER POLICY name ON table_name RENAME TO new_name
ALTER POLICY name ON table_name
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]
描述
ALTER POLICY更改现有行级安全策略的定义。请注意,ALTER POLICY仅允许修改策略适用的角色集和USING和WITH CHECK表达式。要更改策略的其他属性,例如适用的命令或是它是宽容的还是严格的,必须删除并重新创建策略。
要使用 ALTER POLICY,必须拥有策略适用的表。
在 ALTER POLICY的第二种形式中,如果指定了角色列表、using_expression和check_expression,则它们将独立替换。当省略其中一个子句时,策略的相应部分不会改变。
参数
-
name
要更改的现有策略的名称。 -
table_name
策略所在的表的名称(可选架构限定符)。 -
new_name
策略的新名称。 -
role_name
策略适用的角色。可以有多个角色。指定在一定时间内应用策略。要将策略应用于所有角色,请使用PUBLIC。 -
using_expression
策略的USING表达式。有关详细信息,请参见CREATE POLICY。 -
check_expression
策略的WITH CHECK表达式。有关详细信息,请参见CREATE POLICY。
兼容性
ALTER POLICY是UXsinoDB的扩展。
另请参阅
ALTER PROCEDURE
ALTER PROCEDURE — 更改存储过程的定义
概要
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
action [ ... ] [ RESTRICT ]
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
RENAME TO new_name
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
SET SCHEMA new_schema
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
[ NO ] DEPENDS ON EXTENSION extension_name
其中 action 是以下之一:
[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
SET configuration_parameter { TO | = } { value | DEFAULT }
SET configuration_parameter FROM CURRENT
RESET configuration_parameter
RESET ALL
描述
ALTER PROCEDURE更改存储过程的定义。
您必须拥有该存储过程才能使用ALTER PROCEDURE。要更改过程的模式,您还必须对新模式具有CREATE权限。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对过程的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行任何您无法通过删除和重新创建过程来执行的操作。但是,超级用户可以随意更改任何过程的所有权。)
参数
-
name
现有过程的名称(可选模式限定)。如果未指定参数列表,则名称必须在其模式中唯一。 -
argmode
参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。 -
argname
参数的名称。请注意,ALTER PROCEDURE实际上不会注意参数名称,因为只使用参数数据类型来确定过程的标识。 -
argtype
过程的参数的数据类型(可选模式限定),如果有的话。有关使用参数数据类型查找过程的详细信息,请参见DROP PROCEDURE。 -
new_name
过程的新名称。 -
new_owner
过程的新所有者。请注意,如果将过程标记为SECURITY DEFINER,则随后将以新所有者身份执行。 -
new_schema
过程的新模式。 -
extension_name
此形式将过程标记为依赖于扩展,或者如果指定了NO,则不再依赖于扩展。标记为依赖于扩展的过程在删除扩展时被删除,即使未指定级联也是如此。过程可以依赖于多个扩展,并且将在任何一个扩展被删除时被删除。 -
[ EXTERNAL ] SECURITY INVOKER
[ EXTERNAL ] SECURITY DEFINER
更改过程是否为安全定义者。关键字EXTERNAL在SQL符合性方面被忽略。有关此功能的更多信息,请参见CREATE PROCEDURE。 -
configuration_parameter
value
在调用过程时添加或更改要分配给配置参数的值。如果value为DEFAULT或等效地使用RESET,则会删除过程本地设置,以便过程使用值执行在其环境中存在的存储过程。使用RESET ALL清除所有过程本地设置。SET FROM CURRENT将当前参数的值保存为在进入过程时应用的值。ALTER PROCEDURE执行时。
有关允许的参数名称和值的更多信息,请参见SET。
RESTRICT
为符合SQL标准而被忽略。
示例
将具有两个integer类型参数的存储过程insert_data重命名为insert_record:
ALTER PROCEDURE insert_data(integer, integer) RENAME TO insert_record;
将具有两个integer类型参数的存储过程insert_data的所有者更改为joe:
ALTER PROCEDURE insert_data(integer, integer) OWNER TO joe;
将具有两个integer类型参数的存储过程insert_data的模式更改为accounting:
ALTER PROCEDURE insert_data(integer, integer) SET SCHEMA accounting;
将存储过程insert_data(integer,integer)标记为依赖于扩展名为myext的扩展:
ALTER PROCEDURE insert_data(integer, integer) DEPENDS ON EXTENSION myext;
调整自动设置的存储过程的搜索路径:
ALTER PROCEDURE check_password(text) SET search_path = admin, ux_temp;
禁用存储过程的自动设置search_path:
ALTER PROCEDURE check_password(text) RESET search_path;
该过程现在将使用其调用者使用的任何搜索路径执行。
兼容性
此语句部分与SQL标准中的ALTER PROCEDURE语句兼容。标准允许修改过程的更多属性,但不提供将过程重命名、使过程成为安全定义者、将配置参数值附加到过程或更改过程的所有者、模式或易失性的能力。标准还要求使用RESTRICT关键字,该关键字在UXsinoDB中是可选的。
另请参阅
CREATE PROCEDURE,DROP PROCEDURE,ALTER FUNCTION,ALTER ROUTINE
ALTER PUBLICATION
ALTER PUBLICATION — 更改发布的定义
概要
ALTER PUBLICATION name ADD publication_object [, ...]
ALTER PUBLICATION name SET publication_object [, ...]
ALTER PUBLICATION name DROP publication_object [, ...]
ALTER PUBLICATION name SET ( publication_parameter [= value] [, ... ] )
ALTER PUBLICATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER PUBLICATION name RENAME TO new_name
其中 publication_object 是以下之一:
TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [ WHERE ( expression ) ] [, ... ]
TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
描述
ALTER PUBLICATION命令可以更改发布的属性。
前三个变体更改发布中包含的表/模式。SET子句将使用指定的列表替换发布中的表/模式列表;存在于发布中的现有表/模式将被删除。ADD和DROP子句将添加和删除一个或多个表/模式。请注意,向已订阅的发布中添加表/模式将需要在订阅方执行ALTER SUBSCRIPTION ... REFRESH PUBLICATION 操作才能生效。还要注意,DROP TABLES IN SCHEMA不会删除使用FOR TABLE/ADD TABLE,以及将DROP与WHERE子句组合使用是不允许的。
命令概要中列出的第四个变体可以更改在CREATE PUBLICATION中指定的所有出版属性。未在命令中提到的属性保留其先前的设置。
其余的变体更改出版物的所有者和名称。
您必须拥有出版物才能使用ALTER PUBLICATION。将表添加到出版物还需要拥有该表。向出版物添加ADD TABLES IN SCHEMA和SET TABLES IN SCHEMA需要调用用户是超级用户。要更改所有者,您还必须是新所有角色的直接或间接成员。新所有者必须在数据库上具有CREATE特权。此外,FOR ALL TABLES或FOR TABLES IN SCHEMA出版物的新所有者必须是超级用户。但是,超级用户可以更改出版物的所有权,而不受这些限制的影响。
不支持在出版物还发布具有列列表的表以及反之的情况下添加/设置任何模式。
参数
-
name
要更改其定义的现有出版物的名称。 -
table_name
现有表的名称。如果在表名之前指定了ONLY,则仅影响该表。如果未指定ONLY,则该表及其所有后代表(如果有)都将受到影响。可以在表名后面选择性地指定*,以明确表示包括后代表。
可以选择指定列列表。有关详细信息,请参见CREATE PUBLICATION。请注意,订阅在其中已使用不同列列表发布了相同表的多个出版物不受支持。
如果指定了可选的WHERE子句,则不会发布expression计算为false或null的行。请注意,需要在表达式周围使用括号。使用用于复制连接的角色评估expression。
-
schema_name
现有模式的名称。 -
SET ( publication_parameter[=value] [, ... ] )
此子句更改最初由CREATE PUBLICATION设置的出版物参数。 -
new_owner
出版物的新所有者的用户名。 -
new_name
出版物的新名称。
示例
将发布更改为仅发布删除和更新:
ALTER PUBLICATION noinsert SET (publish = 'update, delete');
将一些表添加到发布中:
ALTER PUBLICATION mypublication ADD TABLE users (user_id, firstname), departments;
更改表的已发布列集:
ALTER PUBLICATION mypublication SET TABLE users (user_id, firstname, lastname), TABLE departments;
将模式marketing和 sales添加到发布sales_publication中:
ALTER PUBLICATION sales_publication ADD TABLES IN SCHEMA marketing, sales;
将表users, departments和模式 production添加到发布production_publication中:
ALTER PUBLICATION production_publication ADD TABLE users, departments, TABLES IN SCHEMA production;
兼容性
ALTER PUBLICATION是UXsinoDB的扩展。
另请参阅
CREATE PUBLICATION,DROP PUBLICATION,CREATE SUBSCRIPTION,ALTER SUBSCRIPTION
ALTER ROLE
ALTER ROLE — 更改数据库角色
概要
ALTER ROLE role_specification [ WITH ] option [ ... ]
其中 option 可以是:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
| ROLE VALID UNTIL 'timestamp'
ALTER ROLE name RENAME TO new_name
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL
其中 role_specification 可以是:
role_name
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
描述
ALTER ROLE更改一个UXsinoDB角色的属性。
概要中列出的第一种变体可以更改可以在 CREATE ROLE中指定的许多角色属性。(所有可能的属性都被涵盖了,除了没有添加或删除成员的选项外,其他设置保持不变。可以使用GRANT和REVOKE来进行添加或删除成员的操作。数据库超级用户可以更改任何角色的任何设置。具有CREATEROLE特权的角色可以更改任何非超级用户和非复制角色的设置,但只能更改非超级用户和非复制角色的设置,不能更改SUPERUSER、REPLICATION和BYPASSRLS的设置。普通角色只能更改自己的密码。
第二种变体更改角色的名称。数据库超级用户可以重命名任何角色。具有CREATEROLE特权的角色可以重命名非超级用户角色。当前会话用户无法重命名,如果需要重命名,请使用不同的用户连接。因为MD5加密的密码使用角色名称作为加密盐,重命名角色会清除其密码,如果密码是MD5加密的。
其余变体更改角色的配置变量的会话默认值,可以是所有数据库,也可以是指定的数据库。如果使用ALL代替角色名称,则会更改所有角色的设置。在指定IN DATABASE子句时使用ALL实际上与使用命令ALTER DATABASE ... SET...相同。
每当角色随后启动新会话时,指定的值成为会话默认值,覆盖uxsinodb.conf中存在的任何设置或从uxdb命令行接收到的设置。这仅在登录时发生;执行SET ROLE或SET SESSION AUTHORIZATION不会导致设置新的配置值。为所有数据库设置的设置被附加到角色的特定数据库设置覆盖。特定数据库或特定角色的设置会覆盖所有角色的设置。
超级用户可以更改任何人的会话默认值。具有CREATEROLE特权的角色可以更改非超级用户角色的默认值。普通角色只能为自己设置默认值。某些配置变量无法以这种方式设置,或者只能在超级用户发出命令时设置。只有超级用户可以更改所有数据库中所有角色的设置。
参数
-
name
要更改其属性的角色的名称。 -
CURRENT_ROLE
CURRENT_USER
更改当前用户而不是明确标识的角色。 -
SESSION_USER
更改当前会话用户而不是明确标识的角色。 -
SUPERUSERNOSUPERUSER
CREATEDB
NOCREATEDB
CREATEROLE
NOCREATEROLE
INHERIT
NOINHERIT
LOGIN
NOLOGIN
REPLICATION
NOREPLICATION
BYPASSRLS
NOBYPASSRLS
CONNECTION LIMITconnlimit
[ENCRYPTED]PASSWORD'password'PASSWORD NULL
VALID UNTIL'timestamp'
这些子句会更改最初由CREATE ROLE 设置的属性。有关更多信息,请参见CREATEROLE参考页面。 -
new_name
角色的新名称。 -
database_name
应设置配置变量的数据库的名称。 -
configuration_parameter
value
将此角色的会话默认值设置为指定配置参数的给定值。如果value为DEFAULT或等效地使用RESET,则会删除角色特定的变量设置,因此角色将在新会话中继承系统范围的默认设置。使用RESET ALL来清除所有角色特定的设置。SET FROM CURRENT将会话的当前值保存为角色特定值。如果指定了IN DATABASE,则仅为给定的角色和数据库设置或删除配置参数。
角色特定的变量设置仅在登录时生效;SET ROLE 和SET SESSION AUTHORIZATION不会处理角色特定的变量设置。
有关允许的参数名称和值的更多信息,请参见SET。
注意事项
使用CREATE ROLE添加新角色,使用DROP ROLE删除角色。
ALTER ROLE无法更改角色的成员身份。使用GRANT和REVOKE来实现。
在使用此命令指定未加密密码时必须小心。密码将以明文形式传输到服务器,并且可能会在客户端的命令历史记录或服务器日志中记录。uxsql包含一个命令\password,可用于更改角色的密码而不暴露明文密码。
还可以将会话默认值绑定到特定数据库而不是角色;请参见ALTER DATABASE。如果存在冲突,则数据库角色特定设置会覆盖角色特定设置,后者又会覆盖数据库特定设置。
示例
更改角色的密码:
ALTER ROLE davide WITH PASSWORD 'hu8jmn3';
删除角色的密码:
ALTER ROLE davide WITH PASSWORD NULL;
更改密码过期日期,指定密码应在2015年5月4日中午过期,使用比UTC提前一小时的时区:
ALTER ROLE chris VALID UNTIL 'May 4 12:00:00 2015 +1';
使密码永久有效:
ALTER ROLE fred VALID UNTIL 'infinity';
授予角色创建其他角色和新数据库的权限:
ALTER ROLE miriam CREATEROLE CREATEDB;
为角色设置非默认的maintenance_work_mem参数:
ALTER ROLE worker_bee SET maintenance_work_mem = 100000;
为角色设置非默认的、特定于数据库的client_min_messages参数:
ALTER ROLE fred IN DATABASE devel SET client_min_messages = DEBUG;
兼容性
ALTER ROLE语句是UXsinoDB的扩展。
另请参阅
CREATE ROLE 、DROP ROLE 、ALTER DATABASE 、SET
ALTER ROUTINE
ALTER ROUTINE — 更改例程的定义
概要
ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
action [ ... ] [ RESTRICT ]
ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
RENAME TO new_name
ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
SET SCHEMA new_schema
ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
[ NO ] DEPENDS ON EXTENSION extension_name
其中 action 是以下之一:
IMMUTABLE | STABLE | VOLATILE
[ NOT ] LEAKPROOF
[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
PARALLEL { UNSAFE | RESTRICTED | SAFE }
COST execution_cost
ROWS result_rows
SET configuration_parameter { TO | = } { value | DEFAULT }
SET configuration_parameter FROM CURRENT
RESET configuration_parameter
RESET ALL
描述
ALTER ROUTINE更改例程的定义,其中可以是聚合函数、普通函数或过程。有关参数、更多示例和详细信息,请参见ALTER AGGREGATE、ALTER FUNCTION和ALTER PROCEDURE下的说明。
示例
将类型为integer的例程foo重命名为foobar:
ALTER ROUTINE foo(integer) RENAME TO foobar;
无论foo是聚合函数、函数还是过程,此命令都可以正常工作。
兼容性
此语句与SQL标准中的ALTER ROUTINE语句部分兼容。有关详细信息,请参见ALTER FUNCTION和ALTER PROCEDURE。允许例程名称引用聚合函数是UXsinoDB的扩展。
另请参阅
ALTER AGGREGATE、ALTER FUNCTION、ALTER PROCEDURE、DROP ROUTINE
请注意,没有CREATE ROUTINE命令。
ALTER RULE
ALTER RULE — 更改规则的定义
概要
ALTER RULE name ON table_name RENAME TO new_name
描述
ALTER RULE更改现有规则的属性。目前,唯一可用的操作是更改规则的名称。
要使用ALTER RULE,您必须拥有规则适用的表或视图。
参数
-
name
要更改的现有规则的名称。 -
table_name
规则适用的表或视图的名称(可选模式限定)。 -
new_name
规则的新名称。
示例
要重命名现有规则:
ALTER RULE notify_all ON emp RENAME TO notify_me;
兼容性
ALTER RULE是UXsinoDB语言扩展,整个查询重写系统也是如此。
另请参阅
ALTER SCHEMA
ALTER SCHEMA — 更改模式的定义
概要
ALTER SCHEMA name RENAME TO new_name
ALTER SCHEMA name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
描述
ALTER SCHEMA更改模式的定义。
您必须拥有该模式才能使用ALTER SCHEMA。要重命名模式,您还必须具有数据库的CREATE权限。要更改所有者,您还必须是新所有角色的直接或间接成员,并且您必须具有数据库的CREATE权限。(请注意,超级用户自动拥有所有这些权限。)
参数
-
name现有模式的名称。 -
new_name模式的新名称。新名称不能以ux_开头,因为这些名称为系统模式保留。 -
new_owner模式的新所有者。
兼容性
SQL标准中没有ALTER SCHEMA语句。
另请参阅
ALTER SEQUENCE
ALTER SEQUENCE — 更改序列生成器的定义
概要
ALTER SEQUENCE [ IF EXISTS ] name
[ AS data_type ]
[ INCREMENT [ BY ] increment ]
[ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
[ START [ WITH ] start ]
[ RESTART [ [ WITH ] restart ] ]
[ CACHE cache | NOCACHE ] [ [ NO ] CYCLE | NOCYCLE ]
[ ORDER | NOORDER ]
[ KEEP | NOKEEP ][ SESSION | GLOBAL ]
[ OWNED BY { table_name.column_name | NONE } ]
ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_name
ALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema
描述
ALTER SEQUENCE更改现有序列生成器的参数。在ALTER SEQUENCE命令中未明确设置的任何参数都保留其先前的设置。
您必须拥有该序列才能使用ALTER SEQUENCE。要更改序列的模式,您还必须在新模式上具有CREATE权限。要更改所有者,您还必须是新所有者的直接或间接成员,并且该角色必须在序列的模式上具有CREATE权限。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建序列来执行的任何操作。但是,超级用户可以更改任何序列的所有权。)
参数
-
name
要更改的序列的名称(可选模式限定符)。 -
IF EXISTS
如果序列不存在,则不会引发错误。在这种情况下会发出通知。 -
data_type
可选的子句AS data_type更改序列的数据类型。有效类型是smallint、integer和bigint。
如果先前的最小值和最大值是旧数据类型的最小值或最大值(换句话说,如果使用NO MINVALUE或NO MAXVALUE(隐式或显式)创建序列),则更改数据类型会自动更改序列的最小值和最大值。否则,将保留最小值和最大值,除非在同一命令的一部分中给出新值。如果最小值和最大值不适合新数据类型,则会生成错误。
-
increment
子句INCREMENT BY increment是可选的。正值将创建升序序列,负值将创建降序序列。如果未指定,则将保留旧的增量值。 -
minvalue
NO MINVALUE
可选的子句MINVALUE minvalue确定序列可以生成的最小值。如果指定了NO MINVALUE,则将使用默认值1和升序和降序序列的数据类型的最小值。如果没有指定任何选项,将保留当前最小值。 -
maxvalue
NO MAXVALUE
可选的子句MAXVALUE maxvalue确定序列的最大值。如果指定了NO MAXVALUE,则将使用数据类型的最大值和-1作为升序和降序序列的默认值。如果没有指定任何选项,将保留当前最大值。 -
start
可选的子句START WITH start更改序列的记录起始值。这对当前序列值没有影响;它只是设置了未来的ALTER SEQUENCE RESTART命令将使用的值。 -
restart
可选的子句RESTART[WITH restart]更改序列的当前值。这类似于使用is_called=false调用setval函数:指定的值将由下一个调用nextval返回。使用没有restart值的RESTART等同于提供 由CREATE SEQUENCE记录的起始值或由ALTER SEQUENCE START WITH最后设置的值。与setval调用不同,序列上的RESTART操作是事务性的,并阻止并发事务从同一序列获取数字。如果这不是所需的操作模式,则应使用setval。 -
CACHEcache
NOCACHE
子句CACHE cache允许预分配序列号并将其存储在内存中以加快访问速度。最小值为1(一次只能生成一个值,即无缓存)。如果未指定,则将保留旧缓存值。
NOCACHE相当于缓存值为1,不会预先在内存里面存放序列,可以避免数据库不正常关闭造成的序列丢失。
CYCLE
NO CYCLE
NOCYCLE
CYCLE选项允许在升序或降序序列达到maxvalue或minvalue时,序列回绕。当升序序列达到最大值时,它会生成最小值minvalue。当降序序列达到最小值时,它会生成最大值maxvalue。
如果指定了NO CYCLE,则序列达到其最大值后调用nextval将返回错误。如果既未指定CYCLE也未指定NO CYCLE,则NO CYCLE是默认值。
使用NOCYCLE来指定序列在达到最大或最小值后不能再生成更多的值。这是默认行为。
ORDER
NOORDER
使用ORDER来保证序列号按照请求的顺序生成。如果你将序列号用作时间戳,这个选项非常有用。对于用于生成主键的序列,保证顺序通常不重要。
使用NOORDER来表示不保证序列号按照请求的顺序生成。这是默认行为。
KEEP
NOKEEP
Oracle用来更改序列的保留属性,当值为KEEP时,他的值在回滚时或撤销时不会被重置。通常用于需要保留连续序列值的特定业务需求。
当值为NOKEEP时,他的值会在回滚或撤销时重置。
SESSION
GLOBAL
SESSION:当序列对象的缓存级别设置为SESSION时,每个会话(session)都会有自己的序列缓存。每个会话在访问序列是都会使用自己的缓存值,不会影响其他会话的缓存。意味着不同会话之间的序列值是独立的,互不干扰的。Uxdb默认是这种模式。
GLOBAL:当序列对象的缓存级别设置为GLOBAL时,所有会话共享同一个序列缓存。多个会话在访问序列时会共享同一个序列缓存值。意味着不同会话之间的序列值是共享的,可能会出现序列值的竞争和冲突。
-
SET { LOGGED | UNLOGGED }
此形式将序列从未记录更改为已记录或反之亦然(请参见CREATE SEQUENCE)。它不能应用于临时序列。 -
OWNED BYtable_name.column_nameOWNED BY NONE
OWNED BY选项使序列与特定表列相关联,因此如果删除该列(或其整个表),则序列也将自动删除。如果指定了此关联,则此关联将替换序列的任何先前指定的关联。指定的表必须与序列具有相同的所有者并且位于相同的模式中。指定OWNED BY NONE将删除任何现有关联,使序列成为“独立的”。 -
new_owner
序列的新所有者的用户名。 -
new_name
序列的新名称。 -
new_schema
序列的新模式。
注意事项
ALTER SEQUENCE不会立即影响除当前后端以外的其他后端中的nextval结果,这些后端已预分配(缓存)序列值。它们将在注意到更改的序列生成参数之前使用完所有缓存的值。当前后端将立即受到影响。
ALTER SEQUENCE不会影响序列的currval状态。
ALTER SEQUENCE阻止并发事务从序列中获取数字,直到修改完成。因此,如果需要在事务中修改序列,则应在事务开始时锁定序列。
并发使用 nextval、currval、lastval和setval调用。
由于历史原因,ALTER TABLE也可以用于序列;但是,允许与序列一起使用的ALTER TABLE变体仅等同于上面显示的形式。
示例
重新启动名为serial的序列,从105开始:
ALTER SEQUENCE serial RESTART WITH 105;
兼容性
ALTER SEQUENCE符合SQL标准,但是AS、START WITH、OWNED BY、OWNER TO、RENAME TO和SET SCHEMA子句是UXsinoDB的扩展。
另请参阅
ALTER SERVER
ALTER SERVER — 更改外部服务器的定义
概要
ALTER SERVER name [ VERSION 'new_version' ]
[ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) ]
ALTER SERVER name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER SERVER name RENAME TO new_name
描述
ALTER SERVER更改外部服务器的定义。第一种形式更改服务器版本字符串或服务器的通用选项(至少需要一个子句)。第二种形式更改服务器的所有者。
要更改服务器,您必须是服务器的所有者。此外,要更改所有者,您必须拥有服务器,并且还必须是新所有角色的直接或间接成员,并且必须在服务器的外部数据包装器上具有USAGE权限。(请注意,超级用户自动满足所有这些条件。)
参数
-
name
现有服务器的名称。 -
new_version
新服务器版本。 -
OPTIONS ( [ ADD | SET | DROP ] option['value'] [, ... ])
更改服务器的选项。ADD、SET和DROP指定要执行的操作。ADD假定如果没有明确指定操作。选项名称必须是唯一的;名称和值也使用服务器的外部数据包装器库进行验证。 -
new_owner
外部服务器的新所有者的用户名。 -
new_name
新的外部服务器名称。
示例
修改服务器 foo,添加连接选项:
ALTER SERVER foo OPTIONS (host 'foo',dbname 'foodb');
修改服务器 foo,更改版本,更改 host 选项:
ALTER SERVER foo VERSION '8.4' OPTIONS (SET host 'baz');
兼容性
ALTER SERVER符合ISO/IEC 9075-9 (SQL/MED)。OWNER TO和RENAME表单是UXsinoDB的扩展。
参见
ALTER STATISTICS
ALTER STATISTICS —更改扩展统计对象的定义
概要
ALTER STATISTICS name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER STATISTICS name RENAME TO new_name
ALTER STATISTICS name SET SCHEMA new_schema
ALTER STATISTICS name SET STATISTICS new_target
描述
ALTER STATISTICS更改现有扩展统计对象的参数。在ALTER STATISTICS命令中未明确设置的任何参数都保留其先前的设置。
您必须拥有统计对象才能使用ALTER STATISTICS。要更改统计对象的模式,您还必须对新模式具有CREATE权限。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对统计对象的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行您通过删除和重新创建统计对象无法执行的任何操作。但是,超级用户可以更改任何统计对象的所有权。)
参数
-
name
要更改的统计对象的名称(可选模式限定)。 -
new_owner
统计对象的新所有者的用户名。 -
new_name
统计对象的新名称。 -
new_schema
统计对象的新模式。 -
new_target
此统计对象的统计收集目标,用于后续ANALYZE操作。目标可以设置在0到10000的范围内;或者将其设置为-1,以使用引用列的统计目标的最大值(如果设置),或系统默认统计目标(default_statistics_target)。
兼容性
SQL标准中没有ALTER STATISTICS命令。
另请参阅
CREATE STATISTICS,DROP STATISTICS
ALTER SUBSCRIPTION
ALTER SUBSCRIPTION — 更改订阅的定义
概要
ALTER SUBSCRIPTION name CONNECTION 'conninfo'
ALTER SUBSCRIPTION name SET PUBLICATION publication_name [, ...] [ WITH ( publication_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name ADD PUBLICATION publication_name [, ...] [ WITH ( publication_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name DROP PUBLICATION publication_name [, ...] [ WITH ( publication_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name ENABLE
ALTER SUBSCRIPTION name DISABLE
ALTER SUBSCRIPTION name SET ( subscription_parameter [= value] [, ... ] )
ALTER SUBSCRIPTION name SKIP ( skip_option = value )
ALTER SUBSCRIPTION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER SUBSCRIPTION name RENAME TO new_name
描述
ALTER SUBSCRIPTION可以更改大多数订阅属性,这些属性可以在CREATE SUBSCRIPTION中指定。
您必须拥有订阅才能使用ALTER SUBSCRIPTION。要更改所有者,您还必须是新所有者角色的直接或间接成员。新所有者必须是超级用户。(目前,所有订阅所有者都必须是超级用户,因此实际上将绕过所有者检查。但这可能会在将来更改。)
在刷新发布时,我们会删除不再属于发布的关系,并且如果有任何表同步插槽,我们也会删除它们。必须删除这些插槽,以释放远程主机上为订阅分配的资源。如果由于网络故障或其他错误UXsinoDB无法删除插槽,则会报告错误。在这种情况下,用户需要重试操作或按照DROP SUBSCRIPTION中所述将插槽与订阅分离并删除订阅。
命令 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 和 ALTER SUBSCRIPTION... {SET|ADD|DROP} PUBLICATION ...,其中refresh选项为true,不能在事务块内执行。
除非copy_data为false,否则在启用two_phase提交的情况下,也无法执行这些命令。请参见ux_subscription的subtwophasestate列以了解实际的两阶段状态。
参数
-
name
要更改其属性的订阅的名称。 -
CONNECTION 'conninfo'
此子句替换最初由CREATE SUBSCRIPTION设置的连接字符串。 -
SET PUBLICATION publication_name
ADD PUBLICATION publication_name
DROP PUBLICATION publication_name
这些形式更改已订阅的发布列表。SET用新列表替换整个发布列表,ADD将其他发布添加到发布列表中,DROP从发布列表中删除发布。我们允许在ADD和SET变体中指定不存在的发布,以便用户稍后添加这些发布。有关更多信息,请参见CREATE SUBSCRIPTION。默认情况下,此命令还将像REFRESH PUBLICATION一样运行。
publication_option 指定此操作的其他选项。支持的选项包括:
refresh (boolean)
当为false时,该命令将不尝试刷新表信息。REFRESH PUBLICATION然后应该单独执行。默认值为true。
此外,可以指定在REFRESH PUBLICATION下描述的选项,以控制隐式刷新操作。
REFRESH PUBLICATION
从发布者获取缺失的表信息。这将启动对自上次CREATE SUBSCRIPTION或上次调用REFRESH PUBLICATION以来添加到订阅出版物的表的复制。
refresh_option
指定刷新操作的其他选项。支持的选项包括:
copy_data (boolean)
指定在复制开始时是否复制正在订阅的出版物中的预先存在的数据。默认值为true。
即使自上次订阅以来表的行过滤器WHERE子句已被修改,也不会复制以前订阅的表。
-
ENABLE
启用先前禁用的订阅,从事务结束时开始逻辑复制工作进程。 -
DISABLE
禁用正在运行的订阅,从事务结束时停止逻辑复制工作进程。 -
SET ( subscription_parameter[=value] [, ... ] )
此子句更改最初由CREATE SUBSCRIPTION设置的参数。有关更多信息,请参见该处。可以更改的参数包括slot_name、synchronous_commit、binary、streaming 和disable_on_error。
SKIP(skip_option=value)
跳过应用远程事务的所有更改。如果传入数据违反任何约束,则逻辑复制将停止,直到解决为止。通过使用ALTER SUBSCRIPTION... SKIP命令,逻辑复制工作进程将跳过事务中的所有数据修改更改。此选项对已启用订阅者上的two_phase的事务没有影响。逻辑复制工作进程成功跳过事务或完成事务后,LSN(存储在ux_subscription.subskiplsn中)将被清除。
skip_option 指定此操作的选项。支持的选项为:
lsn (ux_lsn)
指定要跳过逻辑复制工作进程的更改的远程事务的完成LSN。完成LSN是事务提交或准备的LSN。不支持跳过单个子事务。在订阅者上启用two_phase后,此选项不会对已准备的事务产生影响。NONE重置LSN。
-
new_owner
订阅的新所有者的用户名。 -
new_name
订阅的新名称。
示例
将订阅的发布更改为insert_only:
ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only;
禁用(停止)订阅:
ALTER SUBSCRIPTION mysub DISABLE;
兼容性
ALTER SUBSCRIPTION是UXsinoDB的扩展。
另请参阅
CREATE SUBSCRIPTION、DROP SUBSCRIPTION、CREATE PUBLICATION、ALTER PUBLICATION
ALTER SYSTEM
ALTER SYSTEM —更改服务器配置参数
概要
ALTER SYSTEM SET configuration_parameter { TO | = } { value | 'value' | DEFAULT }
ALTER SYSTEM RESET configuration_parameter
ALTER SYSTEM RESET ALL
描述
ALTER SYSTEM用于在整个数据库集群中更改服务器配置参数。它比传统的手动编辑uxsinodb.conf文件更方便。ALTER SYSTEM将给定的参数设置写入uxsinodb.auto.conf文件中,该文件除了读取uxsinodb.conf文件外还会读取该文件。将参数设置为DEFAULT,或使用RESET变体,将从uxsinodb.auto.conf文件中删除该配置条目。使用RESET ALL删除所有这样的配置条目。
使用 ALTER SYSTEM设置的值将在下一次服务器配置重新加载后生效,或在只能在服务器启动时更改的参数的情况下,在下一次服务器重启后生效。可以通过调用SQL函数ux_reload_conf()、运行ux_ctl reload或向主服务器进程发送SIGHUP信号来命令服务器配置重新加载。
只有超级用户和被授予参数的ALTER SYSTEM权限的用户才能使用ALTER SYSTEM更改它。此外,由于此命令直接作用于文件系统且无法回滚,因此不允许在事务块或函数内部使用。
参数
-
configuration_parameter
可设置配置参数的名称。 -
value
参数的新值。对于特定的参数,可以将值指定为字符串常量、标识符、数字或逗号分隔的这些值的列表。可以写入DEFAULT以从uxsinodb.auto.conf中删除参数及其值。
注释
此命令不能用于设置data_directory,也不能用于不允许在uxsinodb.conf中的参数(例如,preset options)。
示例
设置wal_level:
ALTER SYSTEM SET wal_level = replica;
撤消该设置,恢复在uxsinodb.conf中生效的任何设置:
ALTER SYSTEM RESET wal_level;
兼容性
ALTER SYSTEM语句是UXsinoDB的扩展。
另请参阅
ALTER TABLE
ALTER TABLE — 更改表的定义
概要
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
RENAME [ COLUMN ] column_name TO new_column_name
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
RENAME CONSTRAINT constraint_name TO new_constraint_name
ALTER TABLE [ IF EXISTS ] name
RENAME TO new_name
ALTER TABLE [ IF EXISTS ] name
SET SCHEMA new_schema
ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
SET TABLESPACE new_tablespace [ NOWAIT ]
ALTER TABLE [ IF EXISTS ] name
ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }
ALTER TABLE [ IF EXISTS ] name
DETACH PARTITION partition_name
其中 action 是以下之一:
ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ ENCRYPTED [ { SALT | NO SALT } [ MAC | NO MAC ] ] ] [ COLLATE collation ] [ column_constraint [ ... ] ]
DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ ENCRYPTED [ { SALT | NO SALT } [ MAC | NO MAC ] ] ] [ COLLATE collation ] [ USING expression ]
ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ DECRYPTED ] [ COLLATE collation ] [ USING expression ]
ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
ALTER [ COLUMN ] column_name ENCRYPTED [ { SALT | NO SALT } [ MAC | NO MAC ] ]
ALTER [ COLUMN ] column_name DECRYPTED
ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
ALTER [ COLUMN ] column_name COMMENT comment_info
ALTER [ COLUMN ] column_name SET STATISTICS integer
ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
COMMENT comment_info [,...]
CHANGE [ COLUMN ] column_name new_column_name data_type [ NULL | NOT NULL ] [ DEFAULT default_expr ] [ UNIQUE | PRIMARY KEY ] [ ON UPDATE update_time_expr ] [ COMMENT comment_info ] [ ENCRYPTED ]
MODIFY [ COLUMN ] column_name COMMENT comment_info
ADD table_constraint [ NOT VALID ]
ADD table_constraint_using_index
ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
VALIDATE CONSTRAINT constraint_name
{ DISABLE | ENABLE } [ VALIDATE | NOVALIDATE ] CONSTRAINT constraint_name
DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ]
DISABLE TRIGGER [ trigger_name | ALL | USER ]
ENABLE TRIGGER [ trigger_name | ALL | USER ]
ENABLE REPLICA TRIGGER trigger_name
ENABLE ALWAYS TRIGGER trigger_name
DISABLE RULE rewrite_rule_name
ENABLE RULE rewrite_rule_name
ENABLE REPLICA RULE rewrite_rule_name
ENABLE ALWAYS RULE rewrite_rule_name
DISABLE ROW LEVEL SECURITY
ENABLE ROW LEVEL SECURITY
FORCE ROW LEVEL SECURITY
NO FORCE ROW LEVEL SECURITY
REKEY [ USING 'encypt_method' ]
CLUSTER ON index_name
SET WITHOUT CLUSTER
SET WITHOUT OIDS
SET TABLESPACE new_tablespace
SET { LOGGED | UNLOGGED }
SET ( storage_parameter = value [, ... ] )
RESET ( storage_parameter [, ... ] )
INHERIT parent_table
NO INHERIT parent_table
OF type_name
NOT OF
OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }
并且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 )
并且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 | MATCH SIMPLE ]
[ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ COMMENT comment_info ] [,...]
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
并且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 DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
并且table_constraint_using_index 是:
[ CONSTRAINT constraint_name ]
{ UNIQUE | PRIMARY KEY } USING INDEX index_name
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
index_parameters在UNIQUE、PRIMARY KEY和EXCLUDE约束中是:
[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]
exclude_element在EXCLUDE约束中是:
{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
referential_action在FOREIGN KEY/REFERENCES约束中的含义为:
{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }
只有在安全模式下指定时才支持下列关键字:
DECRYPTED
ENCRYPTED
SALT
NO SALT
MAC
NO MAC
REKEY
描述
ALTER TABLE用于修改现有表的定义。下面描述了几种子形式。请注意,每种子形式所需的锁级别可能不同。除非明确说明,否则将获取ACCESS EXCLUSIVE锁。当给出多个子命令时,所获取的锁将是任何子命令所需的最严格的锁。
-
ADD COLUMN [ IF NOT EXISTS ]
此形式使用与CREATE TABLE相同的语法向表中添加新列。如果指定了IF NOT EXISTS并且已经存在具有此名称的列,则不会抛出错误。 -
DROP COLUMN [ IF EXISTS ]
此形式从表中删除列。索引和涉及该列的表约束也将自动删除。如果删除该列会导致多元统计引用被删除,则也将删除多元统计引用。如果表外的任何内容(例如,外键引用或视图)依赖于该列,则需要使用CASCADE。如果指定了IF EXISTS并且该列不存在,则不会抛出错误。在这种情况下,会发出通知。 -
CHANGE [COLUMN] column_name columnDef ...
这种形式修改列的相关属性,可以修改列名、列类型、空、不为空、默认值、主键、自动更新等属性。当修改的同一列的属性中包含NOT NULL和NULL时,无论两个属性的先后顺序如何,此用法会设置该列为NOT NULL,忽略设置NULL属性。当修改的同一列的属性中包含PRIMARY KEY和NULL时,无论两个属性的先后顺序如何,此用法会设置该列为PRIMARY KRY,忽略设置NULL属性。当多次修改某列的默认值,且修改成功时,以最后一次的修改为准。 -
MODIFY [COLUMN] column_name columnDef ...
这种形式修改列的相关属性,不可以修改列名,可以修改列类型、空、不为空、默认值、主键、自动更新、列自增等属性。当修改的同一列的属性中包含NOT NULL和NULL时,无论两个属性的先后顺序如何,此用法会设置该列为NOT NULL,忽略设置NULL属性。当修改的同一列的属性中包含PRIMARY KEY和NULL时,无论两个属性的先后顺序如何,此用法会设置该列为PRIMARY KRY,忽略设置NULL属性。当多次修改某列的默认值,且修改成功时,以最后一次的修改为准。 -
SET DATA TYPE
此形式更改表的列的类型。索引和涉及该列的简单表约束将通过重新解析最初提供的表达式自动转换为使用新列类型。可选的COLLATE子句指定新列的排序规则;如果省略,则排序规则为新列类型的默认值。可选的USING子句指定如何从旧值计算新列值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。如果没有从旧类型到新类型的隐式或赋值转换,则必须提供USING子句。
使用此形式时,将删除该列的统计信息,因此建议在之后运行ANALYZE。
ADD [ CONSTRAINT [name] ]...
约束的数据类型是一种限制能够存储在表中数据类别的方法。ADD CONSTRAINT子句用于添加表级约束。表级约束包括:PRIMARY KEY约束、UNIQUE约束和检查约束(CHECK)等。添加表级约束时可以带有约束名,系统中同一模式下的约束名不得重复,如果不带约束名,系统自动为此约束命名。
约束和约束名都是可以省略的。但是对于创建表时,如果带有CONSTRAINT关键字的话,约束名不可以省略。
支持检查约束、唯一约束、主键约束、外键约束、排他约束。
对表在约束命省略情况下添加不同约束,均可添加成功,如下所示。
alter table test1 add constraint check(id>0);
alter table test2 add constraint unique(id);
alter table test3 add constraint primary key(id);
alter table test4 add constraint foreign_id foreign key(id) references test2(id);
alter table test5 add constraint EXCLUDE USING gist (c WITH &&)
-
SET/DROP DEFAULT
这些形式设置或删除列的默认值(其中删除等效于将默认值设置为NULL)。新的默认值仅适用于后续的INSERT或UPDATE命令;它不会导致表中已有的行发生更改。 -
SET/DROP NOT NULL
这些形式更改列是否标记为允许空值或拒绝空值。
只有在表中的记录都不包含该列的NULL值时,才可以应用SET NOT NULL到该列。通常,在ALTER TABLE期间通过扫描来检查此项。整个表格;但是,如果找到一个有效的CHECK约束,证明不存在NULL,则跳过表扫描。
如果这个表是一个分区表,在父表中标记为NOT NULL的列不能执行DROP NOT NULL。要从所有分区中删除NOT NULL约束,请在父表上执行DROP NOT NULL。即使父表上没有NOT NULL约束,也可以向单个分区添加这样的约束,如果需要的话;也就是说,子表可以禁止空值,即使父表允许它们,但反过来不行。
DROP EXPRESSION [ IF EXISTS ]
这种形式将一个存储的生成列转换为普通的基本列。列中的现有数据保留,但是以后的更改将不再应用生成表达式。
如果指定了DROP EXPRESSION IF EXISTS并且该列不是存储的生成列,则不会抛出错误。在这种情况下,会发出通知。
ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITYSET GENERATED { ALWAYS | BY DEFAULT }
DROP IDENTITY [ IF EXISTS ]
这些形式改变列是否为标识列或更改现有标识列的生成属性。有关详细信息,请参见CREATE TABLE。与SET DEFAULT一样,这些形式仅影响后续INSERT和UPDATE命令的行为;它们不会导致表中已有的行发生变化。
如果指定了 DROP IDENTITY IF EXISTS并且该列不是标识列,则不会抛出错误。在这种情况下,会发出通知。
-
SET sequence_option
RESTART
这些形式更改现有标识列下面的序列。sequence_option是由 ALTER SEQUENCE支持的选项,例如INCREMENT BY。 -
SET STATISTICS
这种形式为后续的 ANALYZE操作设置每列的统计信息收集目标。目标可以设置在0到10000的范围内;或者将其设置为-1,以恢复使用系统默认的统计信息目标(default_statistics_target)。
SET STATISTICS 获取一个 SHARE UPDATE EXCLUSIVE锁。
SET ( attribute_option=value[, ... ] )RESET ( attribute_option[, ... ] )
这种形式设置或重置每个属性的选项。目前,唯一支持的选项是storage。它可以设置为PLAIN、EXTERNAL或EXTENDED。默认值为PLAIN。这些选项的含义请参见ALTER TABLE。
定义的每个属性选项是n_distinct和n_distinct_inherited,它们覆盖了后续ANALYZE操作所做的不同值数估计。n_distinct影响表本身的统计信息,而n_distinct_inherited影响收集的表及其继承子代的统计信息。当设置为正值时,ANALYZE将假定该列包含指定数量的不同非空值。当设置为负值时(必须大于或等于-1),ANALYZE将假定该列中的不同非空值数与表的大小成线性关系;具体计数是通过将估计的表大小乘以给定数字的绝对值来计算的。例如,值-1意味着列中的所有值都是不同的,而值-0.5意味着每个值平均出现两次。当表的大小随时间变化时,这可能很有用,因为直到查询计划时间才执行乘以表行数的乘法。指定值0以恢复正常估计不同值的数量。
更改每个属性选项会获取SHARE UPDATE EXCLUSIVE锁。
-
SET STORAGE
此形式设置列的存储模式。这控制此列是内联还是在辅助TOAST表中,以及数据是否应压缩。对于诸如integer之类的固定长度值,必须使用PLAIN,并且是内联的,未压缩的。MAIN用于内联,可压缩数据。EXTERNAL用于外部未压缩数据,EXTENDED用于外部压缩数据。对于支持非PLAIN存储的大多数数据类型,默认值为EXTENDED。使用EXTERNAL将使非常大的text和bytea值的子字符串操作运行更快,但代价是增加存储空间。请注意,SET STORAGE本身不会更改表中的任何内容,它只是设置在未来的表更新期间要执行的策略。 -
SET COMPRESSION compression_method
此形式设置列的压缩方法,确定将来插入的值将如何压缩(如果存储模式允许压缩)。这不会导致表被重写,因此现有数据仍可能使用其他压缩方法进行压缩。如果使用ux_restore还原表,则所有值都将使用配置的压缩方法进行重写。但是,当从另一个关系插入数据时(例如,通过INSERT...SELECT),源表中的值不一定会被解压缩,因此任何先前压缩的数据可能会保留其现有的压缩方法,而不是使用目标列的压缩方法重新压缩。支持的压缩方法是uxlz和lz4。(只有在构建UXsinoDB时使用--with-lz4选项才可用lz4。)此外,compression_method可以default,它选择默认行为,在数据插入时咨询default_toast_compression设置以确定要使用的方法。 -
ADD table_constraint[ NOT VALID ]
此形式使用与CREATE TABLE相同的约束语法添加新约束到表中,加上选项NOT VALID,目前仅允许用于外键和CHECK约束。
通常,此形式将导致扫描表以验证表中的所有现有行是否满足新约束。但是,如果使用了NOT VALID选项,则会跳过这个可能很长的扫描。约束仍将强制执行对后续插入或更新(也就是说,它们将失败,除非在引用表中有匹配的行,在外键的情况下,或者除非新行与指定的检查条件匹配)。但是,直到使用VALIDATE CONSTRAINT选项验证约束为止,数据库不会假定约束对表中的所有行都成立。有关使用NOT VALID选项的更多信息,请参见下面的“注意”。
尽管大多数形式的ADD table_constraint需要ACCESS EXCLUSIVE锁,但ADD FOREIGN KEY仅需要SHARE ROW EXCLUSIVE锁。请注意,ADD FOREIGN KEY还会在引用表上获取SHARE ROW EXCLUSIVE锁,除了在声明约束的表上获取锁之外。
向分区表添加唯一或主键约束时,会应用其他限制;请参见CREATE TABLE。此外,目前无法将分区表上的外键约束声明为NOT VALID。
-
COMMENT 'comment_info'
添加或修改注释内容。 -
FISRT | AFTER
用于添加(ADD)或修改(CHANGE或MODIFY)表字段时指定字段的位置。FIRST是将新加列或被CHANGE(或MODIFY)字段置于表的最开始位置,而AFTER将字段置于某一已有字段之后。不用FIRST或AFTER时,ADD语法将字段加在最后,CHANGE(MODIFY)语法仍保持原位置。 -
ENABLE/DISABLE [VALIDATE/NOVALIDATE] CONSTRAINT constraint_name
禁用或启用唯一约束和check约束。DISABLE后,允许违反该约束的数据插入。该功能仅支持oracle运行模式。 -
AUTO_INCREMENT
使用设置列自增属性,指定了起始值为1,递增值为1,这种设置的自增列是只读的,不允许手动插入或更新自增列的值。自增列的值由系统自动生成并管理。 -
ADD table_constraint_using_index
此形式基于现有唯一索引向表中添加新的PRIMARY KEY或UNIQUE约束。索引的所有列都将包含在约束中。
索引不能具有表达式列,也不能是部分索引。此外,它必须是具有默认排序顺序的B树索引。这些限制确保索引等效于通过常规ADD PRIMARY KEY或ADD UNIQUE命令构建的索引。
如果指定了PRIMARY KEY,并且索引的列尚未标记为NOT NULL,则此命令将尝试对每个这样的列执行ALTER COLUMN SET NOT NULL。这需要完整的表扫描来验证列不包含空值。在所有其他情况下,这是一个快速操作。
如果提供了约束名,则索引将重命名以匹配约束名。否则,约束将与索引命名相同。
执行此命令后,索引将被约束“拥有”,就像索引是通过常规的ADD PRIMARY KEY或ADD UNIQUE命令构建的一样。特别地,删除约束也会使索引消失。
目前,此形式不支持分区表。
注意
使用现有索引添加约束可在不长时间阻止表更新的情况下添加新约束。为此,请使用CREATE INDEX CONCURRENTLY创建索引,然后使用此语法将其安装为官方约束。请参见下面的示例。
-
ALTER CONSTRAINT
此形式更改先前创建的约束的属性。目前只能更改外键约束。 -
VALIDATE CONSTRAINT
此形式通过扫描表以确保没有不满足约束的行来验证先前创建为NOT VALID的外键或检查约束。如果约束已标记为有效,则不会发生任何事情。(有关此命令的有用性的说明,请参见下面的ALTER TABLE。)
此命令获取SHARE UPDATE EXCLUSIVE锁。
-
DROP CONSTRAINT [ IF EXISTS ]
此形式删除表上指定的约束以及支持约束的任何索引。如果指定了IF EXISTS并且约束不存在,则不会抛出错误。在这种情况下,将发出通知。 -
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER
这些形式配置属于表的触发器的触发。禁用的触发器仍然为系统所知,但在其触发事件发生时不会执行。对于延迟触发器,启用状态在事件发生时检查,而不是在实际执行触发器函数时检查。可以按名称禁用或启用单个触发器,或禁用或启用表上的所有触发器,或仅禁用或启用用户触发器(此选项不包括用于实现外键约束或可延迟的唯一性和排除约束的内部生成约束触发器)。禁用或启用内部生成的约束触发器需要超级用户特权;应谨慎执行,因为如果不执行触发器,则无法保证约束的完整性。
触发器触发机制也受配置变量session_replication_role的影响。默认情况下启用的触发器将在复制角色为“origin”(默认值)或“local”时触发。配置为ENABLE REPLICA的触发器仅在会话处于“replica”模式时触发,而配置为ENABLE ALWAYS的触发器将始终触发,无论当前复制角色如何。
此机制的影响是,在默认配置中,触发器不会在副本上触发。这很有用,因为如果在源上使用触发器在表之间传播数据,那么复制系统也将复制传播的数据,触发器不应在副本上第二次触发,因为这将导致重复的数据。导致重复。然而,如果触发器用于其他目的,例如创建外部警报,则可能适合将其设置为ENABLE ALWAYS,以便在副本上也触发它。
此命令获取SHARE ROW EXCLUSIVE锁。
DISABLE/ENABLE [ REPLICA | ALWAYS ] RULE
这些形式配置属于表的重写规则的触发。禁用的规则仍然为系统所知,但在查询重写期间不会应用。其语义与禁用/启用触发器相同。对于ON SELECT规则,此配置被忽略,这些规则始终应用,以使视图在当前会话处于非默认复制角色时仍能正常工作。
规则触发机制也受到配置变量session_replication_role的影响,类似于上述触发器。
-
DISABLE/ENABLE ROW LEVEL SECURITY
这些形式控制应用于表的行安全策略。如果启用并且表中不存在策略,则应用默认拒绝策略。请注意,即使在禁用行级安全性的情况下,表也可能存在策略。在这种情况下,将不会应用策略,策略将被忽略。另请参见CREATE POLICY。 -
[
DISABLE|ENABLE] [VALIDATE|NOVALIDATE]CONSTRAINT
普通表和分区表的主键、外键约束如下。
表 普通表约束
| 约束状态 | 主键约束 | 外键约束 |
|---|---|---|
| disable | 默认为novalidate。修改主键索引的唯一性字段为false,对应主键列的非空约束为false,校验字段为false。 | 默认为novalidate。修改对应子表和主表的触发器开关为D表示触发器禁用,修改子表约束的conindid(指向reference表的主键索引oid)字段为0。还有对应的约束开关和校验开关字段。 |
| enable | 默认为validate。执行校验->重建原有主键索引,重建成功表示旧表内所有数据符合唯一性,校验旧表内是否有空值,校验成功后 统一修改该主键索引唯一性字段为true,主键列非空约束为true。 | 默认为validate。先执行数据校验,校验成功之后再修改对应字段,包括触发器,子表约束conindid修改为reference表的主键索引oid。 |
| disable validate | 关闭主键约束,开关置为true,但需执行数据校验,若表此时的约束状态为这个,则禁止对表作任何修改操作(插入、删除、更新)。 | 先执行校验,校验成功之后修改相应的开关字段,触发器开关为D,若表此时的约束状态为disable validate,则禁止对表作任何修改操作(插入、删除、更新)。 |
| disable novalidate | 同单独指定disable。 | 同单独指定disable。 |
| enable validate | 同单独指定enable。 | 同单独指定enable。 |
| enable novalidate | 对于主键不论指定校验或非校验,只要是打开约束开关就都执行校验。 | 仅打开约束开关(触发器开关,conindid字段),对于旧数据不执行校验。 |
分区表:主表实际不存储数据,但存在唯一性索引,所以对主表不执行数据校验,仅修改索引唯一性字段和主键列的非空约束还有约束状态然后对于每个子表重复普通表的操作(每个子表都有一个主键约束)。
约束示例如下所示。
alter table table_name enable constraint constraint_name;
alter table table_name disable constraint constraint_name;
alter table table_name enable validate constraint constraint_name;
alter table table_name enable novalidate constraint constraint_name;
alter table table_name disable validate constraint constraint_name;
alter table table_name disable novalidate constraint constraint_name;
alter table table_name validate constraint constraint_name;
-
NO FORCE/FORCE ROW LEVEL SECURITY
这些形式控制当用户是表所有者时应用于表的行安全策略。如果启用,则当用户是表所有者时将应用行级安全策略。如果禁用(默认值),则当用户是表所有者时将不应用行级安全性。另请参见CREATE POLICY。 -
CLUSTER ON
此形式选择未来CLUSTER操作的默认索引。它实际上不会重新对表进行聚集。
更改聚集选项会获取SHARE UPDATE EXCLUSIVE锁。
SET WITHOUT CLUSTER
此形式从表中删除最近使用的CLUSTER索引规范。这会影响未指定索引的未来聚集操作。
更改聚集选项会获取SHARE UPDATE EXCLUSIVE锁。
-
SET WITHOUT OIDS
用于删除oid系统列的向后兼容语法。由于无法再添加oid系统列,因此这永远不会产生影响。 -
SET ACCESS METHOD
此形式通过重写更改表的访问方法。 -
SET TABLESPACE
此形式将表的表空间更改为指定的表空间,并将与表关联的数据文件移动到新表空间。表上的索引(如果有)不会移动;但是它们可以移动。使用额外的SET TABLESPACE命令可以将表移动到不同的表空间中。当应用于分区表时,不会移动任何内容,但是之后使用CREATE TABLE PARTITION OF创建的任何分区都将使用该表空间,除非被TABLESPACE子句覆盖。
可以使用ALL IN TABLESPACE形式将当前数据库中的所有表移动到表空间中,该形式将首先锁定要移动的所有表,然后逐个移动。此形式还支持OWNED BY,它只会移动由指定角色拥有的表。如果指定了NOWAIT选项,则如果无法立即获取所需的所有锁定,则命令将失败。请注意,此命令不会移动系统目录;如果需要,请改用ALTER DATABASE或显式的ALTER TABLE调用。information_schema关系不被视为系统目录的一部分,因此将被移动。另请参见CREATE TABLESPACE。
SET { LOGGED | UNLOGGED }
此形式将表从未记录更改为记录或反之亦然(请参见CREATE TABLE中的“UNLOGGED”)。它不能应用于临时表。
这还会更改链接到表的任何序列的持久性(用于标识或序列列)。但是,也可以单独更改这些序列的持久性。
SET ( storage_parameter[=value] [, ... ])
此形式更改表的一个或多个存储参数。有关可用参数的详细信息,请参见CREATE TABLE中的“存储参数”。请注意,此命令不会立即修改表内容;根据参数,您可能需要重写表以获得所需的效果。可以使用VACUUM 、CLUSTER 或强制表重写的ALTER TABLE形式来完成。对于与规划器相关的参数,更改将在下次锁定表时生效,因此当前正在执行的查询不会受到影响。
对于fillfactor、toast和autovacuum存储参数以及规划器参数parallel_workers,将采取SHARE UPDATE EXCLUSIVE锁定。
-
RESET(storage_parameter[, ... ] )
此形式将一个或多个存储参数重置为其默认值。与SET一样,可能需要对表进行重写才能完全更新表。 -
INHERIT parent_table
此形式将目标表作为指定父表的新子项添加。随后,针对父表的查询将包括目标表的记录。要作为子项添加,目标表必须已包含与父表相同的所有列(也可以有其他列)。这些列必须具有匹配的数据类型,如果父表中有NOT NULL约束,则子表中也必须有NOT NULL约束。此外,对于父表的所有CHECK约束,必须有相应的子表约束,除了那些标记为不可继承的约束(即使用ALTERTABLE ... ADD CONSTRAINT ... NO INHERIT创建的约束)在父表中被忽略;所有匹配的子表约束都不能被标记为不可继承。目前,UNIQUE、PRIMARY KEY和FOREIGN KEY约束不被考虑,但这可能会在未来发生改变。 -
NO INHERIT parent_table
此形式将目标表从指定父表的子表列表中移除。对父表的查询将不再包括从目标表中获取的记录。 -
OF type_name
此形式将表与组合类型链接,就好像CREATE TABLE OF已经形成了它。表的列名和类型列表必须与组合类型完全匹配。表不能从任何其他表继承。这些限制确保CREATE TABLE OF将允许等效的表定义。 -
NOT OF
此形式将一个类型化的表与其类型分离。 -
OWNER TO
此形式将表、序列、视图、物化视图或外部表的所有者更改为指定的用户。 -
REPLICA IDENTITY
此形式更改写入预写式日志以标识更新或删除的行的信息。在大多数情况下,每个列的旧值仅在与新值不同的情况下记录;但是,如果旧值存储在外部,则无论是否更改,它始终被记录。除非逻辑复制正在使用,否则此选项无效。 -
DEFAULT
记录主键列的旧值(如果有)。这是非系统表的默认值。 -
USING INDEX index_name
记录被命名索引覆盖的列的旧值,该索引必须是唯一的、非部分的、不可延迟的,并且仅包括标记为NOT NULL的列。如果删除此索引,则行为与NOTHING相同。 -
FULL
记录行中所有列的旧值。 -
NOTHING
不记录有关旧行的任何信息。这是系统表的默认值。 -
RENAME
RENAME形式更改表(或索引、序列、视图、物化视图或外部表)的名称、表中单个列的名称或表的约束的名称。重命名约束时,如果有底层索引,则索引也会被重命名。对存储的数据没有影响。 -
SET SCHEMA
此形式将表移动到另一个模式中。关联的索引、触发器和约束也会被移动。如果目标模式不存在,则会创建它。
形式将表列所拥有的约束和序列一并移动。
ATTACH PARTITION partition_name{ FOR VALUESpartition_bound_spec| DEFAULT }
这种形式将一个现有的表(可能本身已经被分区)作为目标表的一个分区进行附加。可以使用FOR VALUES指定表作为特定值的分区,也可以使用DEFAULT将其作为默认分区进行附加。对于目标表中的每个索引,都会在附加的表中创建相应的索引;或者,如果已经存在等效的索引,则会将其附加到目标表的索引上,就像执行了ALTER INDEX ATTACH PARTITION一样。请注意,如果现有的表是外部表,则当前不允许将该表作为目标表的分区附加,如果目标表上有UNIQUE索引的话。(另请参见CREATE FOREIGN TABLE。)对于目标表中存在的每个用户定义的行级触发器,都会在附加的表中创建相应的触发器。
使用 FOR VALUES 的分区使用与CREATE TABLE相同的语法来指定partition_bound_spec。分区边界规范必须对应于目标表的分区策略和分区键。要附加的表必须具有与目标表相同的所有列,而且不能多出任何列;此外,列类型也必须匹配。此外,它必须具有目标表的所有NOT NULL 和 CHECK 约束。目前不考虑FOREIGN KEY约束。如果父表中存在UNIQUE和PRIMARYKEY约束,则会在分区中创建它们,如果它们不存在的话。如果要附加的表中的任何CHECK约束被标记为 NOINHERIT,则该命令将失败;必须重新创建这些约束,而不使用NO INHERIT子句。
如果新分区是一个常规表,则会执行完整的表扫描,以检查表中现有的行是否违反了分区约束。可以通过在运行此命令之前向表添加一个有效的CHECK约束,该约束只允许满足所需分区约束的行,来避免此扫描。将使用CHECK约束来确定无需扫描表以验证分区约束。但是,如果分区键中的任何一个是表达式,并且分区不接受NULL值,则此方法不起作用。如果附加的是一个不接受NULL值的列表分区,请在分区键列中添加NOT NULL约束,除非它是一个表达式。
如果新分区是一个外部表,则不会执行任何操作来验证外部表中的所有行是否符合分区约束。(有关外部表上的约束的讨论,请参见CREATE FOREIGN TABLE。)
当一个表有一个默认分区时,定义一个新的分区会更改默认分区的分区约束。默认分区不能包含需要移动到新分区的任何行,并且将进行扫描以验证没有这样的行存在。这将移动目标表中的行,以使它们符合新的分区约束。如果目标表上有任何触发器,则它们将在移动行之前运行。如果目标表上有任何索引,则它们将在移动行之后重建。如果目标表上有任何约束,则它们将在移动行之后重建。如果目标表上有任何序列,则它们也将移动。如果新分区是一个默认分区,则不会执行任何操作来验证默认分区中的所有行是否符合分区约束。
扫描,例如新分区的扫描,可以通过存在适当的CHECK约束来避免。与新分区的扫描一样,当默认分区是外部表时,它总是被跳过。附加分区会在父表上获取SHARE UPDATE EXCLUSIVE锁,除了在要附加的表和默认分区(如果有)上获取ACCESS EXCLUSIVE锁之外。如果要附加的表本身是分区表,则还必须持有所有子分区的锁。同样,如果默认分区本身是分区表,则也必须持有子分区的锁。可以通过添加CHECK约束来避免锁定子分区。
DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ]
此形式分离目标表的指定分区。分离的分区将继续存在作为独立的表,但不再与其分离的表有任何关联。附加到目标表的任何索引都将被分离。从目标表中克隆的任何触发器都将被删除。在外键约束中引用此分区表的任何表都会获得SHARE锁。
如果指定了CONCURRENTLY,它将使用降低的锁级别运行,以避免阻塞可能正在访问分区表的其他会话。在此模式下,内部使用两个事务。在第一个事务期间,对父表和分区都采取SHARE UPDATE EXCLUSIVE锁,并将分区标记为正在分离;此时,提交事务并等待使用分区表的所有其他事务。一旦所有这些事务都完成,第二个事务将在分区表上获取SHARE UPDATE EXCLUSIVE和在分区上获取ACCESS EXCLUSIVE,并完成分离过程。将添加一个重复分区约束的CHECK约束到分区中。如果分区表包含默认分区,则不能在事务块中运行CONCURRENTLY,也不允许运行。
如果指定了FINALIZE,则会完成之前被取消或中断的DETACH CONCURRENTLY调用。在分区表中,最多只能有一个分区处于待分离状态。
除RENAME、SET SCHEMA、ATTACH PARTITION和DETACH PARTITION之外,所有作用于单个表的ALTER TABLE形式都可以组合成多个要一起应用的更改列表。例如,可以在单个命令中添加多个列或更改多个列的类型。这对于大型表格特别有用,因为只需要对表格进行一次遍历。
您必须拥有表格才能使用ALTER TABLE。要更改表的模式或表空间,您还必须在新模式或表空间上拥有CREATE特权。要将表格添加为父表的新子项,您还必须拥有父表。此外,要将表格附加为表格的新分区,您必须拥有要附加的表格。要更改所有者,您还必须是新所有者的直接或间接成员。拥有角色必须是表的所有者,并且该角色必须在表的模式上具有CREATE特权。(这些限制强制执行更改所有者不会执行删除和重新创建表无法执行的操作。但是,超级用户可以随意更改任何表的所有权。)要添加列或更改列类型或使用OF子句,您还必须在数据类型上具有USAGE特权。
参数
-
IF EXISTS
如果表不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
要更改的现有表的名称(可选架构限定)。如果在表名之前指定了ONLY,则仅更改该表。如果没有指定ONLY,则更改表及其所有子孙表(如果有)。可以在表名后面明确指定*,以明确表示包括子孙表。 -
column_name
新列或现有列的名称。 -
new_column_name
现有列的新名称。 -
new_name
表的新名称。 -
data_type
新列的数据类型,或现有列的新数据类型。 -
table_constraint
表的新表约束。 -
constraint_name
新或现有约束的名称。 -
CASCADE
自动删除依赖于删除的列或约束的对象(例如,引用该列的视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果存在任何依赖对象,则拒绝删除列或约束。这是默认行为。 -
trigger_name
要禁用或启用的单个触发器的名称。 -
ALL
禁用或启用属于表的所有触发器。(如果任何触发器是内部生成的约束触发器,例如用于实现外键约束或可延迟的唯一性和排除约束,则需要超级用户特权。) -
USER
禁用或启用属于表的所有触发器,但不包括内部生成的约束触发器,例如用于实现外键约束或可延迟的唯一性和排除约束。 -
index_name
现有索引的名称。 -
storage_parameter
表存储参数的名称。 -
value
表存储参数的新值。这可能是一个数字或一个单词,具体取决于参数。 -
parent_table
一个与此表关联或取消关联的父表。 -
new_owner
表的新所有者的用户名。 -
new_access_method
将表转换为的访问方法的名称。 -
new_tablespace
表将被移动到的表空间的名称。 -
new_schema
表将被移动到的模式的名称。 -
partition_name
要作为新分区附加或从此表中分离的表的名称。 -
partition_bound_spec
新分区的分区边界规范。有关语法的详细信息,请参见CREATE TABLE。
注意事项
关键字FISRT/AFTER需要在GUC参数enable_mysql_attpo = on时可以使用,否则报语法错误,nable_mysql_attpo默认值为off,只能通过uxsiondb.conf修改参数并重启数据库生效。如果enable_mysql_attpo = on,使用first、after语法将会报错,表的字段顺序将恢复为按照新加列的时间先后顺序,包括那些已经被first、after关键字修改过的表的字段顺序。
关键字COLUMN是无用的,可以省略。
使用ADD COLUMN添加列并指定非易失性DEFAULT时,默认值会在语句执行时计算,并存储在表的元数据中。该值将用于所有现有行的列。如果未指定DEFAULT,则使用NULL。在任一情况下,都不需要重写表。
添加具有易失性DEFAULT或更改现有列的类型将需要重写整个表及其索引。作为例外,当更改现有列的类型时,如果USING子句未更改列内容,并且旧类型可以二进制强制转换为新类型或是新类型的未约束域,则不需要重写表。但是,除非系统可以验证新索引在逻辑上等效于现有索引,否则必须重建索引。例如,如果更改列的排序规则,则始终需要重建索引,因为新的排序顺序可能不同。但是,在没有排序规则更改的情况下,可以将列从text更改为varchar(反之亦然)而无需重建索引,因为这些数据类型排序相同。对于大型表,表或索引重建可能需要大量时间,并且将暂时需要多达两倍的磁盘空间。
添加CHECK或NOT NULL约束需要扫描表以验证现有行是否符合约束条件,但不需要重写表。
类似地,当附加新分区时,可能会扫描以验证现有行是否符合分区约束。
提供在单个ALTER TABLE中指定多个更改的选项的主要原因是可以将多个表扫描或重写合并为对表的单个传递。
扫描大型表以验证新外键或检查约束可能需要很长时间,并且在提交ALTER TABLE ADD CONSTRAINT命令之前,表的其他更新将被锁定。NOT VALID约束选项的主要目的是减少添加约束对表的影响。并发更新。使用 NOT VALID,ADD CONSTRAINT命令不会扫描表格,可以立即提交。之后,可以发出VALIDATE CONSTRAINT命令来验证现有行是否满足约束条件。验证步骤不需要锁定并发更新,因为它知道其他事务将为它们插入或更新的行强制执行约束条件;只需要检查预先存在的行。因此,验证仅在正在更改的表上获取SHARE UPDATE EXCLUSIVE 锁定。(如果约束是外键,则还需要在约束引用的表上获取ROW SHARE锁定。)除了提高并发性外,使用NOT VALID和VALIDATE CONSTRAINT还可以在表格已知包含预先存在的违规情况的情况下使用。一旦约束条件到位,就不会插入新的违规行,现有问题可以在VALIDATE CONSTRAINT最终成功之前随意纠正。
DROP COLUMN表单不会物理删除列,而只是使其对SQL操作不可见。表格中的后续插入和更新操作将为该列存储空值。因此,删除列很快,但它不会立即减少表格的磁盘占用空间,因为删除的列占用的空间不会被回收。随着现有行的更新,空间将随时间而被回收。要强制立即回收删除列所占用的空间,可以执行执行整个表格重写的ALTER TABLE表单之一。这将导致重构每一行,将删除的列替换为空值。
ALTER TABLE 的重写表单不是 MVCC安全的。在表格重写之后,如果并发事务使用了重写之前的快照,则表格将对它们呈现为空。
SET DATA TYPE 的 USING选项实际上可以指定任何涉及行旧值的表达式;也就是说,它可以引用除正在转换的列之外的其他列。这允许使用SET DATA TYPE语法进行非常通用的转换。由于这种灵活性,USING表达式不适用于列的默认值(如果有的话);结果可能不是默认值所需的常量表达式。这意味着当旧类型和新类型之间没有隐式或赋值转换时,SET DATA TYPE 可能无法转换默认值,即使提供了USING子句。在这种情况下,使用DROP DEFAULT删除默认值,执行ALTER TYPE,然后使用SET DEFAULT添加一个合适的新默认值。类似的考虑也适用于涉及该列的索引和约束。如果一个表格有任何子表格,不允许在父表格中添加、重命名或更改列的类型,而不对子表格进行相同的操作。这确保了后代始终具有与父项匹配的列。同样,如果不在所有后代中重命名,则不能在父项中重命名CHECK约束,以便父项和其后代之间的CHECK约束也匹配。(但是,该限制不适用于基于索引的约束。)此外,因为从父项中选择也会从其后代中选择,所以在查询中使用SELECT时,必须小心处理重复的行。除非对这些后代也标记为有效,否则无法将父级上的约束标记为有效。在所有这些情况下,ALTER TABLE ONLY将被拒绝。
递归的 DROP COLUMN操作仅在后代表未从任何其他父级继承该列并且从未独立定义该列的情况下才会删除后代表的列。非递归的DROP COLUMN(即 ALTER TABLE ONLY ... DROP COLUMN)永远不会删除任何后代列,而是将它们标记为独立定义而不是继承。对于分区表,非递归的DROP COLUMN命令将失败,因为表的所有分区必须与分区根具有相同的列。
标识列的操作(ADD GENERATED、DROP IDENTITY、SET 等),以及TRIGGER、CLUSTER、OWNER和TABLESPACE操作永远不会递归到后代表中;也就是说,它们总是像指定了ONLY一样操作。添加约束只递归到未标记为NO INHERIT的CHECK约束。
不允许更改系统目录表的任何部分。
有关有效参数的进一步说明,请参见CREATE TABLE。
示例
要向表中添加一个varchar类型的列:
ALTER TABLE distributors ADD COLUMN address varchar(30);
这将导致表中所有现有行的新列填充为null值。
要添加一个具有非空默认值的列:
ALTER TABLE measurements
ADD COLUMN mtime timestamp with time zone DEFAULT now();
现有行将用当前时间填充新列的值,然后新行将接收其插入时间。
要添加一个列并用与默认值不同的值填充它以供以后使用:
ALTER TABLE transactions
ADD COLUMN status varchar(30) DEFAULT 'old',
ALTER COLUMN status SET default 'current';
现有行将填充为old,但随后命令的默认值将为current。效果与如果两个子命令已在单独的ALTER TABLE命令中发出相同。
要从表中删除列:
ALTER TABLE distributors DROP COLUMN address RESTRICT;
要在一个操作中更改两个现有列的类型:
ALTER TABLE distributors
ALTER COLUMN address TYPE varchar(80),
ALTER COLUMN name TYPE varchar(100);
要通过USING子句将包含Unix时间戳的整数列更改为timestamp with time zone:
ALTER TABLE foo
ALTER COLUMN foo_timestamp SET DATA TYPE timestamp with time zone
USING
timestamp with time zone 'epoch' + foo_timestamp * interval '1 second';
当列具有无法自动转换为新数据类型的默认表达式时,操作相同:
ALTER TABLE foo
ALTER COLUMN foo_timestamp DROP DEFAULT,
ALTER COLUMN foo_timestamp TYPE timestamp with time zone
USING
timestamp with time zone 'epoch' + foo_timestamp * interval '1 second',
将现有列的默认值设置为当前时间戳:
ALTER COLUMN foo_timestamp SET DEFAULT now();
重命名现有列:
ALTER TABLE distributors RENAME COLUMN address TO city;
重命名现有表:
ALTER TABLE distributors RENAME TO suppliers;
重命名现有约束:
ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip_check;
向列添加非空约束:
ALTER TABLE distributors ALTER COLUMN street SET NOT NULL;
从列中删除非空约束:
ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL;
向表及其所有子表添加检查约束:
ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
仅向表添加检查约束,而不是其子表:
ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT;
(检查约束也不会被未来的子表继承。)
从表及其所有子表中删除检查约束:
ALTER TABLE distributors DROP CONSTRAINT zipchk;
仅从一个表中删除检查约束:
ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk;
(检查约束仍然适用于任何子表。)
向表添加外键约束:
ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address);
以对其他工作影响最小的方式向表添加外键约束:
ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID;
ALTER TABLE distributors VALIDATE CONSTRAINT distfk;
向表添加(多列)唯一约束:
ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode);
向表添加自动命名的主键约束,注意表只能有一个主键:
ALTER TABLE distributors ADD PRIMARY KEY (dist_id);
将表移动到不同的表空间:
ALTER TABLE distributors SET TABLESPACE fasttablespace;
将表移动到不同的模式:
ALTER TABLE myschema.distributors SET SCHEMA yourschema;
重新创建主键约束,而不会在重建索引时阻止更新:
CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id);
ALTER TABLE distributors DROP CONSTRAINT distributors_pkey,
ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx;
将分区附加到范围分区表:
ALTER TABLE measurement
ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');
将分区附加到列表分区表:
ALTER TABLE cities
ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b');
将分区附加到哈希分区表:
ALTER TABLE orders
ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3);
将默认分区附加到分区表:
ALTER TABLE cities
ATTACH PARTITION cities_partdef DEFAULT;
从分区表中分离分区:
ALTER TABLE measurement
DETACH PARTITION measurement_y2015m12;
通过change只修改列名,如下所示。
Alter table test change v1 v2 int;
通过change只修改列类型,如下所示。
Alter table test change v1 v2 varchar2(10);
通过change修改不为空属性和设置默认值,如下所示。
Alter table test change v1 v1 int not null default 2;
通过change设置主键,如下所示。
Alter table test change v1 v1 int primary key;
通过change设置唯一约束,如下所示。
Alter table test change v1 v1 int unique;
通过change设置自动更新,如下所示。
Alter table test change v1 v1 timestamp on update now();
通过change设置列加密,如下所示。
Alter table test change v1 v1 int encrypted;
将字段c添加在最前,如下所示。
alter table test add column c int first;
将字段c添加在字段a之后,如下所示。
alter table test2 add column c int after a;
通过MODIFY只修改列类型,如下所示。
ALTER TABLE test MODIFY c VARCHAR(30);
通过MODIFY只修改列默认值,如下所示。
ALTER TABLE test MODIFY c DOUBLE DEFAULT NULL;
通过MODIFY设置唯一约束,如下所示。
ALTER TABLE test MODIFY c INT UNIQUE;
通过MODIFY设置主键约束,如下所示。
ALTER TABLE test MODIFY c INT PRIMARY KEY;
通过MODIFY只修改列注释,如下所示。
ALTER TABLE test MODIFY c INT COMMENT ‘comment1’;
通过MODIFY设置列自增属性,如下所示。
ALTER TABLE test MODIFY c INT AUTO_INCREMENT;
通过MODIFY设置列加密,如下所示。
ALTER TABLE test MODIFY c INT UX_INCREMENT;
通过MODIFY进行列解密,如下所示。
ALTER TABLE test MODIFY c INT DECRYPTED;
通过MODIFY设置timestamp列类型自动更新,如下所示。
ALTER TABLE test MODIFY c TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
通过MODIFY将字段c移动到最前面,如下所示。
ALTER TABLE test MODIFY c INT FIRST;
通过MODIFY将字段c移动到字段a之后,如下所示。
ALTER TABLE test MODIFY c INT AFTER a;
禁用t1_id_check的检查约束,如下所示。
ALTER TABLE t1 DISABLE VALIDATE CONSTRAINT t1_id_check;
启用t1_id_check的检查约束,如下所示。
ALTER TABLE t1 ENABLE CONSTRAINT t1_id_check;
兼容性
表单ADD(不使用USING INDEX)、DROP [COLUMN]、DROP IDENTITY、RESTART、SET DEFAULT、SET DATA TYPE(不使用USING)、SET GENERATED和SET sequence_option符合SQL标准。其他形式是SQL标准的UXsinoDB扩展。此外,在单个ALTER TABLE命令中指定多个操作的能力是一种扩展。
ALTER TABLE DROP COLUMN可用于删除表的唯一列,从而留下一个零列表。这是SQL的扩展,它不允许零列表。
另请参阅
ALTER TABLESPACE
ALTER TABLESPACE — 更改表空间的定义
概要
ALTER TABLESPACE name RENAME TO new_name
ALTER TABLESPACE name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER TABLESPACE name SET ( tablespace_option = value [, ... ] )
ALTER TABLESPACE name RESET ( tablespace_option [, ... ] )
描述
ALTER TABLESPACE可用于更改表空间的定义。
您必须拥有表空间才能更改表空间的定义。要更改所有者,您还必须是新所有者角色的直接或间接成员。(超级用户自动拥有这些特权。)
参数
-
name
现有表空间的名称。 -
new_name
表空间的新名称。新名称不能以ux_开头,因为这些名称保留给系统表空间。 -
new_owner
表空间的新所有者。 -
tablespace_option
要设置或重置的表空间参数。目前,唯一可用的参数是seq_page_cost、random_page_cost、effective_io_concurrency和maintenance_io_concurrency。为特定表空间设置这些值将覆盖规划器对从该表空间中的表读取页面的成本的通常估计,以及执行器的预取行为,这是由配置参数确定的。相同的名称(参见seq_page_cost、random_page_cost、effective_io_concurrency、maintenance_io_concurrency)。如果一个表空间位于比其余I/O子系统更快或更慢的磁盘上,则这可能很有用。
示例
将表空间index_space重命名为fast_raid:
ALTER TABLESPACE index_space RENAME TO fast_raid;
更改表空间index_space的所有者:
ALTER TABLESPACE index_space OWNER TO mary;
兼容性
SQL标准中没有ALTER TABLESPACE语句。
另请参阅
CREATE TABLESPACE、DROP TABLESPACE
ALTER TEXT SEARCH CONFIGURATION
ALTER TEXT SEARCH CONFIGURATION — 更改文本搜索配置的定义
概要
ALTER TEXT SEARCH CONFIGURATION name
ADD MAPPING FOR token_type [, ... ] WITH dictionary_name [, ...]
ALTER TEXT SEARCH CONFIGURATION name
ALTER MAPPING FOR token_type [, ... ] WITH dictionary_name [, ...]
ALTER TEXT SEARCH CONFIGURATION name
ALTER MAPPING REPLACE old_dictionary WITH new_dictionary
ALTER TEXT SEARCH CONFIGURATION name
ALTER MAPPING FOR token_type [, ... ] REPLACE old_dictionary WITH new_dictionary
ALTER TEXT SEARCH CONFIGURATION name
DROP MAPPING [ IF EXISTS ] FOR token_type [, ...]
ALTER TEXT SEARCH CONFIGURATION name RENAME TO new_name
ALTER TEXT SEARCH CONFIGURATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER TEXT SEARCH CONFIGURATION name SET SCHEMA new_schema
描述
ALTER TEXT SEARCH CONFIGURATION更改文本搜索配置的定义。您可以修改其从标记类型到字典的映射,或更改配置的名称或所有者。
您必须是配置的所有者才能使用ALTER TEXT SEARCH CONFIGURATION。
参数
-
name
一个现有的文本搜索配置的名称(可选地包含模式限定符)。 -
token_type
由配置的解析器发出的标记类型的名称。 -
dictionary_name
要查询指定标记类型的文本搜索字典的名称。如果列出了多个字典,则按指定顺序查询它们。 -
old_dictionary
要在映射中替换的文本搜索字典的名称。 -
new_dictionary
要替换old_dictionary的文本搜索字典的名称。 -
new_name
文本搜索配置的新名称。 -
new_owner
文本搜索配置的新所有者。 -
new_schema
文本搜索配置的新模式。
ADD MAPPING FOR表单安装要查询指定标记类型的字典列表;如果任何标记类型已经有映射,则会出现错误。ALTER MAPPING FOR表单执行相同的操作,但首先删除这些标记类型的任何现有映射。ALTER MAPPING REPLACE表单将new_dictionary替换为任何出现old_dictionary的地方。当出现FOR时,仅对指定的标记类型执行此操作,否则对配置的所有映射执行此操作。DROP MAPPING表单删除指定标记类型的所有字典,导致忽略这些类型的标记。如果没有标记类型的映射,则会出现错误,除非出现IF EXISTS。
示例
以下示例将my_config中任何使用english的地方替换为swedish。
ALTER TEXT SEARCH CONFIGURATION my_config
ALTER MAPPING REPLACE english WITH swedish;
兼容性
SQL标准中没有ALTER TEXT SEARCH CONFIGURATION语句。
另请参阅
CREATE TEXT SEARCH CONFIGURATION,DROP TEXT SEARCH CONFIGURATION
ALTER TEXT SEARCH DICTIONARY
ALTER TEXT SEARCH DICTIONARY — 更改文本搜索词典的定义
概要
ALTER TEXT SEARCH DICTIONARY name (
option [ = value ] [, ... ]
)
ALTER TEXT SEARCH DICTIONARY name RENAME TO new_name
ALTER TEXT SEARCH DICTIONARY name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER TEXT SEARCH DICTIONARY name SET SCHEMA new_schema
描述
ALTER TEXT SEARCH DICTIONARY更改文本搜索词典的定义。您可以更改词典的模板特定选项,或更改词典的名称或所有者。
您必须是词典的所有者才能使用ALTER TEXT SEARCH DICTIONARY。
参数
-
name
现有文本搜索词典的名称(可选模式限定)。 -
option
要为此词典设置的模板特定选项的名称。 -
value
用于模板特定选项的新值。如果省略等号和值,则从词典中删除任何先前的选项设置,从而允许使用默认值。 -
new_name
文本搜索词典的新名称。 -
new_owner
文本搜索词典的新所有者。 -
new_schema
文本搜索词典的新模式。
模板特定选项可以以任何顺序出现。
示例
以下示例命令更改基于Snowball的字典的停用词列表。其他参数保持不变。
ALTER TEXT SEARCH DICTIONARY my_dict ( StopWords = newrussian );
以下示例命令将语言选项更改为dutch,并完全删除停用词选项。
ALTER TEXT SEARCH DICTIONARY my_dict ( language = dutch, StopWords );
以下示例命令“更新”字典的定义,而实际上并未更改任何内容。
ALTER TEXT SEARCH DICTIONARY my_dict ( dummy );
(这样做的原因是选项删除代码不会抱怨是否存在此选项。)当更改字典的配置文件时,这个技巧非常有用:ALTER将强制现有数据库会话重新读取配置文件,否则如果它们之前读取了这些文件,它们将永远不会这样做。
兼容性
SQL标准中没有ALTER TEXT SEARCH DICTIONARY语句。
另请参阅
CREATE TEXT SEARCH DICTIONARY,DROP TEXT SEARCH DICTIONARY
ALTER TEXT SEARCH PARSER
ALTER TEXT SEARCH PARSER — 更改文本搜索解析器的定义
概要
ALTER TEXT SEARCH PARSER name RENAME TO new_name
ALTER TEXT SEARCH PARSER name SET SCHEMA new_schema
描述
ALTER TEXT SEARCH PARSER更改文本搜索解析器的定义。目前,唯一支持的功能是更改解析器的名称。
您必须是超级用户才能使用ALTER TEXT SEARCH PARSER。
参数
-
name
现有文本搜索解析器的名称(可选模式限定)。 -
new_name
文本搜索解析器的新名称。 -
new_schema
文本搜索解析器的新模式。
兼容性
SQL标准中没有ALTER TEXT SEARCH PARSER语句。
另请参阅
CREATE TEXT SEARCH PARSER,DROP TEXT SEARCH PARSER
ALTER TEXT SEARCH TEMPLATE
ALTER TEXT SEARCH TEMPLATE — 修改文本搜索模板的定义
概要
ALTER TEXT SEARCH TEMPLATE name RENAME TO new_name
ALTER TEXT SEARCH TEMPLATE name SET SCHEMA new_schema
描述
ALTER TEXT SEARCH TEMPLATE修改文本搜索模板的定义。目前,唯一支持的功能是更改模板的名称。
您必须是超级用户才能使用ALTER TEXT SEARCH TEMPLATE。
参数
-
name
现有文本搜索模板的名称(可选模式限定符)。 -
new_name
文本搜索模板的新名称。 -
new_schema
文本搜索模板的新模式。
兼容性
SQL标准中没有 ALTER TEXT SEARCH TEMPLATE 语句。
另请参阅
CREATE TEXT SEARCH TEMPLATE,DROP TEXT SEARCH TEMPLATE
ALTER TRIGGER
ALTER TRIGGER — 更改触发器的定义
概要
ALTER TRIGGER name ON table_name RENAME TO new_name
ALTER TRIGGER name ON table_name [ NO ] DEPENDS ON EXTENSION extension_name
描述
ALTER TRIGGER更改现有触发器的属性。
RENAME子句更改给定触发器的名称,而不会更改触发器定义。如果触发器所在的表是分区表,则分区中的相应克隆触发器也会被重命名。
DEPENDS ON EXTENSION子句将触发器标记为依赖于扩展,因此如果删除扩展,则触发器也将自动删除。
您必须拥有触发器所在的表才能更改其属性。
参数
-
name
要更改的现有触发器的名称。 -
table_name
此触发器作用的表的名称。 -
new_name
触发器的新名称。 -
extension_name
触发器要依赖的扩展的名称(如果指定了NO,则不再依赖)。标记为依赖于扩展的触发器在删除扩展时会自动删除。
注意事项
临时启用或禁用触发器的能力由ALTER TABLE提供,而不是由ALTER TRIGGER提供,因为ALTER TRIGGER没有此功能。
方便的方式来表达一次性启用或禁用表中所有触发器的选项。
示例
重命名现有触发器:
ALTER TRIGGER emp_stamp ON emp RENAME TO emp_track_chgs;
将触发器标记为依赖于扩展:
ALTER TRIGGER emp_stamp ON emp DEPENDS ON EXTENSION emplib;
兼容性
ALTER TRIGGER 是 UXsinoDB SQL 标准的扩展。
另请参阅
ALTER TYPE
ALTER TYPE — 更改类型的定义
概要
ALTER TYPE name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER TYPE name RENAME TO new_name
ALTER TYPE name SET SCHEMA new_schema
ALTER TYPE name RENAME ATTRIBUTE attribute_name TO new_attribute_name [ CASCADE | RESTRICT ]
ALTER TYPE name action [, ... ]
ALTER TYPE name ADD VALUE [ IF NOT EXISTS ] new_enum_value [ { BEFORE | AFTER } neighbor_enum_value ]
ALTER TYPE name RENAME VALUE existing_enum_value TO new_enum_value
ALTER TYPE name SET ( property = value [, ... ] )
其中 action 是以下之一:
ADD ATTRIBUTE attribute_name data_type [ COLLATE collation ] [ CASCADE | RESTRICT ]
DROP ATTRIBUTE [ IF EXISTS ] attribute_name [ CASCADE | RESTRICT ]
ALTER ATTRIBUTE attribute_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ CASCADE | RESTRICT ]
描述
ALTER TYPE更改现有类型的定义。有几个子形式:
-
OWNER
此形式更改类型的所有者。 -
RENAME
此表单更改类型的名称。 -
SET SCHEMA
此表单将类型移动到另一个模式中。 -
RENAME ATTRIBUTE
此表单仅适用于组合类型。它更改类型的单个属性的名称。 -
ADD ATTRIBUTE
此表单使用与CREATE TYPE相同的语法向组合类型添加新属性。 -
DROP ATTRIBUTE [ IF EXISTS ]
此表单从组合类型中删除属性。如果指定了IF EXISTS并且属性不存在,则不会引发错误。在这种情况下,会发出通知。 -
ALTER ATTRIBUTE ... SET DATA TYPE
此表单更改组合类型的属性的类型。 -
ADD VALUE [ IF NOT EXISTS ] [ BEFORE | AFTER ]
此表单向枚举类型添加新值。可以将新值在枚举的排序中指定为BEFORE或AFTER现有值之一。否则,新项将添加到值列表的末尾。
如果指定了IF NOT EXISTS,则如果类型已经包含新值,则不会出现错误:会发出通知,但不会采取其他任何操作。否则,如果新值已经存在,则会出现错误。
-
RENAME VALUE
此表单重命名枚举类型的值。该值在枚举的排序中不受影响。如果指定的值不存在或新名称已存在,则会出现错误。 -
SET ( property=value[, ... ] )
此表单仅适用于基本类型。它允许调整可以在CREATE TYPE中设置的基本类型属性的子集。具体来说,可以更改以下属性:
-
RECEIVE可以设置为二进制输入函数的名称,或NONE以删除类型的二进制输入函数。使用此选项需要超级用户权限。 -
SEND可以设置为二进制输出函数的名称,或NONE以删除类型的二进制输出函数。使用此选项需要超级用户权限。 -
TYPMOD_IN可以设置为类型修饰符输入函数的名称,或NONE以删除类型的类型修饰符输入函数。使用此选项需要超级用户权限。 -
TYPMOD_OUT可以设置为类型修饰符输出函数的名称,或NONE以删除类型的类型修饰符输出函数。使用此选项需要超级用户权限。 -
ANALYZE可以设置为类型特定的统计信息收集函数的名称,或NONE以删除类型的统计信息收集函数。使用此选项需要超级用户权限。 -
SUBSCRIPT可以设置为类型特定的子脚本处理程序函数,或NONE以删除类型的子脚本处理程序函数。使用此选项需要超级用户权限。 -
STORAGE可设置为plain、extended、external或main。但是,从plain更改为其他设置需要超级用户权限(因为它要求类型的C函数都准备好TOAST),而从其他设置更改为plain则根本不允许(因为类型可能已经在数据库中存在TOAST值)。请注意,更改此选项本身不会更改任何存储的数据,它只是设置将来用于创建表列的默认TOAST策略。请参见ALTER TABLE以更改现有表列的TOAST策略。
有关这些类型属性的更多详细信息,请参见CREATE TYPE。请注意,在适当的情况下,基本类型的这些属性的更改将自动传播到基于该类型的域。
ADD ATTRIBUTE、DROP ATTRIBUTE 和 ALTER ATTRIBUTE操作可以组合成一个多个更改并行应用的列表。例如,可以在单个命令中添加多个属性或更改多个属性的类型。
必须拥有该类型才能使用ALTER TYPE。要更改类型的模式,还必须对新模式具有CREATE权限。要更改所有者,您还必须是新所有者角色的直接或间接成员,并且该角色必须对类型的模式具有CREATE权限。(这些限制强制执行更改所有者不会执行您通过删除和重新创建类型无法执行的任何操作。但是,超级用户可以随意更改任何类型的所有权。)要添加属性或更改属性类型,您还必须对属性的数据类型具有USAGE权限。
参数
-
name
要修改的一个现有类型(集合类型除外)的名称(可能被模式限定)。 -
new_name
类型的新名称。 -
new_owner
类型的新所有者的用户名。 -
new_schema
类型的新模式。 -
attribute_name
要添加、更改或删除的属性的名称。 -
new_attribute_name
要重命名的属性的新名称。 -
data_type
要添加的属性的数据类型,或要更改的属性的新类型。 -
new_enum_value
要添加到枚举类型的值列表中的新值,要为现有值指定新名称,请使用ALTER TYPE ... RENAME VALUE命令。与所有枚举文字一样,它需要用引号括起来。 -
neighbor_enum_value
是现有枚举值,新值应该立即添加到它之前或之后的枚举类型的排序顺序中。与所有枚举文字一样,它需要用引号括起来。 -
existing_enum_value
是应该重命名的现有枚举值。与所有枚举文字一样,它需要用引号括起来。 -
property
是要修改的基本类型属性的名称;请参见上面的可能值。 -
CASCADE
自动将操作传播到正在更改的类型的类型化表及其后代。 -
RESTRICT
如果正在更改的类型是类型化表的类型,则拒绝操作。这是默认设置。
注意事项
如果在事务块内执行ALTER TYPE... ADD VALUE(添加新值到枚举类型的形式),则在提交事务之前无法使用新值。
涉及添加的枚举值的比较有时会比仅涉及枚举类型的原始成员的比较慢。如果在列表的末尾以外的某个位置使用BEFORE或AFTER设置新值的排序位置,则通常只会发生这种情况。但是,即使在末尾添加新值,有时也会发生这种情况(如果自枚举类型的原始创建以来OID计数器“包裹”)。减速通常是微不足道的;但是,如果它很重要,可以通过删除和重新创建枚举类型或通过转储和恢复数据库来恢复最佳性能。
示例
要重命名数据类型:
ALTER TYPE electronic_mail RENAME TO email;
将类型email的所有者更改为joe:
ALTER TYPE email OWNER TO joe;
将类型email的模式更改为customers:
ALTER TYPE email SET SCHEMA customers;
向组合类型添加新属性:
ALTER TYPE compfoo ADD ATTRIBUTE f3 int;
在特定排序位置向枚举类型添加新值:
ALTER TYPE colors ADD VALUE 'orange'AFTER 'red';
重命名枚举值:
ALTER TYPE colors RENAME VALUE 'purple' TO'mauve';
为现有基本类型创建二进制I/O函数:
CREATE FUNCTION mytypesend(mytype) RETURNS bytea ...;
CREATE FUNCTION mytyperecv(internal, oid, integer) RETURNS mytype ...;
ALTER TYPE mytype SET (
SEND = mytypesend,
RECEIVE =mytyperecv
);
兼容性
变体添加和删除属性是SQL标准的一部分;其他变体是UXsinoDB扩展。
另请参阅
ALTER USER
ALTER USER — 更改数据库角色
概要 RESET
ALTER USER role_specification [ WITH ] option [ ... ]
其中 option 可以是:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
ALTER USER name RENAME TO new_name
ALTER USER name ACCOUNT [ LOCK | UNLOCK ]
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL
其中 role_specification 可以是:
role_name
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
描述
ALTER USER现在是ALTER ROLE的别名。
兼容性
ALTER USER语句是UXsinoDB的扩展。SQL标准将用户的定义留给实现。
另请参阅
ALTER USER MAPPING
ALTER USER MAPPING — 更改用户映射的定义
概述
ALTER USER MAPPING FOR { user_name | USER | CURRENT_ROLE | CURRENT_USER | SESSION_USER | PUBLIC }
SERVER server_name
OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] )
描述
ALTER USER MAPPING更改用户映射的定义。
外部服务器的所有者可以为任何用户更改该服务器的用户映射。此外,如果已向用户授予服务器上的USAGE权限,则用户可以更改其自己的用户名的用户映射。
参数
-
user_name
映射的用户名。CURRENT_ROLE、CURRENT_USER和USER与当前用户的名称匹配。PUBLIC用于匹配系统中所有现有和未来的用户名。 -
server_name
用户映射的服务器名称。 -
OPTIONS ( [ ADD | SET | DROP ] option['value'] [, ... ])
更改用户映射的选项。新选项将覆盖任何先前指定的选项。如果没有显式指定操作,则默认为ADD。选项名称必须是唯一的;选项也由服务器的外部数据包装器进行验证。
示例
更改用户映射bob,服务器foo的密码:
ALTER USER MAPPING FOR bob SERVER foo OPTIONS (SET password 'public');
兼容性
ALTER USER MAPPING符合ISO/IEC 9075-9 (SQL/MED)标准。有一个微妙的语法问题:标准省略了FOR关键字。由于CREATE USER MAPPING和DROP USER MAPPING在类似的位置使用FOR,而IBM DB2(另一个主要的SQL/MED实现)也要求在ALTER USER MAPPING中使用它,为了一致性和互操作性,UXsinoDB在这里与标准不同。
另请参阅
CREATE USER MAPPING,DROP USER MAPPING
ALTER VIEW
ALTER VIEW —更改视图的定义
概要
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER VIEW [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER VIEW [ IF EXISTS ] name RENAME [ COLUMN ] column_name TO new_column_name
ALTER VIEW [ IF EXISTS ] name RENAME TO new_name
ALTER VIEW [ IF EXISTS ] name DROP CONSTRAINT cons_name
ALTER VIEW [ IF EXISTS ] name SET SCHEMA new_schema
ALTER VIEW [ IF EXISTS ] name SET ( view_option_name [= view_option_value] [, ... ] )
ALTER VIEW [ IF EXISTS ] name RESET ( view_option_name [, ... ] )
描述
ALTER VIEW更改视图的各种辅助属性。(如果要修改视图的定义查询,请使用CREATE OR REPLACE VIEW。)
您必须拥有该视图才能使用 ALTER VIEW。要更改视图的模式,您还必须在新模式上具有CREATE权限。要更改所有者,您还必须是新所有者的直接或间接成员,并且该角色必须在视图的模式上具有CREATE权限。(这些限制强制执行更改所有者不会执行您无法通过删除和重新创建视图来执行的任何操作。但是,超级用户可以更改任何视图的所有权。)
视图约束名增加语法,创建CHECK OPTION类型的视图可以指定视图约束名,CONSTRAINT指定约束名称,如果不指定的话UXDB依据对象id、域id等自动为约束分配名称。
视图约束删除语法,可以通过alter view命令删除视图中的视图名称。
参数
-
name
一个现有视图的名称(可选地包含模式限定符)。 -
column_name
现有列的名称。 -
new_column_name
现有列的新名称。 -
IF EXISTS
如果视图不存在,则不会引发错误。在这种情况下,会发出通知。 -
SET/DROP DEFAULT
这些形式设置或删除列的默认值。视图列的默认值将替换任何目标为视图的INSERT或UPDATE命令,在应用视图的任何规则或触发器之前。因此,视图的默认值将优先于底层关系的任何默认值。 -
new_owner
视图的新所有者的用户名。 -
new_name
视图的新名称。 -
new_schema
视图的新模式。 -
SET ( view_option_name [= view_option_value] [, ... ] )
RESET ( view_option_name [, ... ] )
设置或重置视图选项。目前支持的选项是: -
check_option (enum)
更改视图的检查选项。该值必须为local或cascaded。 -
security_barrier (boolean)
更改视图的安全屏障属性。该值必须是布尔值,例如true或false。 -
security_invoker (boolean)
更改视图的安全调用者属性。该值必须是布尔值,例如true或false。 -
CONSTRAINT cons_name
要删除的视图约束名。
注意
由于历史原因,ALTER TABLE也可以与视图一起使用;但是,允许与视图一起使用的ALTER TABLE的唯一变体等同于上面显示的变体。
兼容模式下修改表名(列名)时,视图查询报错;标准模式下修改表名(列名)时,视图查询正常。
示例
将视图foo重命名为bar:
ALTER VIEW foo RENAME TO bar;
将默认列值附加到可更新的视图:
CREATE
TABLE base_table(id int,ts timestamptz);
CREATE VIEW a_view AS SELECT * FROM base_table;
ALTER VIEW a_view ALTER COLUMN ts SET DEFAULTnow();
INSERT INTO base_table(id)VALUES(1); - ts将收到NULL
INSERT INTOa_view(id)VALUES(2); - ts将收到当前时间
兼容性
ALTER VIEW是SQL标准的UXsinoDB扩展。
另请参阅
CREATE VIEW,DROP VIEW## ANALYZE
ANALYZE — 收集关于数据库的统计信息
概要
ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ]
其中 option 可以是以下之一:
VERBOSE [ boolean ]
SKIP_LOCKED [ boolean ]
而 table_and_columns 是:
table_name [ ( column_name [, ...] ) ]
描述
ANALYZE收集数据库表的内容统计信息,并将结果存储在ux_statistic系统目录中。随后,查询规划器使用这些统计信息来帮助确定查询的最有效执行计划。
如果没有table_and_columns列表,ANALYZE处理当前用户有权限分析的当前数据库中的每个表和材料化视图。使用列表时,ANALYZE仅处理那些表。还可以为表给出列名列表,在这种情况下,仅收集这些列的统计信息。
当选项列表被括在括号中时,选项可以以任何顺序编写。
参数
-
VERBOSE
启用显示进度消息。 -
SKIP_LOCKED
指定当开始处理关系时,ANALYZE不应等待任何冲突锁被释放:如果不能立即锁定关系而不等待,则跳过该关系。请注意,即使使用此选项,ANALYZE仍然可能等待锁定。
可能仍会在打开关系索引或从分区、表继承子项和某些类型的外部表中获取样本行时阻塞。此外,虽然ANALYZE通常会处理指定分区表的所有分区,但如果分区表上存在冲突锁,则此选项将导致ANALYZE跳过所有分区。
-
boolean
指定所选选项是否应打开或关闭。您可以写TRUE、ON或1来启用该选项,写FALSE、OFF或0来禁用该选项。也可以省略boolean值,此时假定为TRUE。 -
table_name
指定要分析的特定表的名称(可能带有模式限定)。如果省略,则分析当前数据库中的所有常规表、分区表和物化视图(但不包括外部表)。如果指定的表是分区表,则同时更新分区表作为整体的继承统计信息和各个分区的统计信息。 -
column_name
指定要分析的特定列的名称。默认为所有列。
输出
当指定VERBOSE时,ANALYZE会发出进度消息,指示当前正在处理哪个表。还会打印有关表的各种统计信息。
注意事项
要分析表,通常必须是表的所有者或超级用户。但是,数据库所有者被允许分析其数据库中的所有表,除了共享目录。(共享目录的限制意味着只有超级用户才能执行真正的数据库范围的ANALYZE。)ANALYZE将跳过调用用户无权分析的任何表。
只有在显式选择时才会分析外部表。并非所有外部数据包装器都支持ANALYZE。如果表的包装器不支持ANALYZE,则该命令会打印警告并不执行任何操作。
在默认的UXsinoDB配置中,自动清理守护程序会在首次加载数据时自动分析表,并在常规操作中随着表的更改而进行。当禁用自动清理时,最好定期运行ANALYZE,或在表内容发生重大更改后立即运行。准确的统计信息将有助于规划器选择最合适的查询计划,从而提高查询处理速度。对于大多数只读数据库,常见策略是在低使用率的时间每天运行一次VACUUM和ANALYZE。(如果有大量更新活动,则这将不足够。)
ANALYZE仅需要目标表上的读锁,因此可以与表上的其他活动并行运行。
ANALYZE收集的统计信息通常包括每个列中一些最常见的值列表和显示每个列的近似数据分布的直方图。
ANALYZE是一个用于收集表统计信息的命令。这些统计信息包括每个列中最常见的值列表和直方图。如果ANALYZE认为它们不重要(例如在唯一键列中,没有常见的值),则可以省略其中一个或两个。或者,如果列数据类型不支持适当的运算符,则可以省略其中一个或两个。
对于大型表,ANALYZE会随机抽取表内容的样本,而不是检查每一行。这使得即使是非常大的表也可以在很短的时间内进行分析。但是请注意,这些统计信息只是近似值,每次运行ANALYZE时都会稍微改变,即使实际表内容没有改变。这可能会导致EXPLAIN中显示的计划程序估计成本发生微小变化。在极少数情况下,这种非确定性会导致计划程序在运行ANALYZE后更改查询计划的选择。为了避免这种情况,请按下面所述增加ANALYZE收集的统计信息量。
可以通过调整default_statistics_target配置变量或通过使用ALTER TABLE中的ALTER TABLE ... ALTER COLUMN ... SET STATISTICS在每个列上设置每列统计信息目标来控制分析的范围。目标值设置最常见值列表中的最大条目数和直方图中的最大条目数。默认目标值为100,但可以调整以在计划程序估计的准确性与ANALYZE所需时间和ux_statistic所占空间之间进行权衡。特别是,将统计目标设置为零会禁用该列的统计信息收集。对于从未用作查询的WHERE、GROUP BY或ORDER BY子句的列,这可能是有用的,因为计划程序不需要这些列的统计信息。正在分析的列中最大的统计目标确定了用于准备统计信息的表行数。增加目标会导致ANALYZE所需的时间和空间成比例增加。
ANALYZE估计的值之一是每个列中出现的不同值的数量。由于只检查了行的子集,因此即使使用最大可能的统计目标,这个估计值有时也可能非常不准确。如果这种不准确性导致查询计划不佳,则可以手动确定更准确的值,然后使用ALTER TABLE中的ALTER TABLE ... ALTER COLUMN ... SET (n_distinct =...)进行安装。
如果正在分析的表具有继承子项,则ANALYZE会收集两组统计信息:一组仅针对父表的行,另一组包括父表和所有子表的行。在处理整个继承树的查询时,需要这第二组统计信息。在这种情况下,不会单独分析子表。但是,自动清理守护程序仅在决定是否为该表触发自动分析时考虑父表本身的插入或更新。如果很少插入或更新该表,则除非手动运行ANALYZE,否则继承统计信息将不会更新。对于分区表,ANALYZE通过从所有分区中抽样行来收集统计信息;此外,它将递归进入每个分区并更新其统计信息。即使有多级分区,每个叶子分区也只会被分析一次。对于仅包含父表数据(而没有来自其分区的数据)的父表不会收集任何统计信息,因为使用分区保证它为空。
自动清理守护程序不会处理分区表,如果只有子表被修改,则也不会处理继承父表。通常需要定期运行手动ANALYZE来保持表层次结构的统计信息最新B
如果任何子表或分区是不支持ANALYZE的外部表,那么在收集继承统计信息时将忽略这些表。
如果要分析的表完全为空,则ANALYZE不会为该表记录新的统计信息。任何现有的统计信息将被保留。
运行ANALYZE的每个后端将在ux_stat_progress_analyze视图中报告其进度。
兼容性
SQL标准中没有ANALYZE语句。
另请参阅
BEGIN
BEGIN — 开始一个事务块
概要
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
其中 transaction_mode 是以下之一:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
[ NOT ] DEFERRABLE
描述
BEGIN开始一个事务块,也就是说,在BEGIN命令之后的所有语句都将在一个事务中执行,直到明确给出COMMIT或ROLLBACK命令。默认情况下(没有BEGIN),UXsinoDB在“自动提交”模式下执行事务,也就是说,每个语句都在自己的事务中执行,并在语句结束时隐式执行提交(如果执行成功,否则执行回滚)。
在事务块中执行多个语句可以更快地执行语句,因为事务的启动/提交需要大量的CPU和磁盘活动。在事务中执行多个语句还有助于确保在进行几个相关更改时保持一致性:其他会话将无法看到未完成所有相关更新的中间状态。
如果指定了隔离级别、读/写模式或可延迟模式,则新事务具有这些特性,就像执行了SET TRANSACTION一样。
参数
WORK
TRANSACTION
可选关键字。它们没有任何影响。
有关此语句的其他参数的含义,请参见SET TRANSACTION。
注意事项
START TRANSACTION具有与BEGIN相同的功能。
在已经在事务块内部时发出BEGIN将会引发警告消息。事务的状态不受影响。要在事务块内嵌套事务,请使用保存点(参见SAVEPOINT)。
出于向后兼容性的原因,可以省略连续的 transaction_modes 之间的逗号。
示例
要开始一个事务块:
BEGIN;
兼容性
BEGIN是UXsinoDB的语言扩展。它等同于SQL标准命令START TRANSACTION,其参考页面包含其他兼容性信息。
DEFERRABLE transaction_mode 是UXsinoDB的语言扩展。
顺便说一下,在嵌入式SQL中,BEGIN关键字用于不同的目的。在移植数据库应用程序时,建议您注意事务语义。
另请参阅
COMMIT、ROLLBACK、START TRANSACTION、SAVEPOINT
CALL
CALL — 调用一个过程
概要
CALL name ( [ argument ] [, ...] )
描述
CALL执行一个过程。
如果该过程有任何输出参数,则将返回一个结果行,其中包含这些参数的值。
参数
-
name
过程的名称(可选模式限定符)。 -
argument
过程调用的参数表达式。
参数可以包括参数名称,使用语法name=>value。这与普通函数调用相同。
必须为所有缺少默认值的过程参数提供参数,包括OUT参数。但是,不会评估与OUT参数匹配的参数,因此通常只需为它们编写NULL。(为OUT参数编写其他内容可能会导致与未来的UXsinoDB版本不兼容。)
注意事项
用户必须对过程具有EXECUTE权限才能允许调用它。
要调用函数(而不是过程),请改用SELECT。
如果在事务块中执行CALL,则被调用的过程不能执行事务控制语句。只有在自己的事务中执行CALL才允许事务控制语句。
PL/uxSQL以不同的方式处理输出参数在CALL命令中。
示例
CALL do_db_maintenance();
兼容性
CALL符合SQL标准,但对于输出参数的处理有所不同。标准规定用户应编写变量以接收输出参数的值。
另请参阅
CHECKPOINT
CHECKPOINT —强制写入前日志检查点
概要
CHECKPOINT
描述
检查点是写入前日志序列中的一个点,在该点之前所有数据文件都已更新以反映日志中的信息。所有数据文件都将被刷新到磁盘。
CHECKPOINT命令在发出命令时强制立即检查点,而不等待系统计划的常规检查点。CHECKPOINT不适用于正常操作。
如果在恢复期间执行,CHECKPOINT命令将强制重新启动点而不是写入新的检查点。
只有超级用户或具有ux_checkpoint角色权限的用户才能调用CHECKPOINT。
兼容性
CHECKPOINT命令是UXsinoDB语言扩展。
CLOSE
CLOSE — 关闭游标
概要
CLOSE { name | ALL }
描述
CLOSE释放与打开游标相关的资源。关闭游标后,不允许进行后续操作。当不再需要游标时,应该关闭游标。
当事务通过COMMIT或ROLLBACK终止时,每个非保持的打开游标都会被隐式关闭。如果创建它的事务通过ROLLBACK中止,则保持游标会被隐式关闭。如果创建事务成功提交,则保持游标保持打开状态,直到执行显式的CLOSE或客户端断开连接。
参数
-
name
要关闭的打开游标的名称。 -
ALL
关闭所有打开的游标。
注意事项
UXsinoDB没有显式的OPEN游标语句;当声明游标时,游标被视为打开。使用DECLARE语句声明游标。
您可以通过查询ux_cursors系统视图来查看所有可用的游标。
如果在保存点之后关闭游标,而保存点后来被回滚,则CLOSE不会被回滚;也就是说,游标保持关闭状态。
示例
关闭游标liahona:
CLOSE liahona;
兼容性
CLOSE完全符合SQL标准。CLOSE ALL是UXsinoDB的扩展。
另请参阅
CLUSTER
CLUSTER — 根据索引对表进行聚集
概述
CLUSTER [VERBOSE] table_name [ USING index_name ]
CLUSTER ( option [, ...] ) table_name [ USING index_name ]
CLUSTER [VERBOSE]
其中 option 可以是以下之一:
VERBOSE [ boolean ]
描述
CLUSTER指示UXsinoDB根据由index_name指定的索引,对由table_name指定的表进行聚集。索引必须已经在table_name上定义。
当表被聚集时,它会根据索引信息进行物理重排序。聚集是一次性操作:当随后更新表时,更改不会被聚集。也就是说,不会尝试按照它们的索引顺序存储新的或更新的行。(如果希望,可以定期通过再次发出命令来重新聚集。此外,将表的fillfactor存储参数设置为小于100%可以在更新期间保留聚集顺序,因为如果有足够的空间,更新的行会保留在同一页上。)
当表被聚集时,UXsinoDB会记住它是由哪个索引进行聚集的。形式为CLUSTER table_name的命令会使用与之前相同的索引重新聚集表。您还可以使用CLUSTER 或 SET WITHOUT CLUSTER 形式的ALTER TABLE来设置将用于将来聚集操作的索引,或清除任何先前的设置。
没有参数的CLUSTER会重新聚集当前数据库中调用用户拥有的所有以前聚集的表,或者如果由超级用户调用,则会重新聚集所有这样的表。此形式的CLUSTER不能在事务块内执行。
当表正在进行聚集时,它会获得一个ACCESS EXCLUSIVE锁。这会阻止任何其他数据库操作(包括读取和写入)在聚集完成之前对表进行操作。
参数
-
table_name
表的名称(可能带有模式限定)。 -
index_name
索引的名称。 -
VERBOSE
打印每个表聚集时的进度报告。 -
boolean
指定所选选项是否应打开或关闭。您可以写TRUE、ON或1来启用该选项,写FALSE、OFF或0来禁用该选项。也可以省略boolean值,在这种情况下,将假定为TRUE。
注意事项
在表内随机访问单个行的情况下,表中数据的实际顺序并不重要。但是,如果您倾向于访问某些数据而不是其他数据,并且有一个将它们分组在一起的索引,那么使用CLUSTER将会有所帮助。如果您从表中请求一系列索引值,或者单个索引值具有多个匹配行,则CLUSTER将有所帮助,因为一旦索引确定了与第一个匹配行相对应的表页,所有其他匹配行可能已经在同一个表页上,因此您可以节省磁盘访问并加快查询速度。
CLUSTER可以使用指定索引的索引扫描或(如果索引是B树)顺序扫描后进行排序来重新排序表。它将尝试根据规划器成本参数和可用的统计信息选择更快的方法。
当使用索引扫描时,将创建一个临时副本,其中包含按索引顺序排列的表数据。还将创建表上每个索引的临时副本。因此,您需要的磁盘空间至少等于表大小和索引大小之和。
当使用顺序扫描和排序时,还将创建一个临时排序文件,因此峰值临时空间需求至少为表大小的两倍,加上索引大小。这种方法通常比索引扫描方法更快,但如果磁盘空间要求不可接受,则可以通过临时将enable_sort设置为off来禁用此选择。
在聚集之前,建议将maintenance_work_mem设置为相当大的值(但不超过您可以用于CLUSTER操作的RAM量)。
由于规划器记录有关表排序的统计信息,因此建议在新聚集的表上运行ANALYZE。否则,规划器可能会选择不良的查询计划。
由于CLUSTER记住哪些索引已聚集,因此可以手动聚集要聚集的表,然后设置定期维护脚本,该脚本执行没有任何参数的CLUSTER,以便聚集所需的表。表可以使用CLUSTER命令进行物理重排。重排将表中的行按照指定的索引顺序重新排序,这可能会使表的扫描速度加快。重排可能需要一段时间,因此在生产环境中应该谨慎使用。在重排期间,表将被锁定,因此不能对其进行读写操作。如果没有指定索引,则使用表的主键进行重排。可以使用CLUSTER命令对整个数据库中的所有表进行重排。重排操作会定期进行重新聚集。
每个运行CLUSTER的后端都会在ux_stat_progress_cluster视图中报告其进度。
对分区表进行重排将使用指定分区索引的每个分区进行重排。在对分区表进行重排时,不能省略索引。
示例
根据其索引employee_ind对表employee进行聚集:
CLUSTER employees USING employees_ind;
使用以前使用过的相同索引对employee表进行聚集:
CLUSTER employees;
将数据库中以前聚集过的所有表聚集在一起:
CLUSTER;
兼容性
SQL标准中没有CLUSTER语句。
语法
CLUSTER index_name ON table_name
还支持与之前版本版本的兼容性。
COMMENT
COMMENT — 定义或更改对象的注释
概要
COMMENT ON
{
ACCESS METHOD object_name |
AGGREGATE aggregate_name ( aggregate_signature ) |
CAST (source_type AS target_type) |
COLLATION object_name |
COLUMN relation_name.column_name |
CONSTRAINT constraint_name ON table_name |
CONSTRAINT constraint_name ON DOMAIN domain_name |
CONVERSION object_name |
DATABASE object_name |
DOMAIN object_name |
EXTENSION object_name |
EVENT TRIGGER object_name |
FOREIGN DATA WRAPPER object_name |
FOREIGN TABLE object_name |
FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
INDEX object_name |
LARGE OBJECT large_object_oid |
MATERIALIZED VIEW object_name |
OPERATOR operator_name (left_type, right_type) |
OPERATOR CLASS object_name USING index_method |
OPERATOR FAMILY object_name USING index_method |
POLICY policy_name ON table_name |
[ PROCEDURAL ] LANGUAGE object_name |
PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
PUBLICATION object_name |
ROLE object_name |
ROUTINE routine_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
RULE rule_name ON table_name |
SCHEMA object_name |
SEQUENCE object_name |
SERVER object_name |
STATISTICS object_name |
SUBSCRIPTION object_name |
TABLE object_name |
TABLESPACE object_name |
TEXT SEARCH CONFIGURATION object_name |
TEXT SEARCH DICTIONARY object_name |
TEXT SEARCH PARSER object_name |
TEXT SEARCH TEMPLATE object_name |
TRANSFORM FOR type_name LANGUAGE lang_name |
TRIGGER trigger_name ON table_name |
TYPE object_name |
VIEW object_name
} IS 'text'
其中aggregate_signature为:
* |
[ argmode ] [ argname ] argtype [ , ... ] |
[ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ]
描述
COMMENT存储有关数据库对象的注释。
每个对象只存储一个注释字符串,因此要修改注释,请为同一对象发出新的COMMENT命令。要删除注释,请在文本字符串的位置写入NULL。当对象被删除时,注释会自动删除。
在要进行注释的对象上获取SHARE UPDATE EXCLUSIVE锁。
对于大多数类型的对象,只有对象的所有者才能设置注释。角色没有所有者,因此COMMENT ON ROLE的规则是,您必须是超级用户才能对超级用户角色进行注释,或者具有CREATEROLE特权才能对非超级用户角色进行注释。同样,访问方法也没有所有者;您必须是超级用户才能对访问方法进行注释。当然,超级用户可以对任何对象进行注释。
可以使用uxsql的\d命令系列查看注释。其他用户界面可以在uxsql使用的相同内置函数之上构建,即obj_description、col_description和shobj_description。
参数
-
object_name
relation_name.column_name
aggregate_name
constraint_name
function_name
operator_name
policy_name
procedure_name
routine_name
rule_name
trigger_name
要注释的对象的名称。在模式中(表、函数等)的对象名称可以带有模式限定符。在注释列时,relation_name必须引用表、视图、组合类型或外部表。 -
table_name
domain_name
在创建约束、触发器、规则或策略的注释时,这些参数指定定义该对象的表或域的名称。 -
source_type
转换的源数据类型的名称。 -
target_type
转换的目标数据类型的名称。 -
argmode
函数、过程或聚合参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。请注意,COMMENT实际上不会关注OUT参数,因为只需要输入参数即可确定函数的标识。因此,列出IN、INOUT和VARIADIC参数即可。 -
argname
函数、过程或聚合参数的名称。请注意,COMMENT实际上不会关注参数名称,因为只需要参数数据类型即可确定函数的标识。 -
argtype
函数、过程或聚合参数的数据类型。 -
large_object_oid
大对象的OID。 -
left_type
right_type
运算符参数的数据类型(可选模式限定符)。对于前缀运算符的缺失参数,请写NONE。 -
PROCEDURAL
这是一个噪声词。 -
type_name
变换数据类型的名称。 -
lang_name
变换语言的名称。 -
text
新的注释,写成字符串文字;或者NULL表示删除注释。
注释
目前没有查看注释的安全机制:连接到数据库的任何用户都可以查看该数据库中对象的所有注释。对于共享对象,例如数据库、角色和表空间,注释存储在全局,因此连接到群集中任何数据库的任何用户都可以查看共享对象的所有注释。因此,不要在注释中放置安全关键信息。
示例
附加注释到表mytable:
COMMENT ON TABLE mytable IS 'This is my table.';
再次删除它:
COMMENT ON TABLE mytable IS NULL;
一些更多的例子:
COMMENT ON ACCESS METHOD gin IS 'GIN index access method';
COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance';
COMMENT ON CAST (text AS int4) IS 'Allow casts from text to int4';
COMMENT ON COLLATION "fr_CA" IS 'Canadian French';
COMMENT ON COLUMN my_table.my_column IS 'Employee ID number';
COMMENT ON CONVERSION my_conv IS 'Conversion to UTF8';
COMMENT ON CONSTRAINT bar_col_cons ON bar IS 'Constrains column col';
COMMENT ON CONSTRAINT dom_col_constr ON DOMAIN dom IS 'Constrains col of domain';
COMMENT ON DATABASE my_database IS 'Development Database';
COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
COMMENT ON EVENT TRIGGER abort_ddl IS 'Aborts all DDL commands';
COMMENT ON EXTENSION hstore IS 'implements the hstore data type';
COMMENT ON FOREIGN DATA WRAPPER mywrapper IS 'my foreign data wrapper';
COMMENT ON FOREIGN TABLE my_foreign_table IS 'Employee Information in other database';
COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral';
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee ID';
COMMENT ON LANGUAGE plpython IS 'Python support for stored procedures';
COMMENT ON LARGE OBJECT 346344 IS 'Planning document';
COMMENT ON MATERIALIZED VIEW my_matview IS 'Summary of order history';
COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts';
COMMENT ON OPERATOR - (NONE, integer) IS 'Unary minus';
COMMENT ON OPERATOR CLASS int4ops USING btree IS '4 byte integer operators for btrees';
COMMENT ON OPERATOR FAMILY integer_ops USING btree IS 'all integer operators for btrees';
COMMENT ON POLICY my_policy ON mytable IS 'Filter rows by users';
COMMENT ON PROCEDURE my_proc (integer, integer) IS 'Runs a report';
COMMENT ON PUBLICATION alltables IS 'Publishes all operations on all tables';
COMMENT ON ROLE my_role IS 'Administration group for finance tables';
COMMENT ON ROUTINE my_routine (integer, integer) IS 'Runs a routine (which is a function or procedure)';
COMMENT ON RULE my_rule ON my_table IS 'Logs updates of employee records';
COMMENT ON SCHEMA my_schema IS 'Departmental data';
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
COMMENT ON SERVER myserver IS 'my foreign server';
COMMENT ON STATISTICS my_statistics IS 'Improves planner row estimations';
COMMENT ON SUBSCRIPTION alltables IS 'Subscription for all operations on all tables';
COMMENT ON TABLE my_schema.my_table IS 'Employee Information';
COMMENT ON TABLESPACE my_tablespace IS 'Tablespace for indexes';
COMMENT ON TEXT SEARCH CONFIGURATION my_config IS 'Special word filtering';
COMMENT ON TEXT SEARCH DICTIONARY swedish IS 'Snowball stemmer for Swedish language';
对于文本搜索解析器my_parser的注释是“将文本拆分为单词”;对于文本搜索模板snowball的注释是“Snowball词干提取器”;对于语言为plpython3u的hstore转换的注释是在“hstore和Python字典之间进行转换”;对于my_table上的my_trigger触发器的注释是“用于RI”;对于复数数据类型的注释是“复数数据类型”;对于my_view视图的注释是“部门成本视图”。
兼容性
SQL标准中没有COMMENT命令。
COMMIT
COMMIT - 提交当前事务
概要
COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
描述
COMMIT提交当前事务。事务所做的所有更改对其他人都是可见的,并且如果发生崩溃,则保证是持久的。
参数
-
WORK
TRANSACTION
可选关键字。它们没有任何影响。 -
AND CHAIN
如果指定了AND CHAIN,则立即启动一个具有相同事务特性(请参见SET TRANSACTION)的新事务。否则,不会启动新事务。
注释
使用ROLLBACK来中止事务。
在不在事务内时发出COMMIT不会造成任何伤害,但它会引发警告消息。在不在事务内时发出AND CHAIN是错误的。
示例
要提交当前事务并使所有更改永久生效:
COMMIT;
兼容性
命令COMMIT符合SQL标准。形式COMMIT TRANSACTION是UXsinoDB的扩展。
另请参阅
COMMIT PREPARED
COMMIT PREPARED — 提交先前准备好的两阶段提交事务
概要
COMMIT PREPARED transaction_id
描述
COMMIT PREPARED提交处于准备状态的事务。
参数
transaction_id
要提交的事务标识符。
注意事项
要提交准备好的事务,必须是原始执行事务的相同用户或超级用户。但是,您不必在执行事务的同一会话中。
此命令不能在事务块内执行。准备好的事务会立即提交。
所有当前可用的准备好的事务都列在ux_prepared_xacts系统视图中。
示例
提交由事务标识符foobar标识的事务:
COMMIT PREPARED 'foobar';
兼容性
COMMIT PREPARED是UXsinoDB的扩展。它旨在供外部事务管理系统使用,其中一些系统受标准(如X/Open XA)的覆盖,但这些系统的SQL部分未经标准化。
另请参阅
PREPARE TRANSACTION,ROLLBACK PREPARED
COPY
COPY — 在文件和表之间复制数据
概要
COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
[ WHERE condition ]
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
TO { 'filename' | PROGRAM 'command' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
其中 option 可以是以下之一:
FORMAT format_name
PLCOLS [ boolean ]
FREEZE [ boolean ]
DELIMITER 'delimiter_character'
NULL 'null_string'
HEADER [ boolean ]
QUOTE 'quote_character'
ESCAPE 'escape_character'
FORCE_QUOTE { ( column_name [, ...] ) | * }
FORCE_NOT_NULL ( column_name [, ...] )
FORCE_NULL ( column_name [, ...] )
ENCODING 'encoding_name'
MERGE [ boolean ]
IGNORE [ boolean ]
描述
COPY在UXsinoDB表和标准文件系统文件之间移动数据。COPY TO将表的内容复制到文件中,而COPY FROM将数据从文件复制到表中(将数据附加到表中已有的数据)。COPY TO还可以复制SELECT查询的结果。
如果指定了列列表,则COPY TO仅复制指定的列。如果未指定列,则复制整个表。如果指定了查询,则COPY TO将查询结果复制到文件中。
COPY FROM将文件中的数据复制到表中。文件中的每一行都被视为一个要插入到表中的行。如果指定了列,则每行中的值必须与指定的列匹配。如果未指定列,则文件中的每一行必须包含与表中的列相同数量的值,以按顺序插入到表中。
COPY命令可以使用WHERE子句来限制要复制的行。此外,可以使用WITH子句指定选项,例如分隔符、引号字符和空值字符串。
COPY命令还可以使用PROGRAM选项来执行外部命令,并将其输出作为输入复制到表中或从表中复制到文件中。
在指定的列中将数据复制到文件中。对于COPY FROM,文件中的每个字段按顺序插入到指定的列中。未在COPY FROM列列表中指定的表列将接收其默认值。
使用文件名的COPY指示UXsinoDB服务器直接从文件读取或写入文件。文件必须可被UXsinoDB用户(服务器运行的用户ID)访问,并且名称必须从服务器的视角指定。当指定PROGRAM时,服务器执行给定的命令并从程序的标准输出读取,或将输出写入程序的标准输入。命令必须从服务器的视角指定,并且可由UXsinoDB用户执行。当指定STDIN或STDOUT时,数据通过客户端和服务器之间的连接传输。
每个运行COPY的后端将在ux_stat_progress_copy视图中报告其进度。
COPY FROM命令还可以使用MERGE/IGNORE选项来支持特定的增量还原功能。主要是对存在着唯一约束或主键约束冲突的还原功能增强。
参数
-
table_name
现有表的名称(可选模式限定符)。 -
column_name
要复制的列的可选列表。如果未指定列列表,则将复制表的所有列,除了生成的列。 -
query
要复制其结果的SELECT、VALUES、INSERT、UPDATE或DELETE命令。请注意,需要在查询周围使用括号。
对于INSERT、UPDATE和DELETE查询,必须提供一个RETURNING子句,并且目标关系不能有条件规则,也不能有扩展为多个语句的ALSO规则或INSTEAD规则。
-
filename
输入或输出文件的路径名。输入文件名可以是绝对或相对路径,但输出文件名必须是绝对路径。Windows用户可能需要使用E''字符串,并且在路径名中加倍任何反斜杠。 -
PROGRAM
要执行的命令。在COPY FROM中,输入从命令的标准输出读取,在COPY TO中,输出写入命令的标准输入。
请注意,命令由shell调用,因此如果您需要传递来自不受信任的源的任何参数的shell命令,必须小心地剥离或转义可能对shell具有特殊含义的任何特殊字符。出于安全原因,最好使用固定的命令字符串,或者至少避免在其中传递任何用户输入。
-
STDIN
指定输入来自客户端应用程序。 -
STDOUT
指定输出到客户端应用程序。 -
boolean
指定所选选项是否应打开或关闭。您可以写入TRUE、ON或1来启用该选项,写入FALSE、OFF或0来禁用该选项。也可以省略boolean值,此时假定为TRUE。 -
FORMAT
选择要读取或写入的数据格式:text、csv(逗号分隔值)或binary。默认为text。 -
FREEZE
请求复制已经冻结行的数据,就像运行VACUUM FREEZE命令后一样。这是用于初始数据加载的性能选项。只有在当前子事务中创建或截断正在加载的表、没有打开游标并且该事务没有保留旧快照的情况下,才会冻结行。目前无法在分区表上执行COPY FREEZE。
请注意,一旦成功加载数据,所有其他会话将立即能够看到数据。这违反了MVCC可见性的正常规则,指定此选项的用户应该意识到可能会引起的潜在问题。
-
DELIMITER指定文件中每行(行)中分隔列的字符。在文本格式中,默认为制表符,在CSV格式中为逗号。必须是单个一字节字符。使用binary格式时不允许使用此选项。 -
NULL
指定表示空值的字符串。在文本格式中,默认为\N(反斜杠-N),在CSV格式中为未引用的空字符串。在某些情况下,您可能希望在文本格式中使用空字符串,而不是区分空值和空字符串。使用binary格式时不允许使用此选项。
注意
使用COPY FROM时,与此字符串匹配的任何数据项都将存储为null值,因此应确保使用与COPY TO中使用的相同字符串。
-
HEADER
指定文件包含一个带有文件中每个列的名称的标题行。在输出中,第一行包含表中的列名称。在输入时,当此选项设置为true(或等效的布尔值)时,第一行将被丢弃。如果将此选项设置为MATCH,则标题行中的列数和名称必须按顺序与表的实际列名称匹配;否则会引发错误。使用binary格式时不允许使用此选项。MATCH选项仅适用于COPY FROM命令。 -
QUOTE
指定在引用数据值时要使用的引用字符。默认为双引号。这必须是一个单字节字符。此选项仅在使用CSV格式时允许。 -
ESCAPE
指定在数据字符与QUOTE值匹配时应出现的字符。默认值与QUOTE值相同(因此,如果引用字符出现在数据中,则会将其加倍)。这必须是一个单字节字符。此选项仅在使用CSV格式时允许。 -
FORCE_QUOTE
强制对每个指定列中的所有非NULL值使用引用。NULL输出永远不会被引用。如果指定了*,则所有列中的非NULL值都将被引用。此选项仅在使用CSV格式时允许,并且仅在COPY TO中使用。 -
FORCE_NOT_NULL
不将指定列的值与空字符串匹配。在默认情况下,空字符串为空,这意味着即使未引用,空值也将被读取为零长度字符串而不是NULL。此选项仅在使用CSV格式时允许,并且仅在COPY FROM中使用。 -
FORCE_NULL
将指定列的值与空字符串匹配,即使已引用,如果找到匹配,则将该值设置为NULL。在默认情况下,空字符串为空,这将把引用的空字符串转换为NULL。此选项仅在使用CSV格式时允许,并且仅在COPY FROM中使用。 -
ENCODING
指定文件编码为encoding_name。如果省略此选项,则使用当前客户端编码。有关更多详细信息,请参见下面的注释。 -
WHERE
可选的WHERE子句的一般形式为
WHERE condition
其中 condition 是任何计算结果为boolean类型的表达式。任何不满足此条件的行都不会插入到表中。如果将实际行值替换为任何变量引用,则行满足条件,如果返回true,则行满足条件。
目前,在WHERE表达式中不允许子查询,并且评估不会看到COPY本身所做的任何更改(当表达式包含对VOLATILE函数的调用时,这很重要)。
-
MERGE
在copy from命令中提供MERGE选项时,使用来自文件的数据更新冲突元组,非冲突数据正常可以正常插入。 -
IGNORE
在copy from命令中提供MERGE选项时,忽略来自文件中的冲突数据,保留原表中的冲突数据,同时向原表中来自插入文件的非冲突数据。
注意
merge与ignore选项同时只能提供一个,merge与ignore选项必须与copy from联用,即只有还原过程可以使用。它不干扰不存在唯一约束或主键的还原过程。
输出
成功完成后,COPY命令将返回一个命令标记,其形式为
COPY count
其中 count 是复制的行数。
注意
如果命令不是COPY ... TO STDOUT,或等效的uxsql元命令\copy ... to stdout,则uxsql仅会打印此命令标记。这是为了防止混淆。命令标记与刚刚打印的数据一起使用。
注释
COPY TO只能用于普通表,不能用于视图,并且不会复制子表或子分区中的行。例如,COPY table TO复制的行与SELECT * FROM ONLY table相同。语法COPY (SELECT * FROM table) TO ...可用于转储继承层次结构、分区表或视图中的所有行。
COPY FROM可用于普通、外部或分区表,也可用于具有INSTEAD OF INSERT触发器的视图。
您必须对由COPY TO读取的表具有选择权限,并对由COPY FROM插入值的表具有插入权限。在命令中列出的列具有列权限即可。
如果为表启用了行级安全性,则相关的SELECT策略将适用于COPY table TO语句。目前,不支持对启用了行级安全性的表使用COPY FROM。请改用等效的INSERT语句。
COPY命令中命名的文件由服务器直接读取或写入,而不是由客户端应用程序读取。因此,它们必须驻留在或可访问数据库服务器机器,而不是客户端。它们必须对UXsinoDB用户(服务器运行的用户ID)可访问并可读或可写,而不是客户端。同样,使用PROGRAM指定的命令由服务器直接执行,而不是由客户端应用程序执行,必须由UXsinoDB用户可执行。只有数据库超级用户或被授予ux_read_server_files、ux_write_server_files或ux_execute_server_program角色之一的用户才允许使用命名为COPY的文件或命令,因为它允许读取或写入任何服务器具有访问权限的文件或运行程序。
不要将COPY与uxsql指令\copy混淆。\copy调用COPY FROM STDIN或COPY TO STDOUT,然后在可由uxsql客户端访问的文件中获取/存储数据。因此,文件可访问性和访问权限取决于使用\copy时的客户端,而不是服务器。
建议始终将在COPY中使用的文件名指定为绝对路径。这在COPY TO的情况下由服务器强制执行,但对于COPY FROM,您可以选择从由相对路径指定的文件中读取。路径将相对于服务器进程的工作目录(通常是群集的数据目录),而不是客户端的工作目录进行解释。
使用PROGRAM执行命令可能会受到操作系统的访问控制机制(例如SELinux)的限制。
COPY FROM将调用目标表上的任何触发器和检查约束。但是,它不会调用规则。
对于标识列,COPY FROM命令将始终写入输入数据中提供的列值,就像INSERT选项OVERRIDING SYSTEM VALUE一样。
DateStyle会影响COPY的输入和输出。为了确保可移植性到可能使用非默认DateStyle设置的其他UXsinoDB安装,应在使用COPY TO之前将DateStyle设置为ISO。此外,最好避免使用设置为sql_standard的IntervalStyle导出数据,因为负间隔值可能会被具有不同IntervalStyle设置的服务器误解。
输入数据根据ENCODING选项或当前客户端编码进行解释,输出数据则使用ENCODING或当前客户端编码进行编码,即使数据不通过客户端而是直接由服务器从文件中读取或写入。
COPY在第一个错误处停止操作。这在COPY TO的情况下不会导致问题,但目标表已经接收了COPY FROM中的早期行。这些行将不可见或不可访问,但它们仍然占用磁盘空间。如果故障发生在大型复制操作的中途,这可能会导致相当大量的浪费磁盘空间。您可能希望调用VACUUM来恢复浪费的空间。
FORCE_NULL和FORCE_NOT_NULL可以同时用于同一列。这将导致将带引号的空字符串转换为null值,将不带引号的空字符串转换为空字符串。
文件格式
文本格式
当使用text格式时,读取或写入的数据是一个文本文件,每个表行占用一行。行中的列由分隔符字符分隔。列值本身是由每个属性数据类型的输出函数生成或接受的字符串。指定的null字符串用于代替null列。
COPY FROM如果输入文件的任何行包含比预期的列数更多或更少的列,则会引发错误。
数据的结尾可以由仅包含反斜杠句点(\.)的单行表示。当使用pre-3.0客户端协议的客户端应用程序复制数据时,不需要数据结束标记,因为文件结束已经足够;只有在将数据复制到或从使用非3.0客户端协议的客户端应用程序时才需要。
反斜杠字符(\)可以用于在COPY数据中引用可能被视为行或列分隔符的数据字符。特别是,如果以下字符作为列值的一部分出现,则必须在其前面加上反斜杠:反斜杠本身、换行符、回车符和当前分隔符字符。
指定的null字符串由COPY TO发送,而不添加任何反斜杠;相反,COPY FROM在删除反斜杠之前将输入与null字符串进行匹配。因此,null字符串(例如\N)不能与实际数据值\N混淆(该值将表示为\\N)。
COPY FROM识别下列特殊的反斜杠序列:
| 序列 | 表示 |
|---|---|
\b | 退格(ASCII 8) |
\f | 换页符(ASCII 12) |
\n | 换行符(ASCII 10) |
\r | 回车符(ASCII 13) |
\t | 制表符(ASCII 9) |
\v | 垂直制表符(ASCII 11) |
\数字 | 反斜杠后跟一到三个八进制数字指定该数字代码的字节 |
\x数字 | 反斜杠 x 后跟一到两个十六进制数字指定该数字代码的字节 |
目前,COPY TO永远不会发出八进制或十六进制数字反斜杠序列,但它确实使用上述其他序列来表示这些控制字符。
任何其他未在上表中提到的反斜杠字符都将被视为代表它本身。但是,要小心不必要地添加反斜杠,因为这可能会意外地产生与数据结束标记(\.)或空字符串(默认为\N)匹配的字符串。在进行任何其他反斜杠处理之前,这些字符串将被识别。
强烈建议生成COPY数据的应用程序将数据换行符和回车符转换为\n和\r序列。目前,可以通过反斜杠和回车符来表示数据回车符,并通过反斜杠和换行符来表示数据换行符。但是,这些表示可能在未来的版本中不被接受。如果将COPY文件传输到不同的计算机(例如从Unix到Windows或反之),它们也极易受到损坏。
在编码转换之后解释所有反斜杠序列。使用八进制和十六进制数字反斜杠序列指定的字节必须在数据库编码中形成有效字符。
COPY TO将使用Unix风格的换行符(“\n”)终止每行。在Microsoft Windows上运行的服务器会输出回车符/换行符(“\r\n”),但仅适用于将COPY复制到服务器文件;为了在各个平台上保持一致,COPY TO STDOUT总是发送“\n”,而不管服务器平台如何。COPY FROM可以处理以换行符、回车符或回车符/换行符结尾的行。为了减少由于未反斜杠化的换行符或回车符而产生的错误风险,如果输入中的行结束不相同,COPY FROM将发出警告。
CSV 格式**
此格式选项用于导入和导出许多其他程序(例如电子表格)使用的逗号分隔值(CSV)文件格式。它不使用UXsinoDB的标准文本格式所使用的转义规则,而是生成和识别常见的CSV转义机制。
每个记录中的值由DELIMITER分隔。字符。如果值包含分隔符字符、QUOTE字符、NULL字符串、回车或换行符,则整个值将由QUOTE字符前缀和后缀,并且值内的任何QUOTE字符或ESCAPE字符的出现都将由转义字符前缀。您还可以使用FORCE_QUOTE在输出特定列中的非NULL值时强制使用引号。
CSV格式没有标准的方法来区分NULL值和空字符串。UXsinoDB的COPY通过引用来处理这个问题。一个NULL被输出为NULL参数字符串,并且不被引用,而与NULL参数字符串匹配的非NULL值则被引用。例如,使用默认设置,NULL被写为未引用的空字符串,而空字符串数据值则用双引号("")写入。读取值遵循类似的规则。您可以使用FORCE_NOT_NULL来防止特定列的NULL输入比较。您还可以使用FORCE_NULL将带引号的空字符串数据值转换为NULL。
由于反斜杠在CSV格式中不是特殊字符,因此数据值\.(数据结束标记)也可能出现。为避免任何误解,出现在一行上的单个\.数据值会在输出时自动引用,在输入时,如果被引用,则不会被解释为数据结束标记。如果您正在加载由其他应用程序创建的具有单个未引用列的文件,并且可能具有\.的值,则可能需要在输入文件中引用该值。
注意
在CSV格式中,所有字符都是重要的。由空格或任何字符包围的引用值,而不是DELIMITER,将包括这些字符。如果您从填充CSV行的系统导入数据,该系统会将其填充到某个固定宽度以外的空格,则可能会导致错误。如果出现这种情况,您可能需要预处理CSV文件以删除尾随空格,然后将数据导入UXsinoDB。
CSV格式将识别并生成包含嵌入式回车和换行符的带引号值的CSV文件。因此,这些文件不像文本格式文件那样严格地每行一个表行。
许多程序生成奇怪且偶尔是反常的CSV文件,因此文件格式更多是一种约定而不是标准。因此,您可能会遇到一些无法使用此机制导入的文件,而COPY可能会生成其他程序无法处理的文件。
二进制格式
binary格式选项导致所有数据都以二进制格式而不是文本格式存储/读取。它比文本和CSV格式略快,但二进制格式文件在机器体系结构和UXsinoDB版本之间的可移植性较差。此外,二进制格式非常特定于数据类型;例如,二进制格式不适用于跨不同计算机体系结构的数据传输。
即使在文本格式中可以正常工作,但从smallint列输出二进制数据并将其读入integer列是行不通的。binary文件格式由文件头、零个或多个包含行数据的元组以及文件尾组成。头部和数据以网络字节顺序存储。
文件头
文件头由15个字节的固定字段组成,后跟一个可变长度的头部扩展区域。固定字段为:
- 签名
11字节的序列UXCOPY\n\377\r\n\0—注意零字节是签名的必要部分。(该签名旨在方便识别被非8位清洁传输破坏的文件。该签名将被行结束转换过滤器、删除零字节、删除高位或奇偶校验更改所更改。)
- 标记字段
32位整数位掩码,用于表示文件格式的重要方面。位从0(LSB)到31(MSB)编号。请注意,该字段以网络字节顺序存储(最高有效字节在前),文件格式中使用的所有整数字段也是如此。位16-31保留用于表示关键文件格式问题;如果读取器发现在此范围内设置了意外的位,则应中止。位0-15保留用于表示向后兼容的格式问题;如果读取器发现在此范围内设置了任何意外的位,则应简单地忽略它们。目前仅定义了一个标志位,其余必须为零:
-
位16
如果为1,则数据中包含OID;如果为0,则不包含。OID系统列不再受UXsinoDB支持,但格式仍包含指示符。
-
头部扩展区域
32位整数,标头剩余部分的长度(不包括自身)(以字节为单位)。目前,这是零,第一个元组紧随其后。将来的格式更改可能允许在标头中存在其他数据。读取器应该默默地跳过它不知道如何处理的任何标头扩展数据。
头部扩展区域被设计为包含一系列自我识别的块。标志字段不打算告诉读取器扩展区域中有什么。标头扩展内容的具体设计留待以后的版本。
该设计允许向后兼容的头部添加(添加头部扩展块或设置低位标志位)和非向后兼容的更改(设置高位标志位以表示这样的更改,并在需要时添加扩展区域的支持数据)。
元组
每个元组以一个16位整数计数开始,该计数表示元组中字段的数量。(目前,表中的所有元组都将具有相同的计数,但这可能不总是正确的。)然后,对于元组中的每个字段,都有一个32位长度字,后跟该字段的字节数。(长度字不包括自身,可以为零。)作为特殊情况,-1表示NULL字段值。在NULL情况下不会跟随任何值字节。字段之间没有对齐填充或任何其他额外数据。目前,二进制格式文件中的所有数据值都假定为二进制格式(格式代码为1)。预计将来的扩展可能会添加一个头字段,允许指定每列格式代码。要确定实际元组数据的适当二进制格式,您应该查阅UXsinoDB源代码,特别是每个列数据类型的*send和*recv函数(通常这些函数在源分发的src/backend/utils/adt/目录中找到)。
如果文件中包含OID,则OID字段紧随字段计数字之后。它是一个普通字段,除了它不包括在字段计数中。请注意,当前版本的UXsinoDB不支持OID系统列。
文件尾
文件尾由一个包含-1的16位整数字组成。这很容易与元组的字段计数字区分开来。
如果字段计数字既不是-1也不是预期的列数,则读取器应报告错误。这提供了一种额外的检查,以防止与数据同步出现问题。
示例
以下示例使用竖线(|)作为字段分隔符将表复制到客户端:
COPY country TO STDOUT (DELIMITER '|');
将数据从文件复制到country表中:
COPY country FROM '/usr1/proj/bray/sql/country_data';
将以'A'开头的国家名称复制到文件中:
COPY (SELECT * FROM country WHERE country_name LIKE 'A%') TO '/usr1/proj/bray/sql/a_list_countries.copy';
要将数据复制到压缩文件中,可以通过外部压缩程序传输输出:
COPY country TO PROGRAM 'gzip > /usr1/proj/bray/sql/country_data.gz';
以下是适合从STDIN复制到表中的数据示例:
AF AFGHANISTAN
AL ALBANIA
DZ ALGERIA
ZM ZAMBIA
ZW ZIMBABWE
请注意,每行上的空格实际上是制表符。
以下是相同数据的二进制格式输出。在通过Unix实用程序od -c过滤后,显示数据。表具有三列;第一列具有类型char(2),第二列具有类型text,第三列具有类型integer。所有行在第三列中都有空值。
0000000 P G C O P Y \n 377 \r \n \0 \0 \0 \0 \0 \0
0000020 \0 \0 \0 \0 003 \0 \0 \0 002 A F \0 \0 \0 013 A
0000040 F G H A N I S T A N 377 377 377 377 \0 003
0000060 \0 \0 \0 002 A L \0 \0 \0 007 A L B A N I
0000100 A 377 377 377 377 \0 003 \0 \0 \0 002 D Z \0 \0 \0
0000120 007 A L G E R I A 377 377 377 377 \0 003 \0 \0
0000140 \0 002 Z M \0 \0 \0 006 Z A M B I A 377 377
0000160 377 377 \0 003 \0 \0 \0 002 Z W \0 \0 \0 \b Z I
0000200 M B A B W E 377 377 377 377 377 377
兼容性
SQL标准中没有COPY语句。
支持如下语法:
COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | STDIN }
[ [ WITH ]
[ BINARY ]
[ DELIMITER [ AS ] 'delimiter_character' ]
[ NULL [ AS ] 'null_string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote_character' ]
[ ESCAPE [ AS ] 'escape_character' ]
[ FORCE NOT NULL column_name [,...] ] ] ]
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
TO { 'filename' | STDOUT }
[ [ WITH ]
[ BINARY ]
[ DELIMITER [ AS ] 'delimiter_character' ]
[ NULL [ AS ] 'null_string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote_character' ]
[ ESCAPE [ AS ] 'escape_character' ]
[FORCE QUOTE { `column_name` [, ...] | * } ] ] ]
请注意,在此语法中,BINARY 和 CSV 被视为独立的关键字,而不是 FORMAT 选项的参数。
在UXsinoDB之前版本使用以下语法,目前仍然受支持:
COPY [ BINARY ] table_name
FROM { 'filename' | STDIN }
[ [USING] DELIMITERS 'delimiter_character' ]
[ WITH NULL AS 'null_string' ]
COPY [ BINARY ] table_name
TO { 'filename' | STDOUT }
[ [USING] DELIMITERS 'delimiter_character' ]
[ WITH NULL AS 'null_string' ]
CREATE ACCESS METHOD
CREATE ACCESS METHOD — 定义新的访问方法
概要
CREATE ACCESS METHOD name
TYPE access_method_type
HANDLER handler_function
描述
CREATE ACCESS METHOD 创建新的访问方法。
访问方法名称必须在数据库中唯一。
只有超级用户才能定义新的访问方法。
参数
-
name
要创建的访问方法的名称。 -
access_method_type
此子句指定要定义的访问方法的类型。目前仅支持TABLE和INDEX。 -
handler_function
handler_function是先前注册的函数的名称(可能是模式限定的),表示访问方法。处理程序函数必须声明为接受类型为internal的单个参数,其返回类型取决于访问方法的类型;对于TABLE访问方法,它必须是table_am_handler,对于INDEX访问方法,它必须是index_am_handler。处理程序函数必须实现的C级API因访问方法的类型而异。
示例
创建一个名为heptree的索引访问方法,其处理程序函数为heptree_handler:
CREATE ACCESS METHOD heptree TYPE INDEX HANDLER heptree_handler;
兼容性
CREATE ACCESS METHOD 是 UXsinoDB 的扩展功能。
另请参阅
DROP ACCESS METHOD、CREATE OPERATOR CLASS、CREATE OPERATOR FAMILY。
CREATE AGGREGATE
CREATE AGGREGATE —定义新的聚合函数
概要
CREATE [ OR REPLACE ] AGGREGATE name ( [ argmode ] [ argname ] arg_data_type [ , ... ] ) (
SFUNC = sfunc,
STYPE = state_data_type
[ , SSPACE = state_data_size ]
[ , FINALFUNC = ffunc ]
[ , FINALFUNC_EXTRA ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , COMBINEFUNC = combinefunc ]
[ , SERIALFUNC = serialfunc ]
[ , DESERIALFUNC = deserialfunc ]
[ , INITCOND = initial_condition ]
[ , MSFUNC = msfunc ]
[ , MINVFUNC = minvfunc ]
[ , MSTYPE = mstate_data_type ]
[ , MSSPACE = mstate_data_size ]
[ , MFINALFUNC = mffunc ]
[ , MFINALFUNC_EXTRA ]
[ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , MINITCOND = minitial_condition ]
[ , SORTOP = sort_operator ]
[ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
)
CREATE [ OR REPLACE ] AGGREGATE name ( [ [ argmode ] [ argname ] arg_data_type [ , ... ] ]
ORDER BY [ argmode ] [ argname ] arg_data_type [ , ... ] ) (
SFUNC = sfunc,
STYPE = state_data_type
[ , SSPACE = state_data_size ]
[ , FINALFUNC = ffunc ]
[ , FINALFUNC_EXTRA ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , INITCOND = initial_condition ]
[ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
[ , HYPOTHETICAL ]
)
或者旧的语法:
CREATE [ OR REPLACE ] AGGREGATE name (
BASETYPE = base_type,
SFUNC = sfunc,
STYPE = state_data_type
[ , SSPACE = state_data_size ]
[ , FINALFUNC = ffunc ]
[ , FINALFUNC_EXTRA ]
[ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , COMBINEFUNC = combinefunc ]
[ , SERIALFUNC = serialfunc ]
[ , DESERIALFUNC = deserialfunc ]
[ , INITCOND = initial_condition ]
[ , MSFUNC = msfunc ]
[ , MINVFUNC = minvfunc ]
[ , MSTYPE = mstate_data_type ]
[ , MSSPACE = mstate_data_size ]
[ , MFINALFUNC = mffunc ]
[ , MFINALFUNC_EXTRA ]
[ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ]
[ , MINITCOND = minitial_condition ]
[ , SORTOP = sort_operator ]
)
描述
CREATE AGGREGATE定义了一个新的聚合函数。CREATE OR REPLACE AGGREGATE可以定义一个新的聚合函数或替换现有的定义。一些基本和常用的聚合函数已经包含在发行版中。如果定义了新类型或需要一个尚未提供的聚合函数,则可以使用CREATE AGGREGATE提供所需的功能。
在替换现有定义时,参数类型、结果类型和直接参数的数量不能更改。此外,新定义必须与旧定义相同(普通聚合、有序集聚合或假设集聚合)。
如果给出模式名称(例如,CREATE AGGREGATE myschema.myagg ...),则聚合函数将在指定的模式中创建。否则,它将在当前模式中创建。
聚合函数由其名称和输入数据类型标识。如果两个聚合在同一个模式中具有相同的名称,则它们可以在不同的输入类型上运行。聚合的名称和输入数据类型也必须与同一模式中每个普通函数的名称和输入数据类型不同。这个行为与普通函数名称的重载相同(参见CREATE FUNCTION)。
简单的聚合函数由一个或两个普通函数组成:一个状态转换函数sfunc和一个可选的最终计算函数ffunc。它们的使用如下:
sfunc( internal-state, next-data-values ) ---> next-internal-state
ffunc( internal-state ) ---> aggregate-value
UXsinoDB 创建一个临时变量,其数据类型为stype,以保存聚合的当前内部状态。在每个输入行中,计算聚合参数值并将其传递给sfunc函数,该函数将返回下一个内部状态。在处理完所有输入行后,如果定义了ffunc函数,则将最终内部状态传递给该函数以计算最终聚合值。状态转换函数被调用时,会传入当前状态值和新的参数值来计算新的内部状态值。在处理完所有行之后,最终函数会被调用一次来计算聚合的返回值。如果没有最终函数,则结束状态值会原样返回。
聚合函数可以提供一个初始条件,即内部状态值的初始值。这被指定并存储在数据库中作为类型为text的值,但它必须是状态值数据类型的常量的有效外部表示。如果没有提供,则状态值起始为null。
如果状态转换函数被声明为“strict”,则不能使用null输入调用它。对于这样的转换函数,聚合执行的行为如下。具有任何null输入值的行将被忽略(函数不会被调用,之前的状态值将被保留)。如果初始状态值为null,则在第一行具有所有非null输入值时,第一个参数值将替换状态值,并在每个随后的行中使用所有非null输入值调用转换函数。这对于实现像max这样的聚合非常方便。请注意,仅当state_data_type与第一个arg_data_type相同时,才可用此行为。当这些类型不同时,必须提供一个非null的初始条件或使用非严格的转换函数。
如果状态转换函数不是严格的,则它将在每个输入行中无条件地被调用,并且必须自己处理null输入和null状态值。这允许聚合作者完全控制聚合对null值的处理。
如果最终函数被声明为“strict”,则当结束状态值为null时,它将不会被调用;相反,将自动返回null结果。(当然,这只是严格函数的正常行为。)在任何情况下,最终函数都可以选择返回null值。例如,avg的最终函数在看到没有输入行时返回null。
有时将最终函数声明为不仅接受状态值,还接受与聚合输入值相对应的额外参数是有用的。这样做的主要原因是如果最终函数是多态的,状态值的数据类型将不足以确定结果类型。这些额外参数始终传递为NULL(因此当使用FINALFUNC_EXTRA选项时,最终函数不能是严格的),但它们仍然是有效的参数。例如,最终函数可以利用get_fn_expr_argtype来识别当前调用中的实际参数类型。
聚合可以选择支持移动聚合模式。这需要指定MSFUNC、MINVFUNC和MSTYPE参数,以及可选的MSSPACE、MFINALFUNC、MFINALFUNC_EXTRA、MFINALFUNC_MODIFY和MINITCOND参数。除了MINVFUNC之外,这些参数的工作方式类似于不带M的相应简单聚合参数;它们定义了一个包括反转换函数的聚合的单独实现。
在参数列表中带有ORDER BY的语法创建了一种特殊类型的聚合函数,称为有序集合聚合;如果指定了HYPOTHETICAL,则创建一个假设集合聚合。这些聚合函数在排序值的组中以依赖于顺序的方式运作,因此指定输入排序顺序是调用的重要部分。此外,它们可以有直接参数,这些参数仅在每个聚合中计算一次,而不是每个输入行计算一次。假设集合聚合是有序集合聚合的一个子类,在其中一些直接参数需要匹配,以匹配聚合参数列的数量和数据类型。这允许这些直接参数的值被添加到聚合输入行的集合中作为一个额外的“假设”行。
聚合函数可以选择支持部分聚合。这需要指定COMBINEFUNC参数。如果state_data_type是internal,通常还应提供SERIALFUNC和DESERIALFUNC参数,以便进行并行聚合。请注意,聚合必须标记为PARALLEL SAFE才能启用并行聚合。
行为类似于MIN或MAX的聚合函数有时可以通过查看索引而不是扫描每个输入行来进行优化。如果可以这样优化此聚合函数,请指定一个排序操作符。基本要求是聚合函数必须产生由操作符引起的排序顺序中的第一个元素;换句话说:
SELECT agg(col) FROM tab;
必须等同于:
SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
进一步的假设是聚合函数忽略空输入,并且仅在没有非空输入时提供空结果。通常,数据类型的<运算符是MIN的适当排序操作符,>是MAX的适当排序操作符。请注意,除非指定的操作符是B-tree索引操作符类的“小于”或“大于”策略成员,否则优化永远不会实际生效。
要能够创建聚合函数,您必须对参数类型、状态类型和返回类型具有USAGE权限,以及对支持函数具有EXECUTE权限。
参数
-
name
要创建的聚合函数的名称(可选模式限定)。 -
argmode
参数的模式:IN或VARIADIC。(聚合函数不支持OUT参数。)如果省略,则默认为IN。只有最后一个参数可以标记为VARIADIC。 -
argname
参数名称。目前仅用于文档目的。如果省略,则参数没有名称。 -
arg_data_type
此聚合函数操作的输入数据类型。要创建零参数聚合函数,请在参数规范列表的位置写入*。(这样的聚合的一个示例是count(*)。) -
base_type
在CREATE AGGREGATE的旧语法中,输入数据类型由basetype参数指定,而不是写在聚合名称旁边。请注意,此语法仅允许一个输入参数。要使用此语法定义零参数聚合函数,请将basetype指定为"ANY"(而不是*)。无法使用旧语法定义有序集聚合。 -
sfunc
每个输入行调用的状态转换函数的名称。对于普通的N参数聚合函数,sfunc必须采用N+1个参数,第一个参数是state_data_type类型,其余参数与聚合的声明输入数据类型匹配。该函数必须返回state_data_type类型的值。此函数接受当前状态值和当前输入数据值,并返回下一个状态值。
对于有序集(包括虚拟集)聚合,状态转换函数仅接收当前状态值和聚合参数,而不是直接参数。否则,它是相同的。
-
state_data_type
聚合状态值的数据类型。 -
state_data_size
聚合状态值的近似平均大小(以字节为单位)。如果省略此参数或为零,则使用基于state_data_type的默认估计值。规划器使用此值来估计分组聚合查询所需的内存。 -
ffunc
在遍历所有输入行后计算聚合结果的最终函数的名称。对于普通聚合,此函数必须采用state_data_type类型的单个参数。聚合的返回数据类型定义为此函数的返回类型。如果未指定ffunc,则使用结束状态值作为聚合结果,并且返回类型为state_data_type。
对于有序集(包括虚拟集)聚合,最终函数不仅接收最终状态值,还接收所有直接参数的值。
如果指定了FINALFUNC_EXTRA,则除了最终状态值和任何直接参数之外,最终函数还接收额外的NULL值,这些值对应于聚合的常规(聚合)参数。这主要用于允许在定义多态聚合时正确解析聚合结果类型。
FINALFUNC_MODIFY= {READ_ONLY|SHAREABLE|READ_WRITE}
该选项指定最终函数是否为纯函数,不修改其参数。
READ_ONLY表示不修改参数;另外两个值表示它可能会更改转换状态值。有关更多详细信息,请参见下面的“注释”。默认值为READ_ONLY,但对于有序集聚合,其默认值为READ_WRITE。
combinefunc
可以选择指定combinefunc函数,以允许聚合函数支持部分聚合。如果提供,则combinefunc必须将两个包含对某些输入值进行聚合的结果的state_data_type值组合起来,以产生表示聚合两个输入集的结果的新state_data_type。可以将此函数视为sfunc,其中不是作用于单个输入行并将其添加到运行聚合状态中,而是将另一个聚合状态添加到运行状态中。
combinefunc必须声明为具有state_data_type的两个参数,并返回state_data_type的值。在这种情况下,此函数可以是“严格的”。在这种情况下,当任一输入状态为空时,将不调用该函数;将采用另一个状态作为正确的结果。
对于state_data_type为internal的聚合函数,combinefunc不能是严格的。在这种情况下,combinefunc必须确保正确处理空状态,并且返回的状态正确存储在聚合内存上下文中。
-
serialfunc
如果聚合函数的state_data_type为internal,则只有具有serialfunc函数的聚合函数才能参与并行聚合,该函数必须将聚合状态序列化为bytea值以传输到另一个进程。此函数必须采用类型internal的单个参数,并返回类型bytea。还需要相应的deserialfunc。 -
deserialfunc
将先前序列化的聚合状态反序列化回state_data_type。此函数必须采用类型bytea和internal的两个参数,并产生类型internal的结果。(注意:第二个internal参数未使用,但出于类型安全原因需要。) -
initial_condition
状态值的初始设置。这必须是数据类型state_data_type接受的形式的字符串常量。如果未指定,则状态值开始为空。 -
msfunc
要为每个输入行调用的前向状态转换函数的名称在移动聚合模式下输入行。这与常规转换函数完全相同,只是它的第一个参数和结果是类型为mstate_data_type的,这可能与state_data_type不同。 -
minvfunc
要在移动聚合模式下使用的反状态转换函数的名称。此函数具有与msfunc相同的参数和结果类型,但用于从当前聚合状态中删除值,而不是向其中添加值。逆转换函数必须具有与正向状态转换函数相同的严格属性。 -
mstate_data_type
在使用移动聚合模式时,聚合状态值的数据类型。 -
mstate_data_size
在使用移动聚合模式时,聚合状态值的近似平均大小(以字节为单位)。这与state_data_size的工作方式相同。 -
mffunc
在所有输入行遍历后调用的最终函数的名称,用于计算聚合的结果,当使用移动聚合模式时。这与ffunc的工作方式相同,只是它的第一个参数类型为mstate_data_type,并且通过编写MFINALFUNC_EXTRA来指定额外的虚拟参数。由mffunc或mstate_data_type确定的聚合结果类型必须与聚合的常规实现确定的类型相匹配。 -
MFINALFUNC_MODIFY= {READ_ONLY|SHAREABLE|READ_WRITE}
此选项类似于FINALFUNC_MODIFY,但描述了移动聚合最终函数的行为。 -
minitial_condition
在使用移动聚合模式时,状态值的初始设置。这与initial_condition的工作方式相同。 -
sort_operator
MIN或MAX类似聚合的相关排序运算符。这只是一个运算符名称(可能是模式限定的)。假定运算符具有与聚合相同的输入数据类型(聚合必须是单参数正常聚合)。 -
PARALLEL ={SAFE|RESTRICTED|UNSAFE}
PARALLEL SAFE、PARALLEL RESTRICTED和PARALLEL UNSAFE的含义与CREATE FUNCTION中的含义相同。如果将聚合标记为PARALLEL UNSAFE(默认值!)或PARALLEL RESTRICTED,则不会考虑并行化聚合。请注意,计划程序不会查看聚合支持函数的并行安全标记,只会查看聚合本身的标记。 -
HYPOTHETICAL
仅适用于有序集聚合,此标志指定聚合参数应根据虚拟集合聚合的要求进行处理:即,最后几个直接参数必须与聚合(WITHIN GROUP)参数的数据类型匹配。HYPOTHETICAL标志对运行时行为没有影响,只对聚合参数的数据类型和排序解析时间产生影响。
CREATE AGGREGATE的参数可以按任何顺序编写,而不仅仅是上面所示的顺序。
注意事项
在指定支持函数名称的参数中,如果需要,可以写入模式名称,例如SFUNC=public.sum。但是,请勿在此处编写参数类型-支持函数的参数类型是从其他参数确定的。
通常,UXsinoDB函数应该是真正的函数,不应修改其输入值。但是,聚合转换函数在聚合的上下文中使用时,允许欺骗并直接修改其转换状态参数。与每次制作转换状态的新副本相比,这可以提供显着的性能优势。
同样地,虽然通常期望聚合最终函数不修改其输入值,但有时无法避免修改转换状态参数。必须使用FINALFUNC_MODIFY参数声明此类行为。READ_WRITE值表示最终函数以未指定的方式修改转换状态。此值防止将聚合用作窗口函数,并且还防止合并共享相同输入值和转换函数的聚合调用的转换状态。SHAREABLE值表示转换函数无法在最终函数之后应用,但可以对结束转换状态值执行多个最终函数调用。此值防止将聚合用作窗口函数,但允许合并转换状态。(也就是说,这里感兴趣的优化不是重复应用相同的最终函数,而是将不同的最终函数应用于相同的结束转换状态值。只要没有一个最终函数被标记为READ_WRITE,就允许这样做。)
如果聚合支持移动聚合模式,则在将聚合用作具有移动帧开始的窗口函数(即,帧开始模式不是UNBOUNDED PRECEDING)的窗口时,它将提高计算效率。从概念上讲,正向转换函数在从底部进入窗口帧的输入值时将其添加到聚合状态中,而反向转换函数在它们从顶部离开帧时再次将它们移除。因此,当值被移除时,它们总是按添加顺序移除。每当调用反向转换函数时,它都将接收到最早添加但尚未删除的参数值。反向转换函数可以假定在删除最旧的行后,当前状态中至少会保留一行。(当不是这种情况时,窗口函数机制只需开始新的聚合,而不是使用反向转换函数。)
移动聚合模式的正向转换函数不允许返回NULL作为新状态值。如果反向转换函数返回NULL,则将其视为无法为此特定输入反转状态计算,因此将从当前帧起始位置重新计算聚合计算。这种约定使得聚合计算可以在窗口帧内进行,而不必在每个行之间重新开始。允许在存在一些不可逆转的运行状态值的情况下使用移动聚合模式。
如果没有提供移动聚合实现,则仍然可以使用移动帧的聚合,但是UXsinoDB将在帧的起始位置移动时重新计算整个聚合。请注意,无论聚合是否支持移动聚合模式,UXsinoDB都可以处理移动帧的结束而无需重新计算;这是通过继续向聚合状态中添加新值来完成的。这就是为什么将聚合用作窗口函数需要最终函数是只读的原因:它不能破坏聚合的状态值,以便即使已经为一组帧边界获得了聚合结果值,聚合也可以继续。
有序集聚合的语法允许为最后一个直接参数和最后一个聚合(WITHIN GROUP)参数指定VARIADIC。但是,当前的实现限制了VARIADIC的使用方式。首先,有序集聚合只能使用VARIADIC "any",而不能使用其他可变数组类型。其次,如果最后一个直接参数是VARIADIC "any",则只能有一个聚合参数,它也必须是VARIADIC "any"。如果聚合是假设集聚合,则与VARIADIC "any"参数匹配的直接参数是假设参数;任何前置参数都表示不受限制的附加直接参数,不必与聚合参数匹配。
目前,有序集聚合不需要支持移动聚合模式,因为它们不能用作窗口函数。
有序集聚合当前不支持部分(包括并行)聚合。此外,它永远不会用于包括DISTINCT或ORDERBY子句的聚合调用,因为这些语义在部分聚合期间无法支持。
兼容性
CREATE AGGREGATE是UXsinoDB的语言扩展。SQL标准不提供用户定义的聚合函数。
另请参阅
参见ALTER AGGREGATE ,DROP AGGREGATE。
CREATE CAST
CREATE CAST — 定义新的造型
概要
CREATE CAST (source_type AS target_type)
WITH FUNCTION function_name [ (argument_type [, ...]) ]
[ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST (source_type AS target_type)
WITHOUT FUNCTION
[ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST (source_type AS target_type)
WITH INOUT
[ AS ASSIGNMENT | AS IMPLICIT ]
描述
CREATE CAST定义新的造型。造型指定如何在两个数据类型之间进行转换。例如,
SELECT CAST(42 AS float8);
通过调用先前指定的函数(在本例中为float8(int4)),将整数常量42转换为类型float8。(如果没有定义合适的造型,则转换失败。)
两种类型可以是二进制可强制转换,这意味着可以执行转换而不需要调用任何函数。这要求相应的值使用相同的内部表示。例如,类型text和varchar在两个方向上都是二进制可强制转换的。二进制可强制转换不一定是对称关系。例如,从xml到text的转换可以在当前实现中免费执行,但反向方向需要执行至少语法检查的函数。(两种二进制可强制转换的类型也称为二进制兼容。)
您可以使用WITH INOUT语法将造型定义为I/O转换造型。通过调用源数据类型的输出函数,并将结果字符串传递给目标数据类型的输入函数来执行I/O转换造型。在许多常见情况下,此功能避免了编写单独的输入和输出函数的需要。
可以使用WITH FUNCTION语法定义一个造型,该语法指定了一个函数,该函数将源类型转换为目标类型。可以使用WITHOUT FUNCTION语法定义一个造型,该语法指定了一个无需函数即可执行的转换。
可以使用AS ASSIGNMENT或AS IMPLICIT选项指定造型的类型。如果指定了AS ASSIGNMENT,则造型被视为赋值造型,这意味着可以将源类型的值分配给目标类型的变量。如果指定了AS IMPLICIT,则造型被视为隐式造型,这意味着可以在查询中隐式地使用造型。
I/O转换造型的作用与常规基于函数的造型相同;只是实现方式不同。默认情况下,只有在显式造型请求时才能调用造型,即显式的造型(x AS typename)或x::typename构造。
如果将造型标记为AS ASSIGNMENT,则在将值分配给目标数据类型的列时隐式调用它。例如,假设foo.f1是类型为text的列,则如果从类型integer到类型text的造型标记为AS ASSIGNMENT,则允许执行以下操作:
INSERT INTO foo (f1) VALUES (42);
如果将整型转换为文本类型标记为ASSIGNMENT,则不允许。(我们通常使用术语赋值类型来描述这种类型的类型。)
如果将造型标记为AS IMPLICIT,则可以在任何上下文中隐式调用它,无论是分配还是在表达式中内部调用它。我们通常使用术语隐式造型来描述这种类型的造型。例如,考虑以下查询:
SELECT 2 + 4.0;
解析器最初将常量标记为类型integer和numeric。系统目录中没有integer+numeric运算符,但是有numeric+numeric运算符。因此,如果可用并标记为AS IMPLICIT的从integer到numeric的造型,则查询将成功执行,实际上就是这样。解析器将应用隐式造型并解析查询,就好像它已经写成:
SELECT CAST (2 AS numeric ) + 4.0;
现在,目录还提供了从numeric到integer的造型。如果该造型标记为AS IMPLICIT,则解析器将面临选择上述解释和将numeric常量转换为integer并应用integer+integer运算符的替代方案。由于缺乏任何关于哪种选择更好的知识,它会放弃并声明查询模糊不清。只有两个造型中的一个是implicit的这一事实是我们教解析器优先将混合numeric和integer表达式的解析结果作为numeric的方式;没有关于这方面的内置知识。
在将造型标记为implicit时要保守。过多的隐式造型路径可能会导致UXsinoDB选择令人惊讶的命令解释,或者根本无法解析命令,因为有多个可能的解释。一个好的经验法则是,仅对在同一一般类型类别中的类型之间进行信息保留转换的造型进行隐式调用。例如,从int2到int4的造型可以合理地是implicit,但从float8到int4的造型可能只能是assignment-only。最好将跨类型类别的造型(例如,从text到int4)设置为仅显式。
注意
有时出于可用性或符合标准的原因,需要在一组类型之间提供多个隐式转换,导致无法避免上述的歧义。解析器具有基于类型类别和首选类型的回退启发式方法,可以帮助在这种情况下提供所需的行为。有关更多信息,请参见CREATE TYPE。
要能够创建转换,您必须拥有源数据类型或目标数据类型,并在另一个类型上具有USAGE特权。要创建二进制可强制转换的转换,您必须是超级用户。(这个限制是因为错误的二进制可强制转换转换可以轻松地使服务器崩溃。)
参数
-
source_type
转换的源数据类型的名称。 -
target_type
转换的目标数据类型的名称。 -
function_name[(argument_type[,...])]
用于执行转换的函数。函数名称可以带有模式限定符。如果没有,将在模式搜索路径中查找该函数。函数的结果数据类型必须与转换的目标类型匹配。下面讨论了它的参数。如果未指定参数列表,则函数名称必须在其模式中是唯一的。 -
WITHOUT FUNCTION
表示源类型可以二进制强制转换为目标类型,因此不需要函数执行转换。 -
WITH INOUT
表示转换是一个I/O转换转换,通过调用源数据类型的输出函数,并将结果字符串传递给目标数据类型的输入函数来执行。 -
AS ASSIGNMENT
表示转换可以在赋值上下文中隐式调用。 -
AS IMPLICIT
表示转换可以在任何上下文中隐式调用。
转换实现函数可以有一个到三个参数。第一个参数类型必须与转换的源类型相同或可以二进制强制转换。如果存在第二个参数,则必须是类型integer;它接收与目标类型关联的类型修饰符,如果没有,则为-1。如果存在第三个参数,则必须是类型boolean;如果转换是显式转换,则它接收true,否则为false。(奇怪的是,在某些情况下,SQL标准对显式和隐式转换要求不同的行为。为必须实现这种转换的函数提供此参数。不建议您设计自己的数据类型,以便这很重要。)
转换函数的返回类型必须与转换的目标类型相同或可以二进制强制转换。
通常,转换必须具有不同的源和目标数据类型。但是,如果具有多个参数的转换实现函数,则允许声明具有相同源和目标类型的转换。这用于表示系统目录中的特定于类型的长度强制转换函数。命名函数用于将类型的值强制转换为其第二个参数给定的类型修饰符值。
当一个转换具有不同的源类型和目标类型,并且一个函数需要多个参数时,它支持在单个步骤中从一种类型转换为另一种类型并应用长度强制转换。当没有这样的条目可用时,强制转换为使用类型修饰符的类型涉及两个转换步骤,一个用于在数据类型之间进行转换,另一个用于应用修饰符。
目前,对域类型的转换没有影响。对域进行转换使用与其基础类型相关联的转换。
注释
使用DROP CAST删除用户定义的转换。
请记住,如果您想能够双向转换类型,则需要明确地声明双向转换。
通常不需要创建用户定义类型和标准字符串类型(text、varchar和char(n),以及定义为字符串类别的用户定义类型)之间的转换。UXsinoDB为此提供了自动I/O转换转换。自动转换为字符串类型被视为赋值转换,而自动转换从字符串类型是显式的。您可以通过声明自己的转换来覆盖此行为,以替换自动转换,但通常唯一的原因是您希望转换比标准的仅赋值或仅显式设置更容易调用。另一个可能的原因是您希望转换的行为与类型的I/O函数不同;但这足够令人惊讶,以至于您应该三思而后行,是否这是一个好主意。(内置类型中有少量类型确实具有不同的转换行为,主要是由于SQL标准的要求。)
虽然不是必需的,但建议您继续遵循将转换实现函数命名为目标数据类型的旧约定。许多用户习惯于使用函数样式表示法转换数据类型,即typename(x)。实际上,这种表示法实际上只是调用转换实现函数的调用;它没有特别对待为转换。如果您的转换函数没有命名以支持此约定,则会使用户感到惊讶。由于UXsinoDB允许使用不同的参数类型重载相同的函数名称,因此从不同类型到目标类型的多个转换函数都使用目标类型的名称没有任何困难。
注意
实际上,前面的段落过于简单化了:在两种情况下,函数调用结构将被视为强制转换请求,而无需与实际函数匹配。如果函数调用名称(x)不完全匹配任何现有函数,但name是数据类型的名称,并且ux_cast提供了从x类型到该类型的二进制强制转换,那么该调用将被解释为二进制强制转换。这个例外是为了使二进制强制转换可以使用函数语法调用,即使它们缺少任何函数。同样,如果没有ux_cast条目,但是强制转换是字符串类型的,那么调用将被解释为I/O转换强制转换。此异常允许使用函数语法调用I/O转换强制转换。
这个例外还有一个例外:从组合类型到字符串类型的I/O转换强制转换不能使用函数语法调用,而必须使用显式强制转换语法(CAST或::符号)编写。之所以添加这个异常,是因为在引入自动提供的I/O转换强制转换之后,发现当需要函数或列引用时,很容易意外地调用这种强制转换。
示例
创建从类型bigint到类型int4的赋值强制转换,使用函数int4(bigint):
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;
(此强制转换已在系统中预定义。)
兼容性
CREATE CAST命令符合SQL标准,但SQL不为二进制可强制转换类型或实现函数提供额外参数。AS IMPLICIT也是UXsinoDB的扩展。
另请参阅
CREATE FUNCTION,CREATE TYPE, DROP CAST
CREATE COLLATION
CREATE COLLATION — 定义新的排序规则
概要
CREATE COLLATION [ IF NOT EXISTS ] name (
[ LOCALE = locale, ]
[ LC_COLLATE = lc_collate, ]
[ LC_CTYPE = lc_ctype, ]
[ PROVIDER = provider, ]
[ DETERMINISTIC = boolean, ]
[ VERSION = version ]
)
CREATE COLLATION [ IF NOT EXISTS ] name FROM existing_collation
描述
CREATE COLLATION使用指定的操作系统区域设置或复制现有的排序规则来定义新的排序规则。
要创建排序规则,必须在目标模式上拥有CREATE权限。
参数
-
IF NOT EXISTS
如果已存在同名的排序规则,则不会抛出错误。在这种情况下,会发出通知。请注意,不能保证现有的排序规则与将要创建的排序规则相似。 -
name
排序规则的名称。排序规则名称可以是模式限定的。如果没有,则在当前模式中定义排序规则。排序规则名称必须在该模式中唯一。(系统目录可以包含其他编码的同名排序规则,但如果数据库编码不匹配,则会忽略这些规则。) -
locale
这是设置LC_COLLATE和LC_CTYPE的快捷方式。如果指定了此参数,则不能指定这两个参数之一。 -
lc_collate
使用指定的操作系统区域设置来设置LC_COLLATE区域类别。 -
lc_ctype
使用指定的操作系统区域设置作为LC_CTYPE区域设置的语言环境。 -
provider
指定用于与此排序相关的语言环境服务的提供程序。可能的值为:icu,libc。默认为libc。可用的选择取决于操作系统和构建选项。 -
DETERMINISTIC
指定排序是否应使用确定性比较。默认值为true。确定性比较将不是字节相等的字符串视为不相等,即使它们在逻辑上被认为是相等的。UXsinoDB使用字节比较来打破平局。不确定性比较可能会使排序变得不区分大小写或不区分重音符号。为此,您需要选择适当的LC_COLLATE设置,并在此处将排序设置为不确定性。
仅支持使用 ICU 提供程序的不确定性排序。
version
指定要与排序一起存储的版本字符串。通常应省略此选项,这将导致版本从操作系统提供的排序的实际版本计算出来。此选项旨在由ux_upgrade用于从现有安装中复制版本。
有关如何处理排序版本不匹配的信息,请参见ALTER COLLATION。
existing_collation
要复制的现有排序的名称。新排序将具有与现有排序相同的属性,但它将是一个独立的对象。
注释
CREATE COLLATION在ux_collation系统目录上获取SHARE ROW EXCLUSIVE锁,这是自相矛盾的,因此一次只能运行一个CREATE COLLATION命令。
使用DROP COLLATION删除用户定义的排序。
当使用libc排序提供程序时,语言环境必须适用于当前数据库编码。有关详细规则,请参见CREATE DATABASE。
示例
要从操作系统区域设置fr_FR.utf8(假设当前数据库编码为UTF8)创建排序:
CREATE COLLATION french (locale = 'fr_FR.utf8');
要使用 ICU提供程序使用德语电话簿排序顺序创建排序:
CREATE COLLATION german_phonebook (provider = icu, locale = 'de-u-co-phonebk');
要从现有排序创建排序:
CREATE COLLATION german FROM "de_DE";
这可以方便地使用与操作系统无关的排序名称在应用程序中使用。
兼容性
SQL标准中有一个CREATE COLLATION语句,但它仅限于复制现有的排序规则。创建新的排序规则的语法是UXsinoDB的扩展。
另请参阅
ALTER COLLATION,DROP COLLATION
CREATE CONVERSION
CREATE CONVERSION — 定义新的编码转换
概要
CREATE [ DEFAULT ] CONVERSION name
FOR source_encoding TO dest_encoding FROM function_name
描述
CREATE CONVERSION定义两个字符集编码之间的新转换。
标记为DEFAULT的转换可用于客户端和服务器之间的自动编码转换。为了支持该用法,必须定义从编码A到B的两个转换,以及从编码B到A的两个转换。
要能够创建转换,必须对函数具有EXECUTE权限,并对目标模式具有CREATE权限。
参数
-
DEFAULT
DEFAULT子句表示此转换是特定源到目标编码的默认转换。模式中应只有一个默认编码对。 -
name
转换的名称。转换名称可以是模式限定的。如果不是,则在当前模式中定义转换。转换名称必须在模式内唯一。 -
source_encoding
源编码名称。 -
dest_encoding
目标编码名称。 -
function_name
用于执行转换的函数。函数名称可以是模式限定的。如果不是,则将在路径中查找该函数。
函数必须具有以下签名:
conv_proc(
integer, -- 源编码 ID
integer, -- 目标编码 ID
CREATE CONVERSION conversion_name FOR source_encoding TO destination_encoding FROM function_name (
cstring, -- source string (null terminated C string)
internal, -- destination (fill with a null terminated C string)
integer, -- source string length
boolean -- if true, don't throw an error if conversion fails
) RETURNS integer;
返回值是成功转换的源字节数。如果最后一个参数为false,则函数必须在无效输入时抛出错误,返回值始终等于源字符串长度。
注释
源编码和目标编码都不能是SQL_ASCII,因为对于涉及SQL_ASCII“编码”的情况,服务器的行为是硬编码的。
使用DROP CONVERSION删除用户定义的转换。
创建转换所需的权限可能会在将来的版本中更改。
示例
创建从编码UTF8到LATIN1的转换,使用myfunc:
CREATE CONVERSION myconv FOR 'UTF8' TO 'LATIN1' FROM myfunc;
兼容性
CREATE CONVERSION是UXsinoDB的扩展。SQL标准中没有CREATE CONVERSION语句,但有一个非常类似于目的和语法的CREATE TRANSLATION语句。
另请参阅
ALTER CONVERSION、CREATE FUNCTION、DROP CONVERSION
CREATE DATABASE
CREATE DATABASE — 创建新数据库
概要
CREATE DATABASE name
[ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ STRATEGY [=] strategy ] ]
[ LOCALE [=] locale ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ ICU_LOCALE [=] icu_locale ]
[ LOCALE_PROVIDER [=] locale_provider ]
[ COLLATION_VERSION = collation_version ]
[ TABLESPACE [=] tablespace_name ]
[ ALLOW_CONNECTIONS [=] allowconn ]
[ CONNECTION LIMIT [=] connlimit ]
[ IS_TEMPLATE [=] istemplate ]
[ OID [=] oid ]
描述
CREATE DATABASE创建一个新的UXsinoDB数据库。
要创建数据库,您必须是超级用户或具有特殊的CREATEDB权限。请参见CREATE ROLE 。
默认情况下,新数据库将通过克隆标准系统数据库template1来创建。可以通过编写TEMPLATE name来指定不同的模板。特别地,通过编写TEMPLATE template0,您可以创建一个原始的数据库(其中不存在用户定义的对象,系统对象也没有被修改)仅包含由您的版本的UXsinoDB预定义的标准对象。如果您希望避免复制任何安装本地对象,这将非常有用。
参数
-
name
要创建的数据库的名称。 -
user_name
将拥有新数据库的用户的角色名称,或者使用默认值(即执行命令的用户)的DEFAULT。要创建由另一个角色拥有的数据库,您必须是该角色的直接或间接成员,或者是超级用户。 -
template
从中创建新数据库的模板的名称,或者使用默认模板(template1)的DEFAULT。 -
encoding
在新数据库中使用的字符集编码。指定一个字符串常量(例如'SQL_ASCII'),或者一个整数编码数字,或者使用默认编码(即模板数据库的编码)。有关更多限制,请参见下文。 -
strategy
创建新数据库时要使用的策略。如果使用WAL_LOG策略,则会逐块复制数据库,并将每个块单独写入预写日志。这是在模板数据库较小的情况下最有效的策略,因此它是默认值。旧的FILE_COPY策略也可用。此策略为目标数据库使用的每个表空间写入预写日志中的一个小记录。每个这样的记录表示将整个目录复制到文件系统级别的新位置。虽然这确实大大减少了预写日志的体积,特别是如果模板数据库很大,但它也强制系统在创建新数据库之前和之后执行检查点。在某些情况下,这可能会对整体系统性能产生明显的负面影响。 -
locale
这是一种同时设置LC_COLLATE和LC_CTYPE的快捷方式。
提示
其他语言环境设置lc_messages、lc_monetary、lc_numeric和lc_time不是每个数据库固定的,也不是由此命令设置的。如果要将它们设置为特定数据库的默认值,可以使用ALTER DATABASE ... SET。
-
lc_collate
在新数据库中使用的排序顺序(LC_COLLATE)。这会影响应用于字符串的排序顺序,例如在具有ORDER BY的查询中,以及在文本列上使用的索引中使用的顺序。默认值是使用模板数据库的排序顺序。有关更多限制,请参见下文。 -
lc_ctype
在新数据库中使用的字符分类(LC_CTYPE)。数据库。这会影响字符的分类,例如小写、大写和数字。默认情况下,使用模板数据库的字符分类。有关其他限制,请参见下文。 -
icu_locale
如果使用ICU区域设置提供程序,则指定ICU区域设置ID。 -
locale_provider
指定在此数据库中使用的默认排序规则提供程序。可能的值为:icu,libc。默认为libc。可用的选择取决于操作系统和构建选项。 -
collation_version
指定要存储在数据库中的排序版本字符串。通常应省略此选项,这将导致版本从操作系统提供的数据库排序的实际版本计算出来。此选项旨在由ux_upgrade使用,用于从现有安装中复制版本。
有关如何处理数据库排序版本不匹配的信息,请参见ALTER DATABASE 。
-
tablespace_name
将与新数据库关联的表空间的名称,或DEFAULT以使用模板数据库的表空间。此表空间将是在此数据库中创建的对象使用的默认表空间。有关详细信息,请参见CREATE TABLESPACE。 -
allowconn
如果为 false,则无人可以连接到此数据库。默认为true,允许连接(除非受其他机制的限制,例如GRANT/REVOKE CONNECT)。 -
connlimit
可以同时连接到此数据库的并发连接数。-1(默认值)表示没有限制。 -
istemplate
如果为 true,则任何具有CREATEDB特权的用户都可以克隆此数据库;如果为false(默认值),则只有超级用户或数据库所有者可以克隆它。 -
oid
要用于新数据库的对象标识符。如果未指定此参数,则UXsinoDB将自动选择合适的OID。此参数主要供ux_upgrade内部使用,只有ux_upgrade可以指定小于16384的值。
可选参数可以按任何顺序编写,不仅限于上面的顺序。
注意事项
无法在事务块内执行CREATE DATABASE。
类似于“无法初始化数据库目录”的错误最可能与数据目录上的权限不足、磁盘已满或其他文件系统问题有关。
使用DROP DATABASE删除数据库。程序createdb是一个包装程序,为方便起见提供。
通过ALTER DATABASE设置的数据库级配置参数和数据库级权限(通过GRANT设置)不会从模板数据库复制。
虽然可以通过将其名称指定为模板来复制除template1之外的数据库,但这不是(尚未)作为通用“COPY DATABASE”设施而设计的。主要限制是在复制模板数据库时不能连接其他会话。如果在启动时存在任何其他连接,则CREATE DATABASE将失败;否则,对模板数据库的新连接将被锁定,直到CREATE DATABASE完成。
为新数据库指定的字符集编码必须与选择的区域设置(LC_COLLATE和LC_CTYPE)兼容。如果区域设置为C(或等效于POSIX),则允许使用所有编码,但对于其他区域设置,只有一种编码可以正常工作。(但是,在Windows上,UTF-8编码可以与任何区域设置一起使用。)CREATE DATABASE将允许超级用户指定SQL_ASCII编码,而不考虑区域设置,但是这个选择已经被弃用,如果存储在数据库中的数据与区域设置不兼容,则可能导致字符串函数的错误行为。
编码和区域设置必须与模板数据库的编码和区域设置匹配,除非使用template0作为模板。这是因为其他数据库可能包含与指定编码不匹配的数据,或者可能包含受LC_COLLATE和LC_CTYPE影响的排序顺序的索引。复制这样的数据将导致根据新设置损坏的数据库。template0已知不包含任何受影响的数据或索引。
目前没有使用具有非确定性比较的数据库区域设置的选项(请参见CREATE COLLATION以获取说明)。如果需要此功能,则需要使用每列排序规则。
CONNECTION LIMIT选项仅大约执行;如果在数据库仅剩一个连接“插槽”时同时启动两个新会话,则两者都可能失败。此外,该限制不适用于超级用户或后台工作进程。
示例
创建一个新数据库:
CREATE DATABASE lusiadas;
创建一个由用户salesapp拥有的名为sales的数据库,并使用默认表空间salesspace:
CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;
创建一个具有不同区域设置的数据库music:
CREATE DATABASE music
LOCALE 'sv_SE.utf8'TEMPLATE template0;
在这个例子中,如果指定的语言环境与template1中的语言环境不同,则需要使用TEMPLATE template0子句。(如果它们相同,则显式指定语言环境是多余的。)
要创建一个具有不同语言环境和不同字符集编码的数据库music2:
CREATE DATABASE music2
LOCALE 'sv_SE.iso885915'
ENCODING LATIN9
TEMPLATE template0;
指定的语言环境和编码设置必须匹配,否则会报错。
请注意,语言环境名称是特定于操作系统的,因此上述命令可能无法在所有地方以相同的方式工作。
兼容性
SQL标准中没有CREATE DATABASE语句。数据库等同于目录,其创建是实现定义的。
另请参阅
CREATE DATABASE LINK
CREATE DATABASE LINK — 创建数据库链接
概要
CREATE [ PUBLIC ] DATABASE LINK linkname
CONNECT TO username
IDENTIFIED BY password
USING 'connstr' | ( connstr='values', dbtype='values' )
描述
uxdb兼容Oracle使用CREATE DATABASE LINK语句创建数据库链接。创建数据库链接后,可以在SQL语句中通过附加@dblink到表、视图或PL/SQL对象名称来引用其他数据库中的表、视图和PL/SQL对象。可以使用该语句查询其他数据库中的表或视图。还可以使用任何INSERT、UPDATE、DELETE或LOCK TABLE语句访问远程表和视图。
UXDB数据库实现CREATE/DROP DATABASE LINK相关语法及功能支持场景如下表所示。
表 CREATE/DROP DATABASE LINK相关语法及功能支持 | 应用场景 | Oracle-Oracle | Oracle-其他库 | Uxdb-uxdb | Uxdb-oracle | |----------|---------------|---------------|-----------|-------------| | SELECT | 支持 | 支持 | 支持 | 支持 | | INSERT | 支持 | 支持 | 支持 | 支持 | | UPDATE | 支持 | 支持 | 支持 | 支持 | | DELETE | 支持 | 支持 | 支持 | 支持 | | LOCK TABLE | 支持 | 不支持 | 不支持 | 不支持 | | PL/SQL functions | 支持 | 不支持 | 不支持 | 不支持 | | procedures | 支持 | 支持部分(创建本地过程操作远程对象) | 不支持 | 不支持 | | packages | 支持 | 不支持 | 不支持 | 不支持 |
UXDB数据库通过@dblink操作远程对象的支持场景如下所示。
表 操作远程对象用法汇总
| 描述 | 例句 | Oracle | UXDB |
|---|---|---|---|
| from阶段带@ | select ... from tab@dblink1 where id < 1; | 支持 | 支持 |
| from阶段带@,where子句中[带@dblink]引用远程表列 | select ... from tab@dblink1 where tab.id@dblink1 < 1;select ... from tab@dblink1 where id < 3; | 支持 | 支持 |
| from阶段带@,where子句中直接使用远程表名.列 (多表连接) | select ... from tab@dblink1,t_b where tab.id = t_b.id; | 支持 | 不支持 |
| 本地表和远程表同名,两表连接操作 | select ... from t_a@dblink1,t_a where t_a.id = t_a.id;select ... from t_a@dblink1,t_a where id@dblink1 = t_a.id;select ... from t_a@dblink1,t_a where id1@dblink1 = t_a.id; | 支持(但列名相同时报错) | 例1支持,例2报错,例3支持 |
| 表名 @ dblink三者之间可以任意空格 | select ... from tab@dblink1;select ... from tab @dblink1;select ... from tab@ dblink1;select ... from tab @ dblink1; | 支持 | 支持 |
| Update远程表时,set后的目标对象支持带@ | update stu@dblink set stu.name@dblink = 'ji' where stu.id@dblink = 3;update stu@dblink set name@dblink = 'ji' where stu.id@dblink = 3; | 支持 | 支持 |
| Insert远程表后的目标列中使用带@ | insert into t_a@DBLINK3(id, t_a.address@dblink3, name) values(4, 'jhfje' , 'lpp'); | 支持 | 不支持 |
参数
-
linkname
dblink名称。 -
username
远程连接用户名(注意标准模式和兼容模式下用户名的大小写)。 -
password
远程用户登录密码。 -
connstr
此规则针对oracle数据库的专用连接标识串如192.71.1.104:1521/orcl,传入的字符串包含远程机器HOST:PORT/SERVICE_NAME。也可以和oracle一样使用连接描述符
。 示例如下所示。
USING '192.71.1.104:1521/orcl' USING '(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 192.71.1.104)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = orcl)))'(connstr=values,dbtype=values):如果需要指定远程连接数据库类型,则使用此规则。
示例如下所示。
USING (connstr='192.71.1.104:1521/orcl', dbtype='oracle') USING (connstr='(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 192.71.1.102)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = orcl)))', dbtype='oracle') USING (connstr='192.71.1.104:5532/uxdb', dbtype='uxdb') 其中connstr串代表HOST:PORT/DBNAME
使用限制说明
-
通过dblink访问远程库上的系统表时,需要指定对应的模式名。(uxdb对应为ux_catalog;oracle对应sys)
-
Oracle指定connecting_string有两种方式,可以是配置的网络服务名<tsn_name>;uxdb不支持tsn_name的方式。
-
远程连接oracle数据库时,版本不高于11g,如果连接高于此版本(如12c),则会报错(ORA-28040: No matching authentication protocol),原因oracle_fdw对应的ODBC库版本为libclntsh.so.11.1,高版本数据库对应的库版本不一致。
-
通用户创建dblink需要的权限。
uxdb用户登录授权,如下所示。
grant all on FOREIGN data wrapper oracle_fdw|uxdb_fdw to public;
grant all on DATABASE dbname to PUBLIC; (在创建dblink的时候需要创建本地外部表对应的schema,因此需要对相应的数据库授予public权限)
-
uxdb私有dblink不能创建在public模式下。
-
当远程库为oracle时,
UPDATE|DELETE远程表时,远程表必须有主键(本地外部表必须有主键才可以执行,否则会报错)。 -
Uxdb操作远程oracle视图,执行
update|delete操作会报错,原因无论表是否有主键,创建的视图都是不带主键的,因此oracle_fdw会报错。
针对5、6的情况,当远程表没有主键时,但又需要执行update|delete操作,可以为远程表对应的本地外部表增加主键,但是本地外部表必须要选择一个值唯一且不为空的列作为主键列。
执行sql语句为alter foreign table <foreign_tabname> alter <colname> options (key 'true');
-
foreign_tabname:外部表名
-
colname:选择的主键列列名
-
不支持远程物化视图的刷新。
-
当远程库为oracle时,对远程表进行批量插入时,可能因意外情况导致序列化错误(ORA-08177)。解决方法如下所示。
a.通过脚本调用uxsql执行远程表的insert命名(该方法脚本运行时,第一条insert也会报ORA-08177错误,后续的不会再报错)。
b.修改外部服务器的隔离级别为read_committed,但根据oracle_fdw官方文档说明,可能会存在数据不一致风险。
ALTER SERVER <server_name> OPTIONS (isolation_level 'read_committed');
- 远端服务器为oracle时,列类型为real类型,通过dblink插入数据时数据最大位数不超过63位。
注解
如果访问中文,如用户名或密码中含有中文,需要注意编码保持一致,Uxdb客户端和服务端编码为UTF8。
Oracle客户端和服务端为AMERICAN_AMERICA.AL32UTF8。
Oracle编码配置方法如下。
- 配置客户端编码
在~/.bash_profile增加如下内容,保存并退出。
vi ~/.bash_profile
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
执行source ~/.bash_profile使其生效,执行echo $NLS_LANG结果为上面设置的编码这说明配置成功。
- 配置/修改Oracle服务器端的编码
当前服务端编码为AMERICAN_AMERICA.UTF8,需要和客户端保持一致,因此将服务端编码修改为AMERICAN_AMERICA.AL32UTF8。
修改方法如下。
以sys用户登录进去,执行以下命令。
shutdown immediate //关闭数据库
startup nomount //以nomount启动数据库
alter database mount exclusive; //装载数据为专用的高级模式;
alter system enable restricted session; //启用受限制的session模式
alter system set job_queue_processes=0; //设置工作队列的最大进程数为0
alter system set aq_tm_processes=0;
alter database open;
alter database character set INTERNAL_USE AL32UTF8; // 修改字符集为 AL32UTF8
shutdown immediate //关闭数据库
Startup //启动数据库
select userenv('language') from dual; //查看编码是否修改成功
需要注意的是,对于之前已经存在的数据,在修改了字符集之后还是会显示为乱码,只有新插入的数值才会生效。
示例
- 本地数据库实例配置文件预加载database_link插件。
vim data1/uxsinodb.conf
shared_preload_libraries = 'database_link'
如果未将插件名写入配置文件,在创建该插件时会报错。
- 启动本地实例,创建对应的插件。
create extension database_link ;
create extension uxdb_fdw;
create extension oracle_fdw;
- 打开表结构比对开关。
表结构比对开关默认关闭,使用如下语句进行打开或者关闭。
set databaselink.enable_dblink_comparetable = on/off;
关闭时,远端表结构发生改变,本地不会感知,也不会更新本地外部表结构。
打开后,远端表结构发生改变时,使用DML语句会更新本地外部表结构。
- 创建dblink,并进行应用。
uxdb-uxdb标准模式测试如下。
- 本地数据库实例配置文件预加载database_link插件,并启动。
vim data1/uxsinodb.conf
shared_preload_libraries = 'orafce,database_link'
- 启动本地实例,创建对应的插件。
create extension database_link ;
create extension uxdb_fdw;
create extension oracle_fdw;
- 创建dblink,并进行相关应用测试。
准备环境本地实例data1,远程实例data2。
vim data1/uxsinodb.conf
shared_preload_libraries = 'orafce,database_link'
启动data1 data2。
---远程实例data2 创建测试表
create table t_a (id int, name char(5));
insert into t_a values (1, 'a');
insert into t_a values (2, 'b');
insert into t_a values (3, 'c');
insert into t_a values (4, 'd');
create table t_b (id int, name char(5));
insert into t_b values (1, 'c');
insert into t_b values (2, 'a');
insert into t_b values (3, 'd');
insert into t_b values (4, 'e');
create table t_c (id int, name char(5));
insert into t_c values (1, 'a');
insert into t_c values (2, 'b');
insert into t_c values (3, 'c');
insert into t_c values (4, 'd');
--远程表带默认值
create table stu1( id int, name varchar(4) not null, birthday date default '2015-4-27');
insert into stu1 values(1, 'bbb');
--远程表带引号
create table "Atest" (id int);
insert into "Atest" values (1),(2),(3);
create schema "BBB";
set search_path to "BBB";
create table "BTESt" (id int);
insert into "BTESt" values (1),(2),(3);
--远程创建视图
create view myview as select * from t_c;
CREATE VIEW
select * from myview ;
id | name
----+--
1 | a
2 | b
3 | c
4 | d
(4 rows)
--远程创建物化视图
CREATE MATERIALIZED VIEW mymatview AS SELECT * FROM stu1;
SELECT 3
select * from mymatview;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
3 | ddd | 2015-04-27
(3 rows)
---实例data1 创建dblink
create extension database_link ;
CREATE EXTENSION
create extension uxdb_fdw;
CREATE EXTENSION
create public database link dblink2
connect to 'uxdb' identified by '1'
USING (connstr='127.0.0.1:5532/uxdb', dbtype='uxdb');
CREATE DATABASE LINK
---增删改查测试
select * from t_a@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
4 | d
(4 rows)
insert into t_a@dblink2 values(5, 'hhh');
INSERT 0 1
select * from t_a@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
4 | d
5 | hhh
(5 rows)
insert into t_a@dblink2 values(6, 'kkkk') returning ctid, *;
ctid | id | name
--+----+--
(0,6) | 6 | kkkk
(1 row)
INSERT 0 1
update t_a@dblink2 set name = 'ddd' where id = 4;
UPDATE 1
select * from t_a@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
5 | hhh
4 | ddd
(5 rows)
delete from t_a@dblink2 where id = 3;
DELETE 1
select * from t_a@dblink2;
id | name
----+--
1 | a
2 | b
5 | hhh
4 | ddd
(4 rows)
--为带默认值的远程表插入数据
select * from stu1@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
(1 row)
insert into stu1@dblink2 values(2,'ccc');
INSERT 0 1
select * from stu1@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
(2 rows)
insert into stu1@dblink2 values(3,'ddd', '2019-10-08');
INSERT 0 1
select * from stu1@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
3 | ddd | 2019-10-08
(3 rows)
update stu1@dblink2 set birthday=default where id = 3;
UPDATE 1
select * from stu1@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
3 | ddd | 2015-04-27
(3 rows)
--对于创建时加引号的模式名|表名|列名,通过dblink操作时也需要加引号
select * from "Atest"@dblink2;
id
----
1
2
3
(3 rows)
select * from "BBB"."BTESt"@dblink2;
id
----
1
2
3
(3 rows)
insert into "BBB"."BTESt"@dblink2 values (5), (6);
INSERT 0 2
select * from "BBB"."BTESt"@dblink2;
id
----
1
2
3
5
6
(5 rows)
---访问远程视图或物化视图
select * from myview@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
4 | d
(4 rows)
select * from mymatview@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
3 | ddd | 2015-04-27
(3 rows)
--insert|update|delete操作远程视图
insert into myview@dblink2 values(5,'p');
INSERT 0 1
select * from myview@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
4 | d
5 | p
(5 rows)
update myview@dblink2 set name = 'pp' where id = 4;
UPDATE 1
select * from myview@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
5 | p
4 | pp
(5 rows)
delete from myview@dblink2 where id = 4;
DELETE 1
select * from myview@dblink2;
id | name
----+--
1 | a
2 | b
3 | c
5 | p
(4 rows)
--insert|update|delete操作远程物化视图
insert into mymatview@dblink2 values(4,'eee');
ERROR: cannot change materialized view "mymatview"
CONTEXT: remote SQL command: INSERT INTO public.mymatview(id, name, birthday) VALUES ($1, $2, $3)
update mymatview@dblink2 set name = 'hhh' where id = 2;
ERROR: cannot change materialized view "mymatview"
CONTEXT: remote SQL command: UPDATE public.mymatview SET name = 'hhh'::character varying(4) WHERE ((id = 2))
delete from mymatview@dblink2 where id = 3;
ERROR: cannot change materialized view "mymatview"
CONTEXT: remote SQL command: DELETE FROM public.mymatview WHERE ((id = 3))
select * from mymatview@dblink2;
id | name | birthday
----+-+--
1 | bbb | 2015-04-27
2 | ccc | 2015-04-27
3 | ddd | 2015-04-27
(3 rows)
多表连接测试
--本地创建测试表
create table tt (id int, name char(5));
insert into tt values (1, 'g');
insert into tt values (2, 'j');
insert into tt values (3, 'k');
insert into tt values (4, 'l');
\d
List of relations
Schema | Name | Type | Owner
---+-+--+--
public | tt | table | uxdb
(1 row)
select * from t_a@dblink2, tt where t_a.id@dblink2 = tt.id;
id | name | id | name
----+--+----+--
1 | a | 1 | g
2 | b | 2 | j
4 | ddd | 4 | l
(3 rows)
select * from t_a@dblink2, tt where t_a.id@ dblink2 = tt.id;
id | name | id | name
----+--+----+--
1 | a | 1 | g
2 | b | 2 | j
4 | ddd | 4 | l
(3 rows)
select * from t_a@dblink2, tt where t_a.id @ dblink2 = tt.id;
id | name | id | name
----+--+----+--
1 | a | 1 | g
2 | b | 2 | j
4 | ddd | 4 | l
(3 rows)
select * from t_a@dblink2 left join tt on t_a.id @ dblink2 = tt.id;
id | name | id | name
----+--+----+--
1 | a | 1 | g
2 | b | 2 | j
4 | ddd | 4 | l
5 | hhh | |
(4 rows)
select * from t_b@dblink2 right join (select * from t_a@dblink2 left join tt on t_a.id @ dblink2 = tt.id) b on t_b.id@dblink2 > 1;
id | name | id | name | id | name
----+--+----+--+----+--
2 | a | 1 | a | 1 | g
3 | d | 1 | a | 1 | g
4 | e | 1 | a | 1 | g
2 | a | 2 | b | 2 | j
3 | d | 2 | b | 2 | j
4 | e | 2 | b | 2 | j
2 | a | 4 | ddd | 4 | l
3 | d | 4 | ddd | 4 | l
4 | e | 4 | ddd | 4 | l
2 | a | 5 | hhh | |
3 | d | 5 | hhh | |
4 | e | 5 | hhh | |
(12 rows)
--其他用户登录通过PUBLIC类型的dblink访问远程对象
create user aaa password '1';
CREATE ROLE
\c uxdb aaa
Password for user aaa:
You are now connected to database "uxdb" as user "aaa".
select * from "Atest"@dblink2;
id
----
1
2
3
(3 rows)
insert into "BBB"."BTESt"@dblink2 values (5), (6);
INSERT 0 2
select * from "BBB"."BTESt"@dblink2;
id
----
1
2
3
5
6
5
6
(7 rows)
---创建私有dblink测试私有dblink创建在非public模式下,因此需要先创建对应的schema
create database link dblink3
connect to 'uxdb' identified by '1'
USING (connstr='127.0.0.1:5532/uxdb', dbtype='uxdb');
ERROR: Non-public dblink can not be created in "public" schema
create schema stest;
CREATE SCHEMA
set search_path to stest ;
SET
create database link dblink3 connect to 'uxdb' identified by '1' USING (connstr='127.0.0.1:5532/uxdb', dbtype='uxdb');
CREATE DATABASE LINK
create database link stest.dblink4 connect to 'uxdb' identified by '1' USING (connstr='127.0.0.1:5532/uxdb', dbtype='uxdb');
CREATE DATABASE LINK
select * from "BBB"."BTESt"@dblink3;
id
----
1
2
3
5
6
5
6
(7 rows)
select * from "BBB"."BTESt"@dblink4;
id
----
1
2
3
5
6
5
6
(7 rows)
delete from "BBB"."BTESt"@dblink4 where id = 6;
DELETE 2
select * from "BBB"."BTESt"@dblink4;
id
----
1
2
3
5
5
(5 rows)
--其他用户登录通过私有dblink访问远程对象会报错
--私有dblink创建在非public模式下,因此首先需要为普通用户授予使用该模式的权限
grant usage on schema stest to aaa;
GRANT
\c uxdb aaa
Password for user aaa:
You are now connected to database "uxdb" as user "aaa".
set search_path to stest ;
SET
select * from "BBB"."BTESt"@dblink3;
ERROR: connection description for remote database not found
LINE 1: select * from "BBB"."BTESt"@dblink3;
^
--普通用户创建dblink
--首先需要管理员授予相关权限
grant all on FOREIGN data wrapper uxdb_fdw to public;(创建server和mapping的时候需要外部服务器权限)
GRANT
grant all on DATABASE uxdb to PUBLIC;(在创建dblink的时候需要创建本地外部表对应的schema,因此需要将对应数据库授予public,否则会报错)
GRANT
\c uxdb aaa
Password for user aaa:
You are now connected to database "uxdb" as user "aaa".
create public database link dblink5 connect to 'uxdb' identified by '1' USING (connstr='127.0.0.1:5532/uxdb', dbtype='uxdb');
CREATE DATABASE LINK
select * from "BBB"."BTESt"@dblink5;
id
----
1
2
3
5
5
(5 rows)
select * from t_a@dblink5;
id | name
----+--
1 | a
2 | b
5 | hhh
6 | kkkk
4 | ddd
(5 rows)
--其他用户登录通过普通用户aaa创建的dblink5访问远程对象
\c uxdb uxdb
Password for user uxdb:
You are now connected to database "uxdb" as user "uxdb".
create user bbb password '123';
CREATE ROLE
\c uxdb bbb
Password for user bbb:
You are now connected to database "uxdb" as user "bbb".
select * from t_a@dblink5;
id | name
----+--
1 | a
2 | b
5 | hhh
6 | kkkk
4 | ddd
(5 rows)
CREATE DOMAIN
CREATE DOMAIN — 定义新域
概要
CREATE DOMAIN name [ AS ] data_type
[ COLLATE collation ]
[ DEFAULT expression ]
[ constraint [ ... ] ]
其中 constraint 为:
[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | CHECK (expression) }
描述
CREATE DOMAIN创建一个新域。域本质上是一个带有可选约束(对允许值集的限制)的数据类型。定义域的用户成为其所有者。
如果给出模式名称(例如,CREATE DOMAIN myschema.mydomain...),则在指定的模式中创建域。否则,它将在当前模式中创建。域名称必须在其模式中的现有类型和域中是唯一的。
域对于将字段的常见约束抽象为单个位置以进行维护非常有用。例如,多个表可能包含电子邮件地址列,所有这些列都需要相同的CHECK约束来验证地址语法。定义域而不是单独设置每个表的约束。
要能够创建域,必须对基础类型具有USAGE权限。
参数
-
name
要创建的域的名称(可选模式限定符)。 -
data_type
域的基础数据类型。这可以包括数组说明符。 -
collation
域的可选排序规则。如果未指定排序规则,则该域具有与其基础数据类型相同的排序行为。如果COLLATE指定了排序规则,则基础类型必须是可排序的。 -
DEFAULT expression
DEFAULT子句指定了域数据类型列的默认值。该值是任何无变量的表达式(但不允许子查询)。默认表达式的数据类型必须与域的数据类型匹配。如果未指定默认值,则默认值为null值。默认表达式将在任何未指定列值的插入操作中使用。如果为特定列定义了默认值,则它会覆盖与域关联的任何默认值。反过来,域默认值会覆盖与底层数据类型关联的任何默认值。 -
CONSTRAINT constraint_name
约束的可选名称。如果未指定,则系统会生成一个名称。 -
NOT NULL
防止该域的值为空(但请参见下面的注释)。 -
NULL
允许该域的值为空。这是默认值。
此子句仅用于与非标准SQL数据库的兼容性。在新应用程序中不建议使用它。
CHECK(expression)
CHECK子句指定域值必须满足的完整性约束或测试。每个约束都必须是产生布尔结果的表达式。它应该使用关键字VALUE来引用正在测试的值。评估为TRUE或UNKNOWN的表达式成功。如果表达式产生FALSE结果,则报告错误并且不允许将值转换为域类型。
目前,CHECK表达式不能包含子查询,也不能引用除VALUE之外的变量。
当域具有多个CHECK约束时,它们将按名称的字母顺序进行测试。
注释
在将值转换为域类型时,将检查域约束,特别是NOT NULL。尽管存在此类约束,但名义上是域类型的列可能会读取为空。例如,在外连接查询中,如果域列位于外连接的可空侧,则可能会发生这种情况。一个更微妙的例子是
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
空标量子选择将产生一个空值,被认为是域类型,因此不会对其应用进一步的约束检查,插入将成功。
由于SQL普遍假定null值是每种数据类型的有效值,因此很难避免这些问题。因此,最佳做法是设计域的约束,以允许空值,然后根据需要将列NOT NULL约束应用于域类型的列,而不是直接应用于域类型。
UXsinoDB假定CHECK约束条件是不可变的,即它们始终为相同的输入值产生相同的结果。这个假设是证明检查CHECK约束的正确性的基础。
约束只有在值首次转换为域类型时才生效,而不是其他时间。(这与表CHECK约束的处理方式基本相同)
打破这种假设的常见方法是在CHECK表达式中引用用户定义的函数,然后更改该函数的行为。UXsinoDB不会禁止这样做,但它不会注意到存储的域类型值现在违反了CHECK约束。这将导致后续的数据库转储和恢复失败。处理这种更改的推荐方法是删除约束(使用ALTER DOMAIN),调整函数定义,然后重新添加约束,从而针对存储的数据重新检查它。
示例
此示例创建us_postal_code数据类型,然后在表定义中使用该类型。使用正则表达式测试来验证该值是否类似于有效的美国邮政编码:
CREATE DOMAIN us_postal_code AS TEXT
CHECK(
VALUE ~ '^\d{5}$'
OR VALUE ~ '^\d{5}-\d{4}$'
);
CREATE TABLE us_snail_addy (
address_id SERIAL PRIMARY KEY,
street1 TEXT NOT NULL,
street2 TEXT,
street3 TEXT,
city TEXT NOT NULL,
postal us_postal_code NOT NULL
);
兼容性
CREATE DOMAIN命令符合SQL标准。
另请参阅
CREATE EVENT TRIGGER
CREATE EVENT TRIGGER — 定义新的事件触发器
概要
CREATE EVENT TRIGGER name
ON event
[ WHEN filter_variable IN (filter_value [, ... ]) [ AND ... ] ]
EXECUTE { FUNCTION | PROCEDURE } function_name() | {
DECLARE
Declaration-statements
BEGIN
Executable-statements
EXCEPTION
Exception-handling-statements
END;
/}
描述
CREATE EVENT TRIGGER创建一个新的事件触发器。每当指定的事件发生并且与触发器关联的WHEN条件(如果有)被满足时,触发器函数将被执行。创建事件触发器的用户成为其所有者。
参数
-
name
新触发器的名称。该名称必须在数据库中唯一。 -
event
触发调用给定函数的事件的名称。 -
filter_variable
用于过滤事件的变量的名称。这使得可以将触发器的触发限制为其支持的情况的子集。目前唯一支持的filter_variable是TAG。 -
filter_value
触发器应触发的相关filter_variable的值列表。对于TAG,这意味着命令标记的列表(例如'DROP FUNCTION')。 -
function_name
用户提供的函数,声明为不带参数并返回类型为event_trigger。
在CREATE EVENT TRIGGER语法中,关键字FUNCTION和PROCEDURE是等效的,但引用的函数必须是函数,而不是过程。这里使用关键字PROCEDURE是历史遗留问题,已经不推荐使用。
-
Declaration-statements
声明部分。 -
Executable-statements
执行部分。 -
Exception-handling-statements
异常处理部分。
注释
只有超级用户才能创建事件触发器。
在单用户模式下禁用事件触发器。如果错误的事件触发器禁用了数据库,以至于您甚至无法删除触发器,请在单用户模式下重新启动,然后您就可以这样做了。
示例
禁止执行任何DDL命令:
CREATE OR REPLACE FUNCTION abort_any_command()
RETURNS event_trigger
LANGUAGE pluxsql
AS $$
BEGIN
RAISE EXCEPTION 'command % is disabled', tg_tag;
END;
$$;
CREATE EVENT TRIGGER abort_ddl ON ddl_command_start
EXECUTE FUNCTION abort_any_command();
返回一个异常信息,如下所示。
CREATE EVENT TRIGGER abort_ddl ON ddl_command_start begin RAISE EXCEPTION 'command % is disabled', tg_tag;
end;
/
兼容性
SQL标准中没有CREATE EVENT TRIGGER语句。
另请参阅
ALTER EVENT TRIGGER、DROP EVENT TRIGGER、CREATE FUNCTION
CREATE EXTENSION
CREATE EXTENSION — 安装扩展
概要
CREATE EXTENSION [ IF NOT EXISTS ] extension_name
[ WITH ] [ SCHEMA schema_name ]
[ VERSION version ]
[ CASCADE ]
描述
CREATE EXTENSION将一个新的扩展安装到当前数据库中。不能已经加载了同名的扩展。
加载扩展实际上相当于运行扩展的脚本文件。该脚本通常会创建新的SQL对象,例如函数、数据类型、运算符和索引支持方法。CREATE EXTENSION还记录了所有创建的对象的标识,以便在发出DROP EXTENSION时可以删除它们。
运行CREATE EXTENSION的用户成为扩展的所有者,以便进行后续的特权检查,并且通常也成为扩展脚本创建的任何对象的所有者。
加载扩展通常需要与创建其组件对象所需的特权相同的特权。对于许多扩展,这意味着需要超级用户特权。但是,如果扩展在其控制文件中标记为可信,则任何具有当前数据库上的 CREATE 特权的用户都可以安装它。在这种情况下,扩展对象本身将由调用用户拥有,但包含的对象将由引导超级用户拥有(除非扩展的脚本明确将它们分配给调用用户)。这种配置赋予调用用户删除扩展的权利,但不允许修改其中的单个对象。
参数
-
IF NOT EXISTS
如果已经存在同名扩展,则不会抛出错误。在这种情况下会发出通知。请注意,不能保证现有的扩展与要安装的扩展相似。 -
extension_name
要安装的扩展的名称。UXsinoDB将使用来自文件的详细信息创建扩展SHAREDIR/extension/extension_name.control 。 -
schema_name
要安装扩展对象的模式的名称,假设扩展允许其内容被重新定位。命名模式必须已经存在。如果未指定,并且扩展的控制文件也未指定模式,则使用当前默认对象创建模式。
如果扩展在其控制文件中指定了schema参数,则无法覆盖该模式SCHEMA子句。通常,如果出现错误,将引发错误给出SCHEMA子句并与之冲突扩展的schema参数。但是,如果也给出了CASCADE子句,然后将忽略 schema_name 当冲突时。给定的 schema_name 将是用于安装任何需要的扩展,这些扩展没有指定schema在其控制文件中。
请记住,扩展本身不被认为在任何模式中:扩展具有必须唯一的未限定名称整个数据库。但是属于扩展的对象可以在模式。
-
version
要安装的扩展的版本。这可以写成标识符或字符串文字。默认版本是扩展的控制文件中指定的任何内容。 -
CASCADE
自动安装此扩展所依赖的任何扩展尚未安装。它们的依赖项也是自动安装,递归地。SCHEMA子句,如果给出,则适用于以这种方式安装的所有扩展。语句的其他选项不适用于自动安装的扩展;特别是,它们的默认值版本始终被选择。 -
WITH
指定要使用的扩展模式的名称。如果未指定,则使用默认模式。 -
schema_name
要使用的模式的名称。 -
VERSION
指定要安装的扩展的版本。如果未指定,则使用扩展的默认版本。 -
version
要安装的扩展的版本号。 -
CASCADE
删除扩展时,同时删除依赖于该扩展的所有对象。
注意事项
在使用CREATE EXTENSION将扩展加载到数据库中之前,必须安装扩展的支持文件。有关安装UXsinoDB提供的扩展的信息可以在其他提供的模块中找到。
当前可用于加载的扩展可以从中识别ux_available_extensions或ux_available_extension_versions系统视图。
注意
以超级用户身份安装扩展需要信任扩展的作者以安全的方式编写扩展安装脚本。恶意用户很容易创建木马对象,将危及后来的执行粗心编写的扩展脚本,允许该用户获取超级用户权限。但是,木马对象仅在出现时具有危险性在脚本期间处于search_path中的对象执行时,意味着它们在扩展的安装目标模式中或在某个扩展所依赖的模式中。因此,处理那些脚本未经仔细审查的扩展时,一个好的经验法则是仅将它们安装到未授予任何不受信任用户CREATE权限的模式中。对于它们所依赖的任何扩展也是如此。提供的与UXsinoDB相关的扩展被认为是安全的,不会受到此类安装时攻击的影响,除了一些依赖于其他扩展的扩展。如那些扩展的文档所述,它们应该被安装到安全的模式中,或者安装到与它们所依赖的扩展相同的模式中,或者两者都是。
示例
将hstore扩展安装到当前数据库中,并将其对象放置在模式addons中:
CREATE EXTENSION hstore SCHEMA addons;
另一种实现相同效果的方法:
SET search_path =addons; CREATE EXTENSION hstore;
兼容性
CREATE EXTENSION是UXsinoDB的扩展。
另请参阅
ALTER EXTENSION,DROP EXTENSION
CREATE FOREIGN DATA WRAPPER
CREATE FOREIGN DATA WRAPPER — 定义新的外部数据包装器
概要
CREATE FOREIGN DATA WRAPPER name
[ HANDLER handler_function | NO HANDLER ]
[ VALIDATOR validator_function | NO VALIDATOR ]
[ OPTIONS ( option 'value' [, ... ] ) ]
描述
CREATE FOREIGN DATA WRAPPER 创建新的外部数据包装器。定义外部数据包装器的用户将成为其所有者。
外部数据包装器名称必须在数据库中唯一。
只有超级用户才能创建外部数据包装器。
参数
-
name
要创建的外部数据包装器的名称。 -
HANDLER handler_function
handler_function是之前注册的函数的名称,将被调用以检索外部表的执行函数。处理程序函数必须不带参数,并且其返回类型必须是fdw_handler。
可以创建没有处理程序函数的外部数据包装器,但是使用这种包装器的外部表只能被声明,而不能被访问。
-
VALIDATOR validator_function
validator_function是之前注册的函数的名称,将被调用以检查给定给外部数据包装器的通用选项,以及使用外部数据包装器的外部服务器、用户映射和外部表的选项。如果没有指定验证函数或NO VALIDATOR,则选项将不会在创建时被检查。(外部数据包装器可能会在运行时忽略或拒绝无效的选项规范。)指定外部数据包装器的验证器函数。验证器函数必须接受两个参数:一个是text[]类型的数组,其中包含系统目录中存储的选项数组,另一个是oid类型的系统目录的OID,其中包含选项。返回类型被忽略;函数应使用ereport(ERROR)函数报告无效选项。 -
OPTIONS(option'value' [, ... ] )
此子句指定新外部数据包装器的选项。允许的选项名称和值对于每个外部数据包装器都是特定的,并使用外部数据包装器的验证器函数进行验证。选项名称必须是唯一的。
注释
UXsinoDB的外部数据功能仍在积极开发中。查询的优化是原始的(大部分也留给包装器)。因此,未来还有很大的性能改进空间。
示例
创建一个无用的外部数据包装器dummy:
CREATE FOREIGN DATA WRAPPER dummy;
创建一个外部数据包装器file,并使用处理程序函数file_fdw_handler:
CREATE FOREIGN DATA WRAPPER file HANDLER file_fdw_handler;
创建一个外部数据包装器mywrapper,并带有一些选项:
CREATE FOREIGN DATA WRAPPER mywrapper
OPTIONS (debug 'true');
兼容性
CREATE FOREIGN DATA WRAPPER符合ISO/IEC 9075-9(SQL/MED)标准,但HANDLER和VALIDATOR子句是扩展,而标准子句LIBRARY和LANGUAGE在UXsinoDB中未实现。
但是,请注意,SQL/MED功能作为整体尚未符合标准。
另请参阅
ALTER FOREIGN DATA WRAPPER ,DROP FOREIGN DATA WRAPPER,CREATE SERVER,CREATE USER MAPPING,CREATE FOREIGN TABLE
CREATE FOREIGN TABLE
CREATE FOREIGN TABLE — 定义新的外部表
概要
CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name ( [
{ column_name data_type [ OPTIONS ( option 'value' [, ... ] ) ] [ COLLATE collation ] [ column_constraint [ ... ] ]
| table_constraint }
[, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
SERVER server_name
[ OPTIONS ( option 'value' [, ... ] ) ]
CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name
PARTITION OF parent_table [ (
{ column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]
| table_constraint }
[, ... ]
) ]
{ FOR VALUES partition_bound_spec | DEFAULT }
SERVER server_name
[ OPTIONS ( option 'value' [, ... ] ) ]
其中 column_constraint 是:
[ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
CHECK ( expression ) [ NO INHERIT ] |
DEFAULT default_expr |
GENERATED ALWAYS AS ( generation_expr ) STORED }
而 table_constraint 是:
[ CONSTRAINT constraint_name ]
CHECK ( expression ) [ NO INHERIT ]
而 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 )
描述
CREATE FOREIGN TABLE在当前数据库中创建一个新的外部表。该表将由发出命令的用户拥有。
如果给出模式名称(例如,CREATE FOREIGN TABLE myschema.mytable...),则表将在指定的模式中创建。否则,它将在当前模式中创建。外部表的名称必须与同一模式中的任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。
CREATE FOREIGN TABLE还会自动创建一个数据类型,该数据类型表示外部表的一行对应的组合类型。因此,外部表不能与同一模式中的任何现有数据类型具有相同的名称。
如果指定了PARTITION OF子句,则将表创建为具有指定边界的parent_table的分区。
要能够创建外部表,您必须对外部服务器具有USAGE权限,以及对表中使用的所有列类型具有USAGE权限。
参数
-
IF NOT EXISTS
如果已存在具有相同名称的关系,则不会引发错误。在这种情况下,会发出通知。请注意,不能保证现有关系与将创建的关系相似。 -
table_name
要创建的表的名称(可选模式限定)。 -
column_name
要在新表中创建的列的名称。 -
data_type
列的数据类型。这可以包括数组说明符。 -
COLLATE collation
COLLATE子句将排序规则分配给列(必须是可排序的数据类型)。如果未指定,则使用列数据类型的默认排序规则。 -
INHERITS(parent_table[, ... ] )
可选的INHERITS子句指定新外部表自动继承所有列的表列表。父表可以是普通表或外部表。有关详细信息,请参见CREATE TABLE的类似形式。 -
PARTITION OF parent_table{ FOR VALUESpartition_bound_spec| DEFAULT }
此形式可用于将外部表创建为具有指定分区边界值的给定父表的分区。查看CREATE TABLE的类似形式以获取更多详细信息。请注意,如果父表上有UNIQUE索引,则当前不允许将外键表创建为父表的分区。(另请参见ALTER TABLE中的ALTER TABLE ATTACH PARTITION) -
CONSTRAINT constraint_name
列或表约束的可选名称。如果违反约束,则约束名称将出现在错误消息中,因此可以使用像col must be positive这样的约束名称来向客户端应用程序传递有用的约束信息。(需要双引号来指定包含空格的约束名称。)如果未指定约束名称,则系统将生成名称。 -
NOT NULL
该列不允许包含空值。 -
NULL
该列允许包含空值。这是默认设置。
此子句仅提供与非标准SQL数据库的兼容性。不建议在新应用程序中使用它。
CHECK ( expression) [ NO INHERIT ]
CHECK子句指定一个表达式,该表达式产生一个布尔结果,预期每行在外键表中都满足该表达式;也就是说,该表达式应该为外键表中的所有行产生TRUE或UNKNOWN,而不是FALSE。作为列约束指定的检查约束应仅引用该列的值,而出现在表约束中的表达式可以引用多个列。
目前,CHECK表达式不能包含子查询,也不能引用当前行的列以外的变量。可以引用系统列tableoid,但不能引用任何其他系统列。
标记为NO INHERIT的约束将不会传播到子表。
DEFAULT default_expr
DEFAULT子句为其出现在其中的列定义分配默认数据值。该值是任何无变量表达式(不允许子查询和对当前表中其他列的交叉引用)。默认表达式的数据类型必须与列的数据类型匹配。
默认表达式将用于未指定列值的任何插入操作。如果没有列的默认值,则默认值为null。
GENERATED ALWAYS AS(generation_expr)STORED
此子句将列创建为生成列。该列无法写入,读取时将返回指定表达式的结果。
关键字STORED是必需的,以表示该列将在写入时计算。(计算值将呈现给外部数据包装器进行存储,并且必须在读取时返回。)
生成表达式可以引用表中的其他列,但不能引用其他生成列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。
-
server_name
用于外部表的现有外部服务器的名称。有关定义服务器的详细信息,请参见CREATE SERVER。 -
OPTIONS(option'value' [, ...] )
与新外部表或其某个列相关联的选项。允许的选项名称和值对于每个外部数据包装器都是特定的,并使用外部数据包装器的验证器函数进行验证。不允许重复的选项名称(尽管表选项和列选项可以具有相同的名称)。
注释
外部表上的约束(例如CHECK或NOT NULL子句)不由核心UXsinoDB系统强制执行,大多数外部数据包装器也不尝试强制执行它们;也就是说,约束被简单地假定为成立。这样的强制执行几乎没有意义,因为它只适用于通过外部表插入或更新的行,而不适用于通过其他方式修改的行,例如直接在远程服务器上。相反,附加到外部表的约束应该表示由远程服务器强制执行的约束。
一些特殊用途的外部数据包装器可能是它们访问的数据的唯一访问机制,在这种情况下,外部数据包装器本身执行约束强制可能是合适的。但是,除非其文档说明如此,否则不应假定包装器会执行该操作。
虽然UXsinoDB不尝试强制执行外部表上的约束,但它假定它们对于查询优化是正确的。如果外部表中可见的行不满足声明的约束,则对表的查询可能会产生错误或不正确的答案。用户有责任确保约束定义与现实相符。
注意
当将外部表用作分区表的分区时,存在一个隐含的约束,即其内容必须满足分区规则。同样,用户有责任确保这是真实的,最好是在远程服务器上安装匹配的约束。
在包含外部表分区的分区表中,更改分区键值的UPDATE可以导致将行从本地分区移动到外部表分区,前提是外部数据包装器支持元组路由。但是,目前无法将行从外部表分区移动到另一个分区。需要执行这样的UPDATE将由于分区约束而失败,假设远程服务器正确执行该操作。
类似的考虑也适用于生成的列。存储的生成列在本地UXsinoDB服务器上插入或更新时计算,并交给外部数据包装器写入到外部数据存储中,但是不强制执行查询外部表返回与生成表达式一致的存储生成列的值。同样,这可能导致不正确的查询结果。
示例
创建外部表films,该表将通过服务器film_server进行访问:
CREATE FOREIGN TABLE films (
code char(5) NOT NULL,
title varchar(40) NOT NULL,
did integer NOT NULL,
date_prod date,
kind varchar(10),
len interval hour to minute
)
SERVER film_server;
例如,创建一个名为measurement的外部表,它有两个列kind和len,并且它们的数据类型分别为varchar(10)和interval hour to minute),它们没有列约束,它们将通过film_server服务器进行访问,可以使用以下命令:
CREATE FOREIGN TABLE measurement_y2016m07
PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01')
SERVER server_07;
兼容性
CREATE FOREIGN TABLE命令在很大程度上符合SQL标准;但是,与CREATE TABLE一样,允许使用NULL约束和零列外部表。指定列默认值的能力也是UXsinoDB扩展。以UXsinoDB定义的形式进行的表继承是非标准的。
另请参阅
ALTER FOREIGN TABLE, DROP FOREIGN TABLE,CREATE TABLE,CREATE SERVER,IMPORT FOREIGN SCHEMA
CREATE FUNCTION
CREATE FUNCTION — 定义一个新函数
概要
CREATE [ OR REPLACE ] FUNCTION
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
[ RETURNS rettype
| RETURNS TABLE ( column_name column_type [, ...] ) ]
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| WINDOW
| IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
| CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| PARALLEL { UNSAFE | RESTRICTED | SAFE }
| COST execution_cost
| ROWS result_rows
| SUPPORT support_function
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| { AS | IS } 'definition'
| { AS | IS } 'obj_file', 'link_symbol'
} ...
描述
CREATE FUNCTION定义一个新函数。CREATE OR REPLACE FUNCTION将创建一个新函数,或替换现有定义。要定义一个函数,用户必须在语言上具有USAGE权限。
如果包含模式名称,则函数将在指定模式中创建。否则,它将在当前模式中创建。新函数的名称不能与同一模式中具有相同输入参数类型的任何现有函数或过程匹配。但是,具有不同参数类型的函数和过程可以共享名称(这称为重载)。
要替换现有函数的当前定义,可以使用CREATE OR REPLACE FUNCTION。但不能用这种方式更改函数的名称或者参数类型,如果尝试这样做,实际上是创建一个新的不同的函数。CREATE OR REPLACE FUNCTION不会让更改现有函数的返回类型,必须先删除再重建该函数。在使用OUT参数时,这意味着除非函数是以兼容Oracle的语言创建的,否则只能删除函数而无法更改任何OUT参数的类型。
当使用CREATE OR REPLACE FUNCTION替换现有函数时,函数的所有权和权限不会更改。所有其他函数属性都被分配为命令中指定或暗示的值。您必须拥有该函数才能替换它(这包括成为拥有角色的成员)。
如果您删除然后重新创建函数,则新函数不是与旧函数相同的实体;您将不得不删除引用旧函数的现有规则、视图、触发器等。使用CREATE OR REPLACE FUNCTION更改函数定义,而不会破坏引用该函数的对象。此外,ALTER FUNCTION可用于更改现有函数的大多数辅助属性。
创建函数的用户成为函数的所有者。
要能够创建函数,必须对参数类型和返回类型具有USAGE特权。
参数
-
name
要创建的函数的名称(可选模式限定符)。 -
argmode
一个参数的模式:IN、OUT、INOUT或者VARIADIC。如果省略,默认为IN。如果函数是以兼容Oracle的语言定义的,那么VARIADIC参数必须在最后,否则只有OUT参数能跟在一个VARIADIC参数后面。OUT和INOUT参数不能和RETURNS TABLE符号一起使用。 -
argname
参数的名称。一些语言(包括SQL和PL/uxSQL)允许您在函数体中使用名称。对于其他语言,输入参数的名称只是额外的文档,就函数本身而言;但是,您可以在调用函数时使用输入参数名称以提高可读性。无论如何,输出参数的名称是重要的,因为它定义了结果行类型中的列名。(如果省略输出参数的名称,系统将选择默认列名。) -
argtype
函数参数的数据类型(可选模式限定符),如果有的话。参数类型可以是基本类型、组合类型或域类型,也可以引用表列的类型。
根据实现语言,还可以允许指定“伪类型”,例如cstring。伪类型表示实际参数类型是不完全指定的,或者在普通SQL数据类型集之外。
列的类型可以通过写成table_name.column_name%TYPE来引用。使用此功能有时可以帮助使函数独立于表定义的更改。
-
default_expr
如果未指定参数,则使用表达式作为默认值。表达式必须可以强制转换为参数类型。只有输入(包括INOUT)参数可以具有默认值。所有具有默认值的输入参数都必须具有默认值。 -
rettype
返回数据类型,可能被模式限定。返回类型可以是基本类型、组合类型或者域类型,也可以引用表列的类型。根据实现语言,也可以允许指定cstring之类的“伪类型”。如果该函数不会返回值,可以指定返回类型为void。
以兼容Oracle的语言定义的函数,RETURNS子句是不能省略的。
对于其他语言,当有OUT或者INOUT参数时,可以省略RETURNS子句。如果存在,该子句必须和输出参数所表示的结果类型一致:如果有多个输出参数,则为RECORD,否则与单个输出参数的类型相同。
SETOF修饰符表示该函数将返回项的集合而不是单一项。
可以使用table_name.column_name%TYPE引用列的类型。
-
column_name
RETURNS TABLE语法中输出列的名称。这实际上是声明命名的OUT参数的另一种方式,除了RETURNS TABLE还意味着RETURNS SETOF。 -
column_type
RETURNS TABLE语法中输出列的数据类型。 -
lang_name
函数实现的语言名称。它可以是sql、c、internal或用户定义的过程性语言的名称,例如pluxsql。如果指定了sql_body,则默认为sql。将名称括在单引号中已被弃用并需要匹配大小写。 -
TRANSFORM { FOR TYPE type_name} [, ... ] }
列出调用函数应用的转换。转换在SQL类型和特定于语言的数据类型之间进行转换;请参见CREATE TRANSFORM。过程性语言实现通常具有内置类型的硬编码知识,因此不需要在此处列出。如果过程性语言实现不知道如何处理类型并且没有提供转换,则它将回退到用于转换数据类型的默认行为,但这取决于实现。 -
WINDOW
WINDOW表示该函数是一个窗口函数,而不是普通函数。这只对用C写的函数有用。当替换现有函数定义时,WINDOW属性不能被更改。 -
IMMUTABLE
STABLE
VOLATILE
这些属性告诉查询优化器函数的行为。最多只能指定一种选择。如果没有出现这些属性中的任何一个,VOLATILE是默认的假设。
IMMUTABLE表示该函数不能修改数据库,并且在给定相同参数值时始终返回相同的结果;也就是说,它不进行数据库查找或以其他方式使用其参数列表中没有直接存在的信息。如果给出此选项,则任何使用所有常量参数的函数调用都可以立即替换为函数值。
STABLE表示该函数不能修改数据库,并且在单个表扫描中,对于相同的参数值,它将始终返回相同的结果,但其结果可能会在SQL语句之间发生变化。这是适用于其结果取决于数据库查找、参数变量(如当前时区)等的函数的适当选择。(对于希望查询当前命令修改的行的AFTER触发器来说,这是不合适的。)还要注意,current_timestamp函数族符合稳定性,因为它们的值在事务中不会改变。
VOLATILE表示函数值甚至可以在单个表扫描中发生变化,因此无法进行任何优化。相对较少的数据库函数在这个意义上是不稳定的;一些例子是random()、currval()、timeofday()。但是请注意,任何具有副作用的函数必须被分类为不稳定的,即使其结果是非常可预测的,以防止调用被优化掉;一个例子是setval()。
-
LEAKPROOF
LEAKPROOF表示该函数没有副作用。它不会透露关于其参数的信息,除非通过其返回值。例如,对于某些参数值会抛出错误消息但对于其他参数值不会抛出错误消息的函数,或者将参数值包含在任何错误消息中的函数,都不是不透明的。这会影响系统对使用security_barrier选项创建的视图或启用了行级安全性的表执行查询的方式。系统将在任何包含非透明函数的用户提供的查询条件之前执行来自安全策略和安全屏障视图的条件,以防止意外暴露数据。被标记为不透明的函数和运算符被认为是可信的,并且可以在安全策略和安全屏障视图的条件之前执行。此外,不需要将不带参数或未从安全屏障视图或表传递任何参数的函数标记为不透明,以在安全条件之前执行。请参见CREATE VIEW。此选项只能由超级用户设置。 -
CALLED ON NULL INPUT
RETURNS NULL ON NULL INPUT
STRICT
CALLED ON NULL INPUT(默认值)表示当函数的某些参数为空时,将正常调用该函数。然后,函数作者有责任根据需要检查空值并做出适当的响应。
RETURNS NULL ON NULL INPUT或STRICT表示,只要函数的任何参数为空,函数就始终返回null。如果指定了此参数,则在存在空参数时不执行该函数;而是自动假定为null结果。
[EXTERNAL] SECURITY INVOKER
[EXTERNAL] SECURITY DEFINER
SECURITY INVOKER表示将使用调用它的用户的权限执行该函数。这是默认值。SECURITY DEFINER指定将使用拥有它的用户的权限执行该函数。
关键字 EXTERNAL允许SQL符合性,但是它是可选的,因为与SQL不同,此功能适用于所有函数,而不仅仅是外部函数。
PARALLEL
PARALLEL UNSAFE表示该函数无法在并行模式下执行,并且在SQL语句中存在这样的函数会强制执行串行执行计划。这是默认值。PARALLEL RESTRICTED表示该函数可以在并行模式下执行,但执行受限于并行组的组长。PARALLEL SAFE表示该函数可以在并行模式下安全运行,而不受限制。
如果函数修改任何数据库状态,或者进行事务更改(例如使用子事务),或者访问序列或尝试对设置进行持久更改(例如setval),则应将其标记为并行不安全。如果它们访问临时表、客户端连接状态、游标、预处理语句或杂项后端本地状态,系统无法在并行模式下同步它们(例如setseed除了由组长执行外,不能执行,因为另一个进程所做的更改不会反映在组长中)。通常,如果将函数标记为受限制或不安全时,它被标记为安全,或者将其标记为受限制时,实际上它是不安全的,它可能会在并行查询中引发错误或产生错误的答案。理论上,如果错误标记C语言函数,它可能会表现出完全未定义的行为,因为系统无法保护自己免受任意C代码的攻击,但在最可能的情况下,结果不会比其他函数更糟糕。如果有疑问,函数应标记为UNSAFE,这是默认值。
-
COSTexecution_cost
一个正数,给出函数的预计执行成本,以cpu_operator_cost为单位。如果函数返回一个集合,这是每行返回的成本。如果未指定成本,则对于C语言和内部函数,假定为1个单位,对于所有其他语言的函数,则假定为100个单位。较大的值会导致规划器尝试尽可能避免评估函数。 -
ROWSresult_rows
给出预计的计划程序应该期望函数返回的行数。只有当函数声明为返回集合时才允许使用此选项。默认假设为1000行。 -
SUPPORTsupport_function
使用此函数的规划器支持函数的名称(可选模式限定)。 -
configuration_parameter
value
SET子句导致在进入函数时将指定的配置参数设置为指定的值,然后在函数退出时将其恢复为先前的值。SET FROM CURRENT将当前执行CREATE FUNCTION时的参数值保存为进入函数时要应用的值。
如果将SET子句附加到函数,则同一变量的函数内执行SET LOCAL命令的影响仅限于函数:配置参数的先前值仍将在函数退出时恢复。但是,普通的SET命令(不带LOCAL)会覆盖SET子句,就像它对先前的SET LOCAL命令一样:这样的命令的影响将在函数退出后持续存在,除非当前事务被回滚。
有关允许的参数名称和值的更多信息,请参见SET。
definition
定义函数的字符串常量;其含义取决于语言。它可以是内部函数名称、对象文件的路径、SQL命令或过程语言中的文本。
通常有助于使用美元引用编写函数定义字符串,而不是使用正常的单引号语法。如果没有美元引用,则函数定义中的任何单引号或反斜杠都必须加倍转义。
obj_file,link_symbol
在C语言源代码中的函数名称与SQL函数名称不同的动态可加载C语言函数使用此形式的AS子句。字符串obj_file是包含编译的C函数的共享库文件的名称,并按LOAD命令的方式进行解释。字符串link_symbol是函数的链接符号,即在C语言源代码中的函数名称。如果省略链接符号,则假定与正在定义的SQL函数名称相同。所有函数的C名称必须不同,因此必须为重载的C函数提供不同的C名称(例如,使用参数类型作为C名称的一部分)。
当重复的CREATE FUNCTION调用引用相同的对象文件时,该文件仅在会话期间加载一次。要卸载和重新加载文件(可能在开发过程中),请启动新会话。
-
sql_body
LANGUAGE SQL函数的主体。这可以是单个语句RETURN expression或块
BEGIN ATOMIC statement; statement; ... statement; END
这类似于将函数体的文本编写为字符串常量(请参见上面的定义),但有一些区别:此形式仅适用于LANGUAGE SQL,字符串常量形式适用于所有语言。此形式在函数定义时解析,字符串常量形式在执行时解析;因此,此形式无法支持多态参数类型和其他在函数定义时无法解析的构造。此形式跟踪函数和函数体中使用的对象之间的依赖关系,因此DROP ... CASCADE将正确工作,而使用字符串文字的形式可能会留下悬空函数。最后,此形式与SQL标准和其他SQL实现更兼容。
body
代码块内容,即函数或存储过程中需要执行的内容。
重载
UXsinoDB允许函数重载;也就是说,只要它们具有不同的输入参数类型,就可以使用相同的名称来表示多个不同的函数。无论您是否使用它,这种能力都需要在调用数据库中的函数时采取安全预防措施,其中一些用户不信任其他用户。
如果两个函数具有相同的名称和输入参数类型(忽略任何OUT参数),则认为它们是相同的函数。因此,例如,这些声明冲突:
CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, out text) ...
具有不同参数类型列表的函数在创建时不会被认为是冲突的,但是如果提供了默认值,则它们可能在使用中发生冲突。例如,请考虑
CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, int default 42) ...
调用foo(10)将失败,因为无法确定应调用哪个函数。
注解
允许使用完整的SQL类型语法来声明函数的参数和返回值。但是,括号中的类型修饰符(例如,类型numeric的精度字段)将被CREATE FUNCTION忽略。因此,例如CREATE FUNCTION foo (varchar(10)) ...与CREATE FUNCTION foo (varchar) ...完全相同。
在用CREATE OR REPLACE FUNCTION替换现有函数时,更改参数名称存在限制。您不能更改已分配给任何输入参数的名称(尽管您可以为以前没有名称的参数添加名称)。如果有多个输出参数,则不能更改输出参数的名称,因为这会更改描述函数结果的匿名组合类型的列名称。这些限制是为了确保在替换函数时现有的函数调用不会停止工作。
如果使用VARIADIC参数声明STRICT函数,则严格性检查测试整个可变数组是否为非空。如果数组具有空元素,则仍将调用该函数。
当没有LANGUAGE lang_name指定语言时,选择default_pl_language参数配置的语言,支持plsql和pluxsql,默认值为pluxsql。
当默认使用的是pluxsql语言时,在body中变量的定义需要使用declare关键字;如果使用的是plsql语言时,在body中变量的定义则不能使用declare关键字。
示例
使用SQL函数添加两个整数:
CREATE FUNCTION add(integer, integer) RETURNS integer
AS 'select $1 + $2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
使用参数名称和未引用的主体以更符合SQL规范的方式编写相同的函数:
CREATE FUNCTION add(a integer, b integer) RETURNS integer
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT
RETURN a + b;
在PL/uxSQL中使用参数名称增加整数:
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
BEGIN
RETURN i + 1;
END;
$$ LANGUAGE pluxsql;
返回包含多个输出参数的记录:
CREATE FUNCTION dup(in int, out f1 int, out f2 text)
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
您可以使用显式命名的组合类型以更冗长的方式执行相同的操作:
CREATE TYPE dup_result AS (f1 int, f2 text);
CREATE FUNCTION dup(int) RETURNS dup_result
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
返回多个列的另一种方法是使用TABLE函数:
CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
但是,TABLE函数与前面的示例不同,因为它实际上返回一组记录,而不仅仅是一条记录。
安全编写SECURITY DEFINER函数
由于SECURITY DEFINER函数使用拥有它的用户的权限执行,因此需要注意确保函数不能被滥用。出于安全考虑,search_path应设置为排除任何由不受信任的用户可写的模式。这可以防止恶意用户创建掩盖函数预期使用的对象(例如表、函数和运算符)的对象。在这方面特别重要的是临时表模式,默认情况下首先搜索该模式,并且通常可由任何人编写。可以通过将ux_temp作为search_path的最后一个条目来获得安全的排列。此函数说明了安全使用:
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
SELECT (pwd = $2) INTO passed
FROM pwds
WHERE username = $1;
RETURN passed;
END;
$$ LANGUAGE pluxsql
SECURITY DEFINER
-- Set a secure search_path: trusted schema(s), then 'ux_temp'.
SET search_path = admin, ux_temp;
该函数的目的是访问一个名为admin.pwds的表。但是如果没有SET子句,或者只提到admin的SET子句,该函数可能会被创建一个名为pwds的临时表所替代。
另一个需要记住的点是,默认情况下,新创建的函数授予PUBLIC执行权限。通常,您希望将安全定义函数的使用限制为某些用户。为此,您必须撤销默认的PUBLIC权限,然后有选择地授予执行权限。为了避免新函数可供所有人访问的窗口,创建它并在单个事务中设置权限。例如:
BEGIN;
CREATE FUNCTION check_password(uname TEXT, pass TEXT) ...SECURITY DEFINER;
REVOKE ALL ON FUNCTION check_password(uname TEXT,pass TEXT) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION check_password(unameTEXT, pass TEXT) TO admins;
COMMIT;
兼容性
CREATE FUNCTION命令在SQL标准中定义。UXsinoDB实现可以以兼容的方式使用,但具有许多扩展。相反,SQL标准指定了许多可选功能,在UXsinoDB中没有实现。
以下是重要的兼容性问题:
- OR REPLACE是UXsinoDB的扩展。
- 为了与其他一些数据库系统兼容,argmode可以在argname之前或之后编写。但只有第一种方法是标准兼容的。
- 对于参数默认值,SQL标准仅指定使用DEFAULT关键字的语法。使用=的语法在T-SQL和Firebird中使用。
- SETOF修饰符是UXsinoDB的扩展。
- 只有SQL被标准化为一种语言。
- 除了
CALLED ON NULL INPUT和RETURNS NULL ON NULL INPUT之外,所有其他属性都没有标准化。 - 对于LANGUAGE SQL函数的主体,SQL标准仅指定sql_body形式。
简单的LANGUAGE SQL函数可以以符合标准和可移植到其他实现的方式编写。使用高级功能、优化属性或其他语言的更复杂的函数必然在很大程度上特定于UXsinoDB。
另请参阅
ALTER FUNCTION、DROP FUNCTION、GRANT、LOAD、REVOKE
CREATE GROUP
CREATE GROUP — 定义新的数据库角色
概要
CREATE GROUP name [ [ WITH ] option [ ... ] ]
其中 option 可以是:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
| IN ROLE role_name [, ...]
| IN GROUP role_name [, ...]
| ROLE role_name [, ...]
| ADMIN role_name [, ...]
| USER role_name [, ...]
| SYSID uid
描述
CREATE GROUP 现在是CREATE ROLE的别名。
兼容性
SQL标准中没有 CREATE GROUP 语句。
另请参阅
CREATE INDEX
CREATE INDEX — 定义新索引
概要
CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
[ INCLUDE ( column_name [, ...] ) ]
[ NULLS [ NOT ] DISTINCT ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ TABLESPACE tablespace_name ]
[ WHERE predicate ]
描述
CREATE INDEX构建指定关系的指定列的索引,可以是表或材料化视图。索引主要用于提高数据库性能(但不当使用可能会导致性能变慢)。
索引的关键字段指定为列名,或者作为括号中写的表达式。如果索引方法支持多列索引,则可以指定多个字段。
索引字段可以是从表行的一个或多个列的值计算出的表达式。此功能可用于基于基本数据的某些转换快速访问数据。例如,计算在upper(col)上的索引将允许子句WHERE upper(col) = 'JIM'使用索引。
UXsinoDB提供B-tree、hash、GiST、SP-GiST、GIN和BRIN索引方法。用户还可以定义自己的索引方法,但这相当复杂。
当存在WHERE子句时,创建部分索引。部分索引是仅包含部分行的索引。如果指定了UNIQUE,则索引中的所有行都必须是唯一的。如果指定了CONCURRENTLY,则可以在其他事务正在使用表时构建索引。
一个表通常有一部分比其他部分更适合用于索引。例如,如果你有一个包含已开票和未开票订单的表,其中未开票订单只占总表的一小部分,但经常被使用,你可以通过仅在该部分上创建索引来提高性能。另一个可能的应用是使用WHERE和UNIQUE来强制对表的子集进行唯一性约束。
WHERE子句中使用的表达式只能引用基础表的列,但可以使用所有列,而不仅仅是正在索引的列。目前,子查询和聚合表达式在WHERE中也是被禁止的。对于表达式的索引字段也适用相同的限制。
在索引定义中使用的所有函数和运算符都必须是“不可变”的,也就是说,它们的结果必须仅依赖于它们的参数,而不依赖于任何外部影响(例如另一个表的内容或当前时间)。这个限制确保了索引的行为是明确定义的。要在索引表达式或WHERE子句中使用用户定义的函数,请在创建函数时记得将函数标记为不可变。
参数
UNIQUE
当索引被创建时,UNIQUE选项会导致系统检查表中是否存在重复值(如果数据已经存在),并且每次添加数据时都会进行检查。尝试插入或更新数据会导致重复条目的错误。
当唯一索引应用于分区表时,会有额外的限制,请参见CREATE TABLE。
CONCURRENTLY
当使用CONCURRENTLY选项时,UXsinoDB将在构建索引时不会锁定任何防止并发插入、更新或删除表的锁定,而标准索引构建会锁定表上的写入(但不是读取)直到完成。使用此选项时需要注意几个注意事项,请参见下面的CREATE INDEX。
对于临时表,CREATE INDEX始终是非并发的,因为没有其他会话可以访问它们,而非并发索引创建更便宜。
-
IF NOT EXISTS
如果指定了IF NOT EXISTS,则不会在同名关系已经存在时抛出错误。在这种情况下,会发出一个通知。请注意,不能保证现有的索引与将要创建的索引相似。在指定IF NOT EXISTS时需要提供索引名称。 -
INCLUDE
可选的INCLUDE子句指定将作为非键列包含在索引中的列列表。非键列不能用于索引扫描搜索限定条件,并且对于索引强制执行的任何唯一性或排除约束,都会被忽略。但是,索引只扫描可以返回非键列的内容,而无需访问索引的表,因为它们直接从索引条目中可用。因此,添加非键列允许对无法使用索引只扫描的查询使用索引只扫描。
对于添加非关键列到索引中,特别是宽列,保守一些是明智的。如果索引元组超过索引类型允许的最大大小,则数据插入将失败。无论如何,非关键列会复制索引表中的数据并使索引的大小膨胀,从而可能减慢搜索速度。此外,带有非关键列的索引永远不会使用B树去重。
在INCLUDE子句中列出的列不需要适当的操作符类;该子句可以包括其数据类型没有为给定访问方法定义操作符类的列。
由于表达式不能在索引只扫描中使用,因此不支持将表达式作为包含的列。
目前,B树、GiST和SP-GiST索引访问方法支持此功能。在这些索引中,列的值在叶元组中包括,这些叶元组对应于堆元组,但不包括用于树导航的上层索引条目中。
-
name
要创建的索引的名称。此处不能包括模式名称;索引始终在与其父表相同的模式中创建。索引的名称必须与该模式中任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。如果省略名称,则UXsinoDB会根据父表的名称和索引列名称选择一个合适的名称。 -
ONLY
如果表被分区,则指示不要递归创建分区上的索引。默认情况下,会递归。 -
table_name
要索引的表的名称(可能包括模式)。 -
method
要使用的索引方法的名称。选择项为btree、hash、gist、spgist、gin、brin或用户安装的访问方法,如bloom。默认方法是btree。 -
column_name
表的列的名称。 -
expression
基于表的一个或多个列的表达式。通常,表达式必须用括号括起来,如语法中所示。但是,如果表达式具有函数调用形式,则可以省略括号。 -
collation
用于索引的排序规则的名称。默认情况下,索引使用声明为要索引的列或要索引的表达式的结果排序规则。具有非默认排序规则的索引对于涉及使用非默认排序规则的表达式的查询可能很有用。 -
opclass
运算符类的名称。有关详细信息,请参见下文。 -
opclass_parameter
运算符类参数的名称。有关详细信息,请参见下文。 -
ASC
指定升序排序顺序(默认值)。 -
DESC
指定降序排序顺序。 -
NULLS FIRST
指定null值在非null值之前排序。当指定DESC时,这是默认值。 -
NULLS LAST
指定null值在非null值之后排序。当未指定DESC时,这是默认值。 -
NULLS DISTINCT
NULLS NOT DISTINCT
指定对于唯一索引,是否应将null值视为不同(不相等)。默认情况下,它们是不同的,因此唯一索引可以在列中包含多个null值。 -
storage_parameter
索引方法特定的存储参数的名称。有关详细信息,请参见下面的“索引存储参数”。 -
tablespace_name
要创建索引的表空间。如果未指定,则会查询default_tablespace,或者对于临时表上的索引,查询temp_tablespaces。 -
predicate
部分索引的约束表达式。
索引存储参数
可选的WITH子句指定索引的存储参数。每种索引方法都有其自己的一组允许的存储参数。B树、哈希、GiST和SP-GiST索引方法都接受此参数:
fillfactor(integer) 索引的填充因子是一个百分比,用于确定索引方法将尝试将索引页面填满的程度。对于B树,叶子页面在初始索引构建时以及在向右扩展索引(添加新的最大键值)时填充到此百分比。如果页面随后变得完全填满,它们将被分裂,导致磁盘上的索引结构碎片化。B树使用默认填充因子90,但可以选择从10到100的任何整数值。
在预计会有许多插入或更新的表上的B树索引可以从在CREATE INDEX时使用较低的填充因子设置(在表中进行批量加载后)。在50到90的范围内的值可以有用地“平滑”出 B树索引早期生命周期中页面分裂的速率(像这样降低填充因子甚至可能降低页面分裂的绝对数量,尽管这种效果高度依赖于工作负载)。B树自下而上的索引删除技术取决于页面上有一些“额外”空间来存储“额外”的元组版本,因此可能会受到填充因子的影响(尽管影响通常不大)。
在其他特定情况下,增加填充因子到100可能有助于在CREATE INDEX时最大化空间利用率。只有在您确定这样做时才应考虑这一点。
完全确定表是静态的(即永远不会受到插入或更新的影响)。否则,填充因子设置为100会冒着影响性能的风险:即使只有几个更新或插入也会导致突然的页面分裂。其他索引方法以不同但大致类似的方式使用填充因子;默认填充因子因方法而异。
B-tree索引还接受此参数:
deduplicate_items(boolean)
控制B-tree去重复技术的使用。设置为ON或OFF以启用或禁用优化。允许使用替代拼写的ON和OFF。默认值为ON。
注意
通过ALTER INDEX关闭deduplicate_items,可以防止将来的插入触发去重复,但本身并不使现有的posting list元组使用标准元组表示。
GiST索引还接受此参数:
buffering(num)
确定是否使用缓冲区构建技术来构建索引。禁用缓冲区为OFF,启用为ON,初始情况下禁用为AUTO,但一旦索引大小达到effective_cache_size,就会在运行时启用。默认值为AUTO。请注意,如果可以进行排序构建,则会使用排序构建,除非指定了buffering=ON。
GIN索引接受不同的参数:
fastupdate(boolean)
它是一个布尔参数:ON启用快速更新,OFF禁用它。默认值为ON。
注意
通过ALTER INDEX关闭fastupdate,可以防止将来的插入进入待处理索引条目列表,但本身并不刷新先前的条目。您可能需要对表进行VACUUM或在调用gin_clean_pending_list函数后确保待处理列表已清空。
gin_pending_list_limit(integer)
自定义gin_pending_list_limit参数。该值以千字节为单位指定。
BRIN索引接受不同的参数:
-
pages_per_range(integer)
定义每个BRIN索引条目所组成的一个块范围的表块数。默认值为128。 -
autosummarize(boolean)
定义是否在下一个范围检测到插入时,为前一个页面范围排队运行汇总运行。默认值为off。
并发构建索引
创建索引可能会干扰数据库的正常操作。通常情况下,UXsinoDB会锁定要索引的表,防止写入,并使用单个扫描对整个索引进行构建。其他事务仍然可以读取表,但如果它们尝试在表中插入、更新或删除行,则会阻塞,直到索引构建完成。如果系统是一个实时生产数据库,这可能会产生严重影响。非常大的表可能需要数小时才能完成索引,即使对于较小的表,索引构建也可能会锁定写入者的时间,这对于生产系统来说是不可接受的。
UXsinoDB支持在不锁定写入的情况下构建索引。这种方法是通过指定CREATE INDEX的CONCURRENTLY选项来调用的。当使用此选项时,UXsinoDB必须对表进行两次扫描,并且还必须等待所有可能修改或使用索引的现有事务终止。因此,这种方法需要比标准索引构建更多的总工作量,并且需要更长的时间才能完成。但是,由于它允许在构建索引时继续正常操作,因此这种方法对于在生产环境中添加新索引非常有用。当然,索引创建所带来的额外CPU和I/O负载可能会减慢其他操作。
在并发索引构建中,索引实际上是作为“无效”索引输入到系统目录中的一个事务,然后在另外两个事务中进行两个表扫描。在每个表扫描之前,索引构建必须等待已修改表的现有事务终止。在第二次扫描之后,索引构建必须等待任何具有快照的事务终止,该快照先于第二次扫描,包括由任何部分索引或具有不是简单列引用的列的索引的并发索引构建的任何阶段使用的事务。最后,索引可以标记为“valid”并准备好使用,CREATE INDEX命令终止。然而,即使如此,索引也可能无法立即用于查询:在最坏的情况下,只要存在早于索引构建开始的事务,就不能使用它。
如果在扫描表时出现问题,例如在唯一索引中发生死锁或唯一性冲突,CREATE INDEX命令将失败,但会留下一个“invalid”索引。这个索引将被忽略用于查询,因为它可能是不完整的;但它仍然会消耗更新开销。在这种情况下,uxsql的\d命令将报告这样的索引为INVALID:
uxdb=# \d tab
Table "public.tab"
Column | Type | Collation | Nullable | Default
---+----+-++----
col | integer | | |
Indexes:
"idx" btree (col) INVALID
推荐的恢复方法是删除索引,然后尝试执行CREATE INDEX CONCURRENTLY。(另一种可能性是使用REINDEX INDEXCONCURRENTLY重建索引)。
同时构建唯一索引的另一个注意事项是,当第二个表扫描开始时,唯一性约束已经对其他事务进行了强制执行。这意味着在索引可用于使用之前,其他查询可能会报告约束违规,甚至在索引构建最终失败的情况下也是如此。此外,如果第二次扫描失败,则“invalid”索引在此后仍将强制执行其唯一性约束。
支持并发构建表达式索引和部分索引。在这些表达式的评估中发生的错误可能会导致类似于唯一约束违规的行为。
常规索引构建允许在同一表上同时进行其他常规索引构建,但是一次只能在表上进行一个并发索引构建。在任一情况下,不允许在构建索引时修改表的模式。另一个区别是,可以在事务块内执行常规的CREATE INDEX命令,但不能执行CREATE INDEX CONCURRENTLY。
目前不支持对分区表上的索引进行并发构建。但是,您可以分别在每个分区上并发构建索引,然后最终创建非并发分区索引,以减少对分区表的写入被锁定的时间。在这种情况下,构建分区索引是仅元数据操作。
注释
目前,仅B-tree、GiST、GIN和BRIN索引方法支持多键列索引。是否可以有多个键列与是否可以向索引添加INCLUDE列无关。索引最多可以有32列,包括INCLUDE列。(在构建UXsinoDB时可以更改此限制。)目前仅B-tree支持唯一索引。
可以为索引的每个列指定带有可选参数的运算符类。运算符类标识索引用于该列的运算符。例如,在一个包含timestamp列的表上创建B-tree索引时,可以指定timestamp_ops运算符类,以便索引使用与timestamp列一起使用的运算符。四字节整数将使用int4_ops类;这个操作符类包括四字节整数的比较函数。实际上,列数据类型的默认操作符类通常已经足够。操作符类的主要目的是对于某些数据类型,可能存在多个有意义的排序方式。例如,我们可能希望按绝对值或实部对复数数据类型进行排序。我们可以为数据类型定义两个操作符类,然后在创建索引时选择适当的类。
在分区表上调用 CREATE INDEX时,默认行为是递归到所有分区以确保它们都有匹配的索引。首先检查每个分区以确定是否已存在等效的索引,如果存在,则该索引将作为分区索引附加到正在创建的索引上,后者将成为其父索引。如果不存在匹配的索引,则会创建一个新的索引并自动附加;在每个分区中,新索引的名称将被确定为如果在命令中未指定索引名称时的名称。如果指定了ONLY选项,则不进行递归,并且索引将被标记为无效。(ALTER INDEX ... ATTACH PARTITION在所有分区获取匹配的索引后标记索引为有效。) 但是请注意,使用 CREATE TABLE ...PARTITION OF创建的任何分区都将自动具有匹配的索引,而不管是否指定了ONLY。
对于支持有序扫描的索引方法(目前仅限B-tree),可以指定可选的ASC、DESC、NULLS FIRST或NULLS LAST子句来修改索引的排序顺序。由于有序索引可以向前或向后扫描,因此创建单列 DESC索引通常没有用处——该排序顺序已经在常规索引中可用。这些选项的价值在于可以创建多列索引,以匹配混合排序查询所请求的排序顺序,例如SELECT ... ORDER BY x ASC, y DESC。如果需要支持“nulls sort low”行为(而不是默认的“nulls sort high”),则 NULLS选项很有用,以便在依赖于索引避免排序步骤的查询中使用。
系统定期收集表的所有列的统计信息。新创建的非表达式索引可以立即使用这些统计信息来确定索引的有用性。对于新的表达式索引,需要运行ANALYZE 或等待autovacuum守护进程分析表以为这些索引生成统计信息。
对于大多数索引方法,创建索引的速度取决于maintenance_work_mem的设置。较大的值将减少索引创建所需的时间,只要不将其设置为实际可用的内存量以上,否则会导致机器进入交换状态。
UXsinoDB可以利用多个CPU来构建索引,以便更快地处理表行。这个功能被称为并行索引构建。对于支持并行构建索引的索引方法(目前只有B-tree),maintenance_work_mem指定了每个索引构建操作可以使用的最大内存量,无论启动了多少个工作进程。通常,成本模型会自动确定应请求多少个工作进程(如果需要的话)。并行索引构建可能会受益于增加maintenance_work_mem,而等效的串行索引构建将几乎不会受益。请注意,maintenance_work_mem可能会影响请求的工作进程数,因为并行工作进程必须至少有32MB的maintenance_work_mem预算份额。领导进程还必须有剩余的32MB份额。增加max_parallel_maintenance_workers可能允许使用更多的工作进程,这将减少索引创建所需的时间,只要索引构建不是I/O受限的。当然,还应该有足够的CPU容量,否则会空闲。
通过ALTER TABLE直接设置parallel_workers的值可以控制针对表请求多少个并行工作进程。这完全绕过了成本模型,并防止maintenance_work_mem影响请求多少个并行工作进程。通过ALTER TABLE将parallel_workers设置为0将在所有情况下禁用表上的并行索引构建。
提示
在调整索引构建的过程中,您可能希望重置parallel_workers。这样可以避免意外更改查询计划,因为parallel_workers会影响所有并行表扫描。
虽然CREATE INDEX选项CONCURRENTLY支持没有特殊限制的并行构建,但实际上只有第一个表扫描是并行执行的。
使用DROP INDEX删除索引。
与任何长时间运行的事务一样,对表上的CREATE INDEX可能会影响可以由任何其他表的并发VACUUM删除的元组。
以前的UXsinoDB版本还有一种R-tree索引方法。该方法已被删除,因为它与GiST方法相比没有显着优势。如果指定了USING rtree,CREATE INDEX将将其解释为USING gist,以简化旧数据库转换为GiST。运行CREATE INDEX的每个后端将在ux_stat_progress_create_index视图中报告其进度。
示例
在表films的列title上创建唯一的B-tree索引:
CREATE UNIQUE INDEX title_idx ON
要在表films的列title上创建一个唯一的B-树索引并且包括列director和rating:
CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);
创建一个禁用去重的 B-Tree 索引:
CREATE INDEX title_idx ON films (title) WITH (deduplicate_items = off);
创建一个表达式 lower(title) 的索引,允许高效的不区分大小写搜索:
CREATE INDEX ON films ((lower(title)));
(在此示例中,我们选择省略索引名称,因此系统将选择一个名称,通常为 films_lower_idx。)
创建一个具有非默认排序规则的索引:
CREATE INDEX title_idx_german ON films (title COLLATE "de_DE");
创建一个具有非默认空值排序顺序的索引:
CREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST);
创建一个具有非默认填充因子的唯一索引:
CREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70);
创建一个禁用快速更新的 GIN索引:
CREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);
在表 films 中的列 code 上创建一个索引,并使索引驻留在表空间 indexspace 中:
CREATE INDEX code_idx ON films (code) TABLESPACE indexspace;
创建一个GiST索引,用于点属性,以便我们可以在转换函数的结果上高效使用框运算符:
CREATE INDEX pointloc
ON points USING gist (box(location,location));
SELECT * FROM points
WHERE box(location,location) && '(0,0),(1,1)'::box;
创建一个不锁定写入表的索引:
CREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);
兼容性
CREATE INDEX是UXsinoDB的语言扩展。SQL标准中没有索引的规定。
另请参阅
ALTER INDEX、DROP INDEX、REINDEX
CREATE LANGUAGE
CREATE LANGUAGE — 定义新的过程语言
概要
CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name
HANDLER call_handler [ INLINE inline_handler ] [ VALIDATOR valfunction ] [ INCLUDING OUT ARGUMENTS]
CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name
描述
CREATE LANGUAGE在UXsinoDB数据库中注册一个新的过程语言。随后,可以在这种新语言中定义函数和过程。
CREATE LANGUAGE实际上将语言名称与负责执行使用该语言编写的函数的处理程序函数相关联。
CREATE OR REPLACE LANGUAGE将创建一个新语言或替换现有定义。如果语言已经存在,则根据命令更新其参数,但语言的所有权和权限设置不会更改,并且任何使用该语言编写的现有函数都被认为仍然有效。
必须具有UXsinoDB超级用户权限才能注册新语言或更改现有语言的参数。但是,一旦创建了语言,将其所有权分配给非超级用户是有效的,该用户可以删除它、更改其权限、重命名它或将其分配给新所有者。(但是,不要将底层C函数的所有权分配给非超级用户;这将为该用户创建特权升级路径。)
不提供任何处理程序函数的CREATE LANGUAGE形式已经过时。为了向后兼容旧的转储文件,它被解释为CREATEEXTENSION。如果将语言打包到同名扩展中,则这将起作用,这是设置过程语言的常规方式。
参数
-
TRUSTED
TRUSTED指定该语言不授予用户否则无法访问的数据权限。如果在注册语言时省略此关键字,则只有具有UXsinoDB超级用户特权的用户才能使用该语言创建新函数。 -
PROCEDURAL
这是一个噪声词。 -
name
新过程语言的名称。名称必须在数据库中的语言中是唯一的。 -
HANDLERcall_handler
call_handler是一个先前注册的函数的名称,将被调用以执行过程语言的函数。过程语言的调用处理程序必须用编译语言(如C)编写,使用版本1调用约定,并在UXsinoDB中注册为一个不带参数并返回language_handler类型的函数,这是一个占位符类型,仅用于将函数标识为调用处理程序。 -
INLINEinline_handler
inline_handler是一个先前注册的函数的名称,将被调用以执行匿名代码块(DO命令)的语言。如果没有指定inline_handler函数,则该语言不支持匿名代码块。处理程序函数必须接受一个类型为internal的参数,该参数将是DO命令的内部表示形式,并且通常会返回void。处理程序的返回值将被忽略。 -
VALIDATORvalfunction
valfunction是一个先前注册的函数的名称,将在创建语言中的新函数时被调用以验证新函数。如果没有指定验证器函数,则创建新函数时不会检查新函数。验证器函数必须接受一个类型为oid的参数,该参数将是要创建的函数的OID,并通常返回void。
验证器函数通常会检查函数体的语法正确性,但它也可以查看函数的其他属性,例如语言无法处理某些参数类型。要发出错误信号,验证器函数应使用ereport() 函数。函数的返回值将被忽略。
INCLUDING OUT ARGUMENTS
指定该语言兼容Oracle函数的OUT和INOUT参数特性。
注释
使用DROP LANGUAGE删除过程语言。
系统目录ux_language记录有关当前安装的语言的信息。此外,uxsql命令\dL列出已安装的语言。
要在过程语言中创建函数,用户必须具有USAGE是语言的权限。默认情况下,对于受信任的语言,USAGE被授予给PUBLIC(即所有人)。如果需要,可以撤销此权限。
过程语言是针对各个数据库本地的。但是,语言可以安装到template1数据库中,这将使其自动在所有随后创建的数据库中可用。
示例
创建新过程语言的最小序列为:
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
AS '$libdir/plsample'
LANGUAGE C;
CREATE LANGUAGE plsample
HANDLER plsample_call_handler;
通常,这将在扩展的创建脚本中编写,用户将执行以下操作来安装扩展:
CREATE EXTENSION plsample;
兼容性
CREATE LANGUAGE 是 UXsinoDB 的扩展。
另请参阅
ALTER LANGUAGE、CREATE FUNCTION、DROP LANGUAGE、GRANT、REVOKE
CREATE MATERIALIZED VIEW
CREATE MATERIALIZED VIEW — 定义新的物化视图
概要
CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] table_name
[ { REFRESH FAST | REFRESH COMPLETE | REFRESH FORCE | REFRESH FORCE FAST | REFRESH FORCE COMPLETE } ]
[ { ON DEMAND | ON STATEMENT | NEVER REFRESH } ]
[ (column_name [, ...] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ TABLESPACE tablespace_name ]
AS query
[ WITH [ NO ] DATA ]
描述
CREATE MATERIALIZED VIEW定义一个查询的物化视图。该查询在命令发出时执行并用于填充视图(除非使用WITH NO DATA),并且可以稍后使用REFRESH MATERIALIZED VIEW进行刷新。
CREATE MATERIALIZED VIEW类似于CREATE TABLE AS,但它还记住了用于初始化视图的查询,以便在需要时可以刷新。物化视图具有许多与表相同的属性,但不支持临时物化视图。
CREATE MATERIALIZED VIEW需要对用于物化视图的模式具有CREATE权限。
参数
-
IF NOT EXISTS
如果已经存在同名的物化视图,则不会抛出错误。在这种情况下,会发出通知。请注意,不能保证现有的物化视图与将要创建的视图相似。 -
table_name
要创建的物化视图的名称(可选模式限定)。该名称必须与同一模式中的任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。 -
column_name
新材料化视图中的列名。如果未提供列名,则从查询的输出列名中获取列名。 -
USING method
此可选子句指定用于存储新材料化视图内容的表访问方法;该方法需要是类型为TABLE的访问方法。如果未指定此选项,则为新材料化视图选择默认表访问方法。有关更多信息,请参见default_table_access_method。 -
WITH ( storage_parameter[=value] [, ... ])
此子句指定新材料化视图的可选存储参数;有关更多信息,请参见“存储参数”在CREATE TABLE文档中。所有支持CREATE TABLE的参数也支持CREATE MATERIALIZED VIEW。有关更多信息,请参见CREATE TABLE。 -
TABLESPACE tablespace_name
tablespace_name是要创建新材料化视图的表空间的名称。如果未指定,则会查询default_tablespace。 -
query
一个SELECT、TABLE命令或VALUES 命令。此查询将在安全受限操作中运行;特别是,调用自己创建临时表的函数将失败。 -
WITH [ NO ] DATA
此子句指定材料化视图是否应在创建时填充。如果没有,材料化视图将被标记为不可扫描,并且在使用REFRESH MATERIALIZED VIEW之前无法查询。 -
[ {
REFRESH FAST|REFRESH COMPLETE|REFRESH FORCE|REFRESH FORCE FAST|REFRESH FORCE COMPLETE} ]
指定自动更新物化视图的更新方式:REFRESH FAST增量更新,只更新自上次更新以后进行的修改,REFRESH COMPLETE通过执行物化视图定义的query语句,对整个物化视图进行全量更新,REFRESH FORCE|REFRESH FORCE FAST|REFRESH FORCE COMPLETE在更新时会去判断是否可以进行快速更新,如果可以则采用快速更新方式,否则采用全量更新。 -
[ {
ON DEMAND|ON STATEMENT|NEVER REFRESH} ]
指定自动更新物化视图的更新类型:ON DEMAND为手动方式更新,与普通物化视图类似,ON STATEMENT在物化视图的基表上执行任意DML操作时都会发生自动更新,NEVER REFRESH不能以任何方式更新该物化视图。
兼容性
CREATE MATERIALIZED VIEW是UXsinoDB的扩展。
另请参阅
ALTER MATERIALIZED VIEW、CREATE TABLE AS、CREATE VIEW、DROP MATERIALIZED VIEW、REFRESH MATERIALIZED VIEW
CREATE OPERATOR
CREATE OPERATOR — 定义新运算符
概要
CREATE OPERATOR name (
{FUNCTION|PROCEDURE} = function_name
[, LEFTARG = left_type ] [, RIGHTARG = right_type ]
[, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]
[, RESTRICT = res_proc ] [, JOIN = join_proc ]
[, HASHES ] [, MERGES ]
)
描述
CREATE OPERATOR定义一个新的运算符,name定义运算符的用户成为其所有者。如果给出模式名称,则在指定模式中创建运算符。否则,它将在当前模式中创建。
运算符名称是以下列表中最多NAMEDATALEN-1(默认为63)个字符的序列:
+ - * / < > = ~ ! @ # % ^ & | ` ?
对名称的选择有一些限制:
-
--和/*不能出现在运算符名称的任何位置,因为它们将被视为注释的开始。 -
多字符运算符名称不能以
+或-结尾,除非名称还包含至少一个这些字符之一:
~ ! @ # % ^ & | ` ?
例如,@-是允许的运算符名称,但*-不是。此限制允许UXsinoDB解析符合SQL标准的命令,而无需在标记之间添加空格。
- 使用
=>作为运算符名称已被弃用。它可能在将来的版本中被禁止。
运算符!=映射到<>表示这两个名称始终等价。
对于二元运算符,必须定义LEFTARG和RIGHTARG。对于前缀运算符,只需定义RIGHTARG。函数function_name必须先使用CREATE FUNCTION定义,并且必须定义为接受指定类型的正确数量的参数(一个或两个)。
在CREATE OPERATOR的语法中,关键字FUNCTION和PROCEDURE是等效的,但引用的函数在任何情况下都必须是函数,而不是过程。在此使用关键字PROCEDURE是历史遗留问题,已经不推荐使用。
其他子句指定了可选的运算符优化子句。
要能够创建运算符,必须对参数类型和返回类型具有USAGE权限,并对底层函数具有EXECUTE权限。如果指定了交换器或否定运算符,则必须拥有这些运算符。
参数
-
name
要定义的运算符的名称。有关允许的字符,请参见上文。名称可以是模式限定的,例如CREATE OPERATOR myschema.+ (...)。如果没有,则在当前模式中创建运算符。在同一模式中,如果它们作用于不同的数据类型,则两个运算符可以具有相同的名称。这称为重载。 -
function_name
用于实现此运算符的函数。 -
left_type
运算符的左操作数的数据类型(如果有)。对于前缀运算符,应省略此选项。 -
right_type
运算符的右操作数的数据类型。 -
com_op
此运算符的交换器。 -
neg_op
此运算符的否定运算符。 -
res_proc
此运算符的限制选择性估计器函数。 -
join_proc
此运算符的连接选择性估计器函数。 -
HASHES
表示此运算符可以支持哈希连接。 -
MERGES
表示此运算符可以支持合并连接。
要在 com_op 或其他可选参数中给出模式限定的运算符名称,请使用 OPERATOR() 语法,例如:
COMMUTATOR = OPERATOR(myschema.===) ,
注解
在CREATE OPERATOR中无法指定运算符的词法优先级,因为解析器的优先级行为是固定的。
过时的选项SORT1、SORT2、LTCMP和GTCMP曾用于指定与可合并操作符相关联的排序操作符的名称。这已不再必要,因为关于相关操作符的信息是通过查看B树操作符族而获得的。如果给定了其中一个选项,则除了隐式设置MERGES为true之外,它将被忽略。
使用DROP OPERATOR命令从数据库中删除用户定义的操作符。使用ALTER OPERATOR命令修改数据库中的操作符。
示例
下面的命令为数据类型框定义了一个新的运算符,面积相等,用于数据类型box:
CREATE OPERATOR === (
LEFTARG = box,
RIGHTARG = box,
FUNCTION = area_equal_function,
COMMUTATOR = ===,
NEGATOR = !==,
RESTRICT = area_restriction_function,
JOIN = area_join_function,
HASHES, MERGES
);
兼容性
CREATE OPERATOR是UXsinoDB的扩展。SQL标准中没有用户定义操作符的规定。
另请参阅
参见ALTER OPERATOR、CREATE OPERATOR CLASS、DROP OPERATOR
CREATE OPERATOR CLASS
CREATE OPERATOR CLASS — 定义新的操作符类
概述
CREATE OPERATOR CLASS name [ DEFAULT ] FOR TYPE data_type
USING index_method [ FAMILY family_name ] AS
{ OPERATOR strategy_number operator_name [ ( op_type, op_type ) ] [ FOR SEARCH | FOR ORDER BY sort_family_name ]
| FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name ( argument_type [, ...] )
| STORAGE storage_type
} [, ... ]
描述
CREATE OPERATOR CLASS创建一个新的操作符类。操作符类定义了特定数据类型如何与索引一起使用。操作符类指定了某些操作符将填充特定角色或“策略”,用于此数据类型和此索引方法。操作符类还指定了在选择索引列时由索引方法使用的支持函数。在创建操作符类之前,必须定义所有操作符和函数。
如果给出模式名称,则在指定的模式中创建操作符类。否则,它将在当前模式中创建。在同一模式中的两个操作符类只有在它们是针对不同索引方法时才能具有相同的名称。
定义操作符类的用户成为其所有者。目前,创建用户必须是超级用户。(这个限制是因为错误的操作符类定义可能会混淆甚至崩溃服务器。)
CREATE OPERATOR CLASS目前不检查操作符类定义是否包括所有操作符和函数。索引方法所需的运算符和函数,以及运算符和函数是否形成自洽的集合,都没有在此方法中定义。用户有责任定义有效的运算符类。
相关的运算符类可以分组成运算符族。要将新的运算符类添加到现有的族中,请在CREATE OPERATOR CLASS中指定FAMILY选项。如果没有此选项,则新类将被放置在与新类同名的族中(如果不存在,则创建该族)。
参数
-
name
要创建的运算符类的名称。名称可以带有模式限定符。 -
DEFAULT
如果存在,则运算符类将成为其数据类型的默认运算符类。每个特定数据类型和索引方法最多只能有一个默认运算符类。 -
data_type
此运算符类所用的列数据类型。 -
index_method
此运算符类所用的索引方法的名称。 -
family_name
要将此运算符类添加到的现有运算符族的名称。如果未指定,则使用与运算符类同名的族(如果不存在,则创建它)。 -
strategy_number
与运算符类相关联的运算符的索引方法策略号。 -
operator_name
与运算符类相关联的运算符的名称(可选带有模式限定符)。 -
op_type
在OPERATOR子句中,运算符的操作数数据类型,或NONE表示前缀运算符。在正常情况下,操作数数据类型可以省略,因为它们与运算符类的数据类型相同。
在FUNCTION子句中,函数预期支持的操作数数据类型(用于B树比较函数和哈希函数),如果与函数的输入数据类型(对于B树排序支持函数和B树等效图像函数)或类的数据类型(对于B树排序支持函数、B树等效图像函数以及GiST、SP-GiST、GIN和BRIN运算符类中的所有函数)不同。这些默认值是正确的,因此在FUNCTION子句中不需要指定op_type,除非是用于支持跨数据类型比较的B树排序支持函数。
sort_family_name
描述与排序运算符相关的排序顺序的现有btree运算符族的名称(可选带有模式限定符)。
如果未指定FOR SEARCH或FOR ORDER BY,则FOR SEARCH是默认值。
-
support_number
与运算符类相关联的函数的索引方法支持函数号。 -
function_name
一个函数的名称(可选地带有模式限定符),它是操作符类的索引方法支持函数。 -
argument_type
函数的参数数据类型。 -
storage_type
实际存储在索引中的数据类型。通常这与列数据类型相同,但某些索引方法(目前包括GiST、GIN、SP-GiST和BRIN)允许它不同。除非索引方法允许使用不同的类型,否则必须省略STORAGE子句。如果指定的列data_type为anyarray,则可以将storage_type声明为anyelement,以表示索引条目是属于每个特定索引所创建的实际数组类型的元素类型的成员。
OPERATOR、FUNCTION和STORAGE子句可以以任何顺序出现。
注释
由于索引机制在使用函数之前不会检查访问权限,因此在操作符类中包含函数或操作符等同于授予公共执行权限。这通常不是一个问题,对于在操作符类中有用的函数类型。
不应该使用SQL函数定义操作符。SQL函数可能会被内联到调用查询中,这将防止优化器识别查询与索引匹配。
不再支持OPERATOR子句可以包括RECHECK选项,因为索引操作符是否丢失现在是在运行时动态确定的。这允许有效地处理操作符可能或可能不会丢失的情况。
示例
以下示例命令为数据类型_int4(int4数组)定义了一个GiST索引操作符类。
CREATE OPERATOR CLASS gist__int_ops
DEFAULT FOR TYPE _int4 USING gist AS
OPERATOR 3 &&,
OPERATOR 6 = (anyarray, anyarray),
OPERATOR 7 @>,
OPERATOR 8 <@,
OPERATOR 20 @@ (_int4, query_int),
FUNCTION 1 g_int_consistent (internal, _int4, smallint, oid, internal),
FUNCTION 2 g_int_union (internal, internal),
FUNCTION 3 g_int_compress (internal),
FUNCTION 4 g_int_decompress (internal),
FUNCTION 5 g_int_penalty (internal, internal, internal),
FUNCTION 6 g_int_picksplit (internal, internal),
FUNCTION 7 g_int_same (_int4, _int4, internal);
兼容性
CREATE OPERATOR CLASS是UXsinoDB的扩展。SQL标准中没有CREATE OPERATOR CLASS语句。
另请参阅
ALTER OPERATOR CLASS、DROPOPERATOR CLASS、CREATE OPERATOR FAMILY、ALTER OPERATOR FAMILY
CREATE OPERATOR FAMILY
CREATE OPERATOR FAMILY — 定义一个新的操作符族
概要
CREATE OPERATOR FAMILY name USING index_method
描述
CREATE OPERATOR FAMILY创建一个新的操作符族。一个操作符族定义了一组相关的操作符类,以及一些额外的操作符和支持函数,这些操作符和函数与这些操作符类兼容,但对于任何单个索引的功能来说并不是必要的。(对于索引必要的操作符和函数应该被分组在相关的操作符类中,而不是在操作符族中“松散”存在。通常,单数据类型操作符被绑定到操作符类中,而跨数据类型操作符可以在包含两种数据类型操作符类的操作符族中松散存在。)
新的操作符族最初是空的。应该通过发出后续的CREATE OPERATOR CLASS命令来添加包含的操作符类, 以及可选的ALTER OPERATOR FAMILY命令来添加“松散”的操作符及其相应的支持函数。
如果给出模式名称,则在指定的模式中创建操作符族。否则,它将在当前模式中创建。同一模式中的两个操作符族只有在它们是针对不同索引方法时才能具有相同的名称。
定义操作符族的用户成为其所有者。目前,创建用户必须是超级用户。(这个限制是因为错误的操作符族定义可能会混淆甚至崩溃服务器。)
参数
-
name
要创建的操作符族的名称。名称可以是模式限定的。 -
index_method
此操作符族所用于的索引方法名称。
兼容性
CREATE OPERATOR FAMILY是UXsinoDB扩展。SQL标准中没有CREATE OPERATOR FAMILY语句。
参见
ALTER OPERATOR FAMILY,DROP OPERATOR FAMILY,CREATE OPERATOR CLASS,ALTER OPERATOR CLASS,DROPOPERATOR CLASS
CREATE POLICY
CREATE POLICY — 为表定义新的行级安全策略
概要
CREATE POLICY name ON table_name
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]
描述
CREATE POLICY命令为表定义新的行级安全策略。注意,必须在表上启用行级安全(使用ALTER TABLE ... ENABLE ROW LEVEL SECURITY)才能应用创建的策略。
策略授予选择、插入、更新或删除与相关策略表达式匹配的行的权限。现有表行将根据USING中指定的表达式进行检查,而将通过INSERT或UPDATE创建的新行将根据WITH CHECK中指定的表达式进行检查。当USING表达式对于给定行返回true时,该行对用户可见,而如果返回false或null,则该行不可见。当WITH CHECK表达式对于行返回true时,该行将被插入或更新,而如果返回false或null,则会发生错误。
对于INSERT、UPDATE和MERGE语句,WITH CHECK表达式在触发BEFORE触发器之后执行,并在进行任何实际数据修改之前执行。因此,BEFORE ROW触发器可能会修改要插入的数据,从而影响安全策略检查的结果。WITH CHECK表达式在任何其他约束之前执行。
策略名称是针对每个表的。因此,一个策略名称可以用于多个表。
不同的表需要为每个表定义适当的定义。策略可以应用于特定的命令或特定的角色。新创建的策略的默认设置是它们适用于所有命令和角色,除非另有规定。一个命令可能适用多个策略;有关更多详细信息,请参见下面的命令类型应用的策略 。命令类型应用的策略总结了不同类型的策略如何适用于特定的命令。
对于可以具有USING和WITH CHECK表达式(ALL和UPDATE)的策略,如果未定义WITH CHECK表达式,则USING表达式将用于确定哪些行是可见的(正常的USING情况)以及哪些新行将被允许添加(WITH CHECK情况)。
如果启用了行级安全性,但不存在适用的策略,则假定存在一个“默认拒绝”策略,因此没有行将可见或可更新。
参数
-
name
策略名称。必须是标识符。 -
table_name
要为其定义策略的表的名称。必须是标识符。 -
PERMISSIVE
指定要将策略创建为宽容策略。所有适用于给定查询的宽容策略将使用布尔“OR”运算符组合在一起。通过创建宽容策略,管理员可以添加可以访问的记录集。默认情况下,策略是宽容的。 -
RESTRICTIVE
指定要将策略创建为限制性策略。所有适用于给定查询的限制性策略将使用布尔“AND”运算符组合在一起。通过创建限制性策略,管理员可以减少可以访问的记录集,因为必须通过每个记录的所有限制性策略。
请注意,在使用限制性策略之前,需要至少有一个宽容策略来授予对记录的访问权限。如果只存在限制性策略,则无法访问任何记录。当存在宽容和限制性策略的混合时,只有在至少有一个宽容策略通过的情况下,记录才是可访问的,除了所有限制性策略之外。
-
command
策略适用的命令。有效选项为ALL、SELECT、INSERT、UPDATE和DELETE。ALL是默认值。有关如何应用这些的具体信息,请参见下面的说明。 -
role_name
要应用策略的角色。默认值为PUBLIC,这将使策略适用于所有角色。 -
using_expression
任何 SQL条件表达式(返回boolean)。条件表达式不能包含任何聚合或窗口函数。如果启用了行级安全性,则此表达式将添加到引用该表的查询中。表达式返回true的行将可见。表达式返回false或null的任何行将对用户不可见(在SELECT中),并且不可用于修改(在UPDATE或DELETE中)。这些行将被静默抑制;不会报告任何错误。 -
check_expression
任何SQL条件表达式(返回boolean)。条件表达式不能包含任何聚合或窗口函数。如果启用了行级安全性,则此表达式将用于针对该表的INSERT和UPDATE查询。只有表达式评估为true的行将被允许。如果表达式对插入的任何记录或更新后的任何记录评估为false或 null,则会抛出错误。请注意,check_expression是针对建议的新行内容进行评估,而不是针对原始内容进行评估。
每个命令的策略
ALL
对于策略使用ALL意味着它将适用于所有命令,无论命令类型如何。如果存在ALL策略并且存在更具体的策略,则将同时应用ALL策略和更具体的策略(或策略)。此外,如果仅定义了USING表达式,则ALL策略将应用于查询的选择侧和修改侧,都使用USING表达式。
例如,如果发出UPDATE,则ALL策略将适用于UPDATE将能够选择要更新的行(应用USING表达式),以及对于结果更新的行,检查它们是否允许添加到表中(应用WITH CHECK表达式(如果已定义),否则应用USING表达式)。如果INSERT或UPDATE命令尝试添加未通过ALL策略的WITH CHECK表达式的行,则整个命令将被中止。
-
SELECT
对于策略使用SELECT意味着它将适用于SELECT查询和在定义策略的关系上需要SELECT权限的任何时候。结果是,仅返回通过SELECT策略的记录,而不是关系中的所有记录。需要SELECT权限的查询(例如UPDATE)也仅会看到SELECT策略允许的记录。SELECT策略不能具有WITH CHECK表达式。使用CHECK表达式的策略仅适用于从关系中检索记录的情况。 -
INSERT
将INSERT用于策略意味着它将适用于包含INSERT操作的INSERT命令和MERGE命令。未通过此策略的插入行将导致策略违规错误,并且整个INSERT命令将被中止。INSERT策略不能具有USING表达式,因为它仅适用于将记录添加到关系的情况。
请注意,使用ON CONFLICT DO UPDATE的INSERT检查INSERT策略的WITH CHECK表达式仅适用于由INSERT路径附加到关系的行。
UPDATE
将UPDATE用于策略意味着它将适用于UPDATE、SELECT FOR UPDATE和SELECT FOR SHARE命令,以及INSERT命令的辅助ON CONFLICT DO UPDATE子句。包含UPDATE操作的MERGE命令也会受到影响。由于UPDATE涉及提取现有记录并用新的修改记录替换它,UPDATE策略接受USING表达式和WITH CHECK表达式。USING表达式确定UPDATE命令将看到哪些记录进行操作,而WITH CHECK表达式定义允许存储回关系的修改行。
任何更新值未通过WITH CHECK表达式的行都会导致错误,并且整个命令将被中止。如果仅指定USING子句,则该子句将用于USING和WITH CHECK两种情况。
通常,UPDATE命令还需要从正在更新的关系中读取数据(例如,在WHERE子句或RETURNING子句中,或在SET子句的右侧表达式中)。在这种情况下,还需要在正在更新的关系上具有SELECT权限,并且将应用适当的SELECT或ALL策略,除了UPDATE策略之外。因此,用户必须通过SELECT或ALL策略访问正在更新的行,除了通过UPDATE或ALL策略被授予更新行的权限之外。
当INSERT命令具有辅助ON CONFLICT DO UPDATE子句时,如果采用UPDATE路径,则将首先检查要更新的行是否符合任何UPDATE策略的USING表达式,然后检查新的更新行是否符合WITH CHECK表达式。但请注意,与独立的UPDATE不同,INSERT命令的ON CONFLICT DO UPDATE子句仅适用于附加到关系的行。如果现有行不通过USING表达式,则会抛出错误(UPDATE路径永远不会被默默地避免)。
DELETE
使用DELETE策略意味着它将应用于DELETE命令。只有通过此策略的行才会被DELETE命令看到。可能会通过SELECT看到的行不可删除,如果它们不通过DELETE策略的USING表达式。
在大多数情况下,DELETE命令还需要从它正在删除的关系中读取数据(例如,在WHERE子句或RETURNING子句中)。在这种情况下,还需要在关系上应用SELECT权限,并且将应用适当的SELECT或ALL策略,除了DELETE策略之外。因此,用户必须通过SELECT或ALL策略访问要删除的行,除了通过DELETE或ALL策略授予删除行的权限之外。
DELETE策略不能有WITH CHECK表达式,因为它仅适用于从关系中删除记录的情况,因此没有新行可供检查。
命令类型应用的策略表
| 命令 | SELECT/ALL策略 (USING表达式) | INSERT/ALL策略 (WITH CHECK表达式) | UPDATE/ALL策略 (USING表达式) | UPDATE/ALL策略 (WITH CHECK表达式) | DELETE/ALL策略 (USING表达式) |
|---|---|---|---|---|---|
SELECT | 现有行 | — | — | — | — |
SELECT FOR UPDATE/SHARE | 现有行 | — | 现有行 | — | — |
INSERT / MERGE ... THEN INSERT | — | 新行 | — | — | — |
INSERT ... RETURNING | 新行[a] | 新行 | — | — | — |
UPDATE / MERGE ... THEN UPDATE | 现有行和新行[a] | — | 现有行 | 新行 | — |
DELETE | 现有行[a] | — | — | — | 现有行 |
ON CONFLICT DO UPDATE | 现有行和新行 | — | 现有行 | 新行 | — |
[a] 如果需要读取现有行或新行(例如,一个引用关系中的列的 WHERE 或 RETURNING 子句)。
多个策略的应用
当不同命令类型的多个策略应用于同一命令时(例如,应用于UPDATE命令的SELECT和UPDATE策略),则用户必须具有两种类型的权限(例如,从关系中选择行的权限以及更新它们的权限)。因此,一种类型的策略表达式与另一种类型的策略表达式使用AND运算符组合。
当同一命令类型的多个策略应用于同一命令时,必须至少有一个PERMISSIVE策略授予对关系的访问权限,并且所有RESTRICTIVE策略必须通过。因此,所有PERMISSIVE策略表达式使用OR组合,所有RESTRICTIVE策略表达式使用AND组合,结果使用AND组合。如果没有PERMISSIVE策略,则拒绝访问。
请注意,为了组合多个策略,ALL策略被视为具有与应用的其他类型的策略相同的类型。
例如,在需要SELECT和UPDATE权限的UPDATE命令中,如果有多个适用的每种类型的策略,则将按以下方式组合它们:
expression from RESTRICTIVE SELECT/ALL policy 1
AND
expression from RESTRICTIVE SELECT/ALL policy 2
AND
...
AND
(
expression from PERMISSIVE SELECT/ALL policy 1
OR
expression from PERMISSIVE SELECT/ALL policy 2
OR
...
)
AND
expression from RESTRICTIVE UPDATE/ALL policy 1
AND
expression from RESTRICTIVE UPDATE/ALL policy 2
AND
...
AND
(
expression from PERMISSIVE UPDATE/ALL policy 1
OR
expression from PERMISSIVE UPDATE/ALL policy 2
OR
...
)
注释
您必须是表的所有者才能为其创建或更改策略。
虽然策略将应用于对数据库中表的显式查询,但在系统执行内部引用完整性检查或验证约束时不会应用它们。这意味着有间接的方法来确定给定值是否存在。例如,尝试将重复值插入到作为主键或具有唯一约束的列中。如果插入失败,则用户可以推断该值已经存在。(此示例假定用户被策略允许插入他们不被允许查看的记录。)另一个例子是,允许用户插入到引用另一个表的表中,否则隐藏的表。用户可以通过向引用表插入值来确定存在性,成功将表明该值存在于引用表中。这些问题可以通过精心制定策略来解决,以防止用户能够插入、删除或更新可能指示他们无法看到的值的记录,或者使用生成的值(例如,代理键)而不是具有外部含义的键。
通常,系统将在用户查询中出现的限定条件之前强制执行使用安全策略施加的过滤器条件,以防止受保护的数据意外暴露给可能不可信的用户定义函数。然而,系统(或系统管理员)标记为LEAKPROOF的函数和运算符可能会在策略表达式之前评估,因为它们被认为是可信的。
由于策略表达式直接添加到用户的查询中,因此使用给定策略的用户必须能够访问表或函数中引用的任何表或函数,否则当尝试查询启用了行级安全性的表时,他们将仅收到权限被拒绝的错误。但是,这不会改变视图的工作方式。与普通查询和视图一样,引用视图的表的权限检查和策略将使用视图所有者的权限和适用于视图所有者的任何策略,除非视图使用security_invoker选项定义(请参见CREATE VIEW)。
没有单独的策略适用于MERGE。相反,在执行MERGE时,将应用为SELECT、INSERT、UPDATE和DELETE定义的策略,具体取决于执行的操作。
兼容性
CREATE POLICY是UXsinoDB的扩展。
另请参见
ALTER POLICY、DROP POLICY、ALTER TABLE。
CREATE PROCEDURE
CREATE PROCEDURE — 定义新过程
概要
CREATE [ OR REPLACE ] PROCEDURE
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| { AS | IS } 'definition'
| { AS | IS } 'obj_file', 'link_symbol'
} ...
描述
CREATE PROCEDURE定义新过程。CREATE OR REPLACE PROCEDURE将创建新过程或替换现有定义。要定义过程,用户必须具有语言的USAGE权限。
如果包含模式名称,则在指定模式中创建过程。否则,将在当前模式中创建。新过程的名称不能与同一模式中具有相同输入参数类型的任何现有过程或函数相匹配。但是,具有不同参数类型的过程和函数可以共享名称(这称为重载)。
要替换现有过程的当前定义,请使用CREATE OR REPLACE PROCEDURE。无法以这种方式更改过程的名称或参数类型(如果尝试,则实际上将创建一个新的、不同的过程)。
当使用CREATE OR REPLACE PROCEDURE替换现有过程时,过程的所有权和权限不会更改。所有其他过程属性都分配了在命令中指定或暗示的值。您必须拥有该过程的所有权。替换它(这包括成为拥有角色的成员)。
创建过程的用户成为过程的所有者。
要能够创建过程,必须在参数类型上具有USAGE权限。
参数
-
name
要创建的过程的名称(可选模式限定)。 -
argmode
参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。 -
argname
参数的名称。 -
argtype
过程参数的数据类型(可选模式限定),如果有的话。参数类型可以是基本、复合或域类型,也可以引用表列的类型。
根据实现语言,还可以允许指定伪类型,例如cstring。伪类型表示实际参数类型不完全指定,或不在普通SQL数据类型集合之内。
通过编写table_name.column_name%TYPE来引用列的类型。使用此功能有时可以帮助使过程独立于表定义的更改。
-
default_expr
如果未指定参数,则用作默认值的表达式。表达式必须可强制转换为参数的参数类型。所有具有默认值的输入参数都必须具有默认值。 -
lang_name
实现过程的语言的名称。它可以是sql、c、internal或用户定义的过程语言的名称,例如pluxsql。如果指定了sql_body,则默认为sql。将名称括在单引号中已不推荐使用,并且需要匹配大小写。 -
TRANSFORM{FOR TYPE type_name} [, ... ] }
列出调用过程应用的转换。转换在SQL类型和特定于语言的数据类型之间进行转换;请参阅CREATE TRANSFORM。过程语言实现通常具有内置类型的硬编码知识,因此这些不需要在此处列出。如果过程语言实现不知道如何处理类型并且没有提供转换,则它将回退到默认行为以转换数据类型,但这取决于实现。 -
[EXTERNAL] SECURITY INVOKER
[EXTERNAL] SECURITY DEFINER
SECURITY INVOKER表示该过程将以调用它的用户的权限执行。这是默认设置。SECURITY DEFINER指定该过程将以拥有它的用户的权限执行。
关键字EXTERNAL可用于SQL符合性,但是它是可选的,因为与SQL不同,此功能适用于所有过程,而不仅仅是外部过程。
SECURITY DEFINER过程不能执行事务控制语句(例如,COMMIT和ROLLBACK,具体取决于语言)。
configuration_parameter
value
SET子句会在进入过程时将指定的配置参数设置为指定的值,然后在过程退出时将其恢复为先前的值。SET FROM CURRENT会将CREATE PROCEDURE执行时的当前参数值保存为进入过程时要应用的值。
如果将SET子句附加到过程,则在过程内部为同一变量执行的SET LOCAL命令的影响仅限于该过程:配置参数的先前值仍将在过程退出时恢复。但是,普通的SET命令(不带LOCAL)会覆盖SET子句,就像它会为先前的SET LOCAL命令一样:这样的命令的影响将在过程退出后持续存在,除非当前事务被回滚。
如果将SET子句附加到过程,则该过程不能执行事务控制语句(例如,COMMIT和ROLLBACK,具体取决于语言)。
有关允许的参数名称和值的更多信息,请参见SET。
definition
定义过程的字符串常量;其含义取决于语言。它可以是内部过程名称、对象文件的路径、SQL命令或过程性语言中的文本。
通常有助于使用美元引用编写过程定义字符串,而不是使用正常的单引号语法。如果没有使用美元引用,则过程定义中的任何单引号或反斜杠都必须加倍转义。
obj_file,link_symbol
当C语言源代码中的过程名称与SQL过程的名称不同时,此形式的AS子句用于动态可加载的C语言过程。字符串obj_file是包含编译的C过程的共享库文件的名称,并且被解释关于LOAD命令。字符串link_symbol是过程的链接符号,即C语言源代码中过程的名称。如果省略链接符号,则假定与正在定义的SQL过程名称相同。
当重复的CREATE PROCEDURE调用引用相同的对象文件时,该文件仅在会话期间加载一次。要卸载和重新加载文件(可能在开发过程中),请启动新会话。
sql_body
LANGUAGE SQL过程的主体。这应该是一个块
BEGIN ATOMIC
statement;
statement;
...
statement;
END
这类似于将过程主体的文本编写为字符串常量(请参见上面的definition),但有一些区别:此形式仅适用于LANGUAGE SQL,字符串常量形式适用于所有语言。此形式在过程定义时解析,字符串常量形式在执行时解析;因此,此形式无法支持多态参数类型和其他在过程定义时无法解析的构造。此形式跟踪过程和过程主体中使用的对象之间的依赖关系,因此DROP ... CASCADE 将正常工作,而使用字符串字面值的形式可能会留下悬空的过程。最后,此形式与SQL标准和其他SQL实现更兼容。
body
代码块内容,是函数或存储过程中需要执行的内容。
注释
有关适用于过程的函数创建的更多详细信息,请参见CREATE FUNCTION。
使用CALL 执行过程。
当没有LANGUAGE lang_name指定语言时,选择default_pl_language参数配置的语言,默认值为pluxsql。
当默认使用的是pluxsql语言时,在body中变量的定义需要使用declare关键字;如果使用的是plsql语言时,在body中变量的定义则不能使用declare关键字。
示例
CREATE PROCEDURE insert_data(a integer, b integer)
LANGUAGE SQL
AS $$
INSERT INTO tbl VALUES (a);
INSERT INTO tbl VALUES (b);
$$;
或
CREATE PROCEDURE insert_data(a integer, b integer)
LANGUAGE SQL
BEGIN ATOMIC
INSERT INTO tbl VALUES (a);
INSERT INTO tbl VALUES (b);
END;
并像这样调用:
CALL insert_data(1, 2);
兼容性
CREATE PROCEDURE 命令在 SQL 标准中定义。UXsinoDB实现可以以兼容的方式使用,但是有许多扩展。有关详细信息,请参见CREATE FUNCTION。
另请参阅
ALTER PROCEDURE、DROP PROCEDURE、CALL、CREATE FUNCTION
CREATE PUBLICATION
CREATE PUBLICATION — 定义一个新的发布
概要
CREATE PUBLICATION name
[ FOR ALL TABLES
| FOR publication_object [, ... ] ]
[ WITH ( publication_parameter [= value] [, ... ] ) ]
其中 publication_object 是以下之一:
TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [ WHERE ( expression ) ] [, ... ]
TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
描述
CREATE PUBLICATION将一个新的发布添加到当前数据库中。发布名称必须与当前数据库中任何现有发布的名称不同。
发布本质上是一组表,其数据更改旨在通过逻辑复制进行复制。
参数
-
name
新发布的名称。 -
FOR TABLE
指定要添加到发布中的表列表。如果在表名之前指定了ONLY,则只添加该表到发布中。如果没有指定ONLY,则该表及其所有后代表(如果有)都将被添加。可以在表名后面选择性地指定*,以明确表示包括后代表。但是,这不适用于分区表。分区表的分区始终被隐式地视为发布的一部分,因此它们永远不会被显式地添加到发布中。
如果指定了可选的WHERE子句,则定义了一个表的子集,该子集由满足指定条件的行组成。只有满足条件的行才会被复制到订阅者。
当指定列列表时,只有命名列会被复制。如果没有指定列列表,则该表的所有列都会通过此发布进行复制,包括以后添加的任何列。它对TRUNCATE命令没有影响。
只有持久基表和分区表可以成为发布的一部分。临时表、未登录表、外部表、物化视图和常规视图不能成为发布的一部分。
在发布也发布FOR TABLES IN SCHEMA的表时,不支持指定列列表。
当将分区表添加到发布中时,其所有现有和未来的分区都被隐式地视为发布的一部分。因此,即使是直接在分区上执行的操作也会通过其祖先所属的发布进行发布。
-
FOR ALL TABLES
将发布标记为在数据库中复制所有表的更改,包括在未来创建的表。 -
FOR TABLES IN SCHEMA
将发布标记为在指定的模式列表中复制所有表的更改,包括在未来创建的表。
在发布具有列列表的表时指定模式不受支持。
只有在模式中存在的持久基表和分区表将作为发布的一部分包括在内。模式中的临时表、未登录表、外部表、物化视图和常规视图不会成为发布的一部分。
当通过模式级发布发布分区表时,其所有现有和未来的分区都被隐式视为发布的一部分,无论它们是否来自发布模式。因此,即使是直接在分区上执行的操作也会通过其祖先所属的发布进行发布。
-
WITH ( publication_parameter[=value] [, ... ] )
此子句指定发布的可选参数。支持以下参数: -
publish(string)
此参数确定新发布向订阅者发布哪些DML操作。该值是逗号分隔的操作列表。允许的操作是insert、update、delete和truncate。默认情况下,发布所有操作,因此此选项的默认值为'insert,update, delete,truncate'。此参数仅影响DML操作。特别是,逻辑复制的初始数据同步在复制现有表数据时不考虑此参数。
-
publish_via_partition_root(boolean)
该参数确定分区表(或其分区)中的更改是否使用分区表的标识和模式而不是实际更改的各个分区的标识和模式进行发布;后者是默认设置。启用此选项允许将更改复制到非分区表或由不同分区集合组成的分区表中。此参数还影响选择用于分区的行过滤器和列列表;有关详细信息,请参见下文。
如果启用此选项,则直接在分区上执行的
TRUNCATE操作不会被复制。
注意
如果未指定FOR TABLE、FOR ALL TABLES或FOR TABLES INSCHEMA,则发布将以空表集开始。这对稍后添加表或模式很有用。
创建发布不会开始复制。它仅为未来的订阅者定义分组和过滤逻辑。
要创建发布,调用用户必须具有当前数据库的CREATE特权。(当然,超级用户可以绕过此检查。)
要将表添加到发布中,调用用户必须拥有该表的所有权。使用FOR ALL TABLES和FOR TABLES IN SCHEMA子句需要调用用户是超级用户。
发布UPDATE或DELETE操作的表必须定义REPLICA IDENTITY。否则,这些操作将在这些表上被禁止。
任何列列表必须包括REPLICA IDENTITY列,以便发布UPDATE或DELETE操作。如果发布仅发布INSERT操作,则没有列列表限制。
行过滤器表达式(即WHERE子句)必须仅包含由REPLICA IDENTITY覆盖的列,以便发布UPDATE和DELETE操作。对于发布INSERT操作,可以在WHERE表达式中使用任何列。行过滤器允许简单的表达式,不包括用户定义的函数、用户定义的运算符、用户定义的类型、用户定义的排序规则、非不变内置函数或对系统列的引用。
如果指定了FOR TABLES IN SCHEMA并且表属于所引用的模式,则表上的行过滤器变得多余。
对于已发布的分区表,如果发布参数publish_via_partition_root为true,则每个分区的行过滤器取自已发布的分区表,如果为false(默认值),则取自分区本身。同样,对于已发布的分区表,如果发布参数publish_via_partition_root为true,则每个分区的列列表取自已发布的分区表,否则取自分区本身。
对于INSERT ... ON CONFLICT命令,发布将发布由命令产生的操作。根据结果,它可能被发布为INSERT或UPDATE,也可能根本不被发布。
使用具有publish_via_partition_root设置为true的发布将表附加到分区树中的根节点,不会导致表的现有内容被复制。
COPY ... FROM命令被发布为INSERT 操作。
DDL操作不会被发布。
WHERE子句表达式使用用于复制连接的角色执行。
示例
创建一个发布,发布两个表中的所有更改:
CREATE PUBLICATION mypublication FOR TABLE users, departments;
创建一个发布,发布所有活动部门的所有更改:
CREATE PUBLICATION active_departments FOR TABLE departments WHERE (active IS TRUE);
创建一个发布,发布所有表中的所有更改:
CREATE PUBLICATION alltables FOR ALL TABLES;
创建一个发布,仅发布一个表中的 INSERT 操作:
CREATE PUBLICATION insert_only FOR TABLE mydata
WITH (publish = 'insert');
创建一个发布,发布表 users、departments 中的所有更改以及模式 production中存在的所有表的所有更改:
CREATE PUBLICATION production_publication FOR TABLE users, departments, TABLES IN SCHEMA production;
创建一个发布,发布模式 marketing 和 sales中存在的所有表的所有更改:
CREATE PUBLICATION sales_publication FOR TABLES IN SCHEMA marketing, sales;
创建一个发布,仅发布表 users 中的所有更改,但仅复制列 user_id 和 firstname:
CREATE PUBLICATION users_filtered FOR TABLE users (user_id, firstname);
兼容性
CREATE PUBLICATION 是 UXsinoDB 的扩展。
另请参阅
ALTER PUBLICATION、DROP PUBLICATION、CREATE SUBSCRIPTION、ALTER SUBSCRIPTION
CREATE ROLE
CREATE ROLE — 定义新的数据库角色
概要
CREATE ROLE name [ [ WITH ] option [ ... ] ]
其中 option 可以是:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
| ROLE VALID UNTIL 'timestamp'
| IN ROLE role_name [, ...]
| IN GROUP role_name [, ...]
| ROLE role_name [, ...]
| ADMIN role_name [, ...]
| USER role_name [, ...]
| SYSID uid
描述
CREATE ROLE添加一个新的角色到UXsinoDB数据库集群中。角色是可以拥有数据库对象和数据库权限的实体;角色可以被视为一个“用户”、一个“组”,或者两者都是,具体取决于它的使用方式。您必须拥有CREATEROLE权限或是数据库超级用户才能使用此命令。
请注意,角色是在数据库集群级别定义的,因此在集群中的所有数据库中都是有效的。
参数
-
name
新角色的名称。 -
SUPERUSER
NOSUPERUSER
这些子句确定新角色是否为“超级用户”,可以在数据库中覆盖所有访问限制。超级用户状态很危险,只有在真正需要时才应使用。您必须自己成为超级用户才能创建新的超级用户。如果未指定,则默认为NOSUPERUSER。这些子句定义角色创建数据库的能力。 -
CREATEDB
NOCREATEDB
如果指定了CREATEDB,则允许定义的角色创建新数据库。指定NOCREATEDB将拒绝角色创建数据库的能力。如果未指定,则默认为NOCREATEDB。 -
CREATEROLE
NOCREATEROLE
这些子句确定角色是否被允许创建新角色(即执行CREATE ROLE)。具有CREATEROLE特权的角色还可以更改和删除其他角色。如果未指定,则默认为NOCREATEROLE。 -
INHERIT
NOINHERIT
这些子句确定角色是否“继承”其成员角色的特权。具有INHERIT属性的角色可以自动使用已授予其直接或间接成员角色的所有数据库特权。没有INHERIT,成为另一个角色的成员仅授予使用SET ROLE到该其他角色的能力;只有在这样做之后才能使用其他角色的特权。如果未指定,则默认为INHERIT。 -
LOGIN
NOLOGIN
这些子句确定角色是否允许登录;也就是说,角色是否可以在客户端连接期间作为初始会话授权名称。具有LOGIN属性的角色可以被视为用户。没有此属性的角色对于管理数据库特权很有用,但不是通常意义上的用户。如果未指定,则默认为NOLOGIN,除非通过其替代拼写调用CREATE ROLE的CREATE USER。 -
REPLICATION
NOREPLICATION
这些子句确定角色是否为复制角色。角色必须具有此属性(或为超级用户)才能连接到复制模式(物理或逻辑复制)的服务器,并能够创建或删除复制插槽。具有REPLICATION属性的角色是非常高特权的角色,只应用于实际用于复制的角色。如果未指定,则默认为NOREPLICATION。您必须是超级用户才能创建具有REPLICATION属性的新角色。这些子句确定角色是否绕过每个行级安全(RLS)策略。NOBYPASSRLS是默认值。创建具有BYPASSRLS属性的新角色,您必须是超级用户。 -
BYPASSRLS
NOBYPASSRLS
这些子句确定角色是否绕过每个行级安全(RLS)策略。NOBYPASSRLS是默认的。您必须是超级用户才能创建具有BYPASSRLS属性的新角色。
请注意,ux_dump将在默认情况下将row_security设置为OFF,以确保转储出表的所有内容。如果运行ux_dump的用户没有适当的权限,将返回一个错误。然而,超级用户和被转储表的所有者总是绕过RLS。
-
CONNECTION LIMITconnlimit
如果角色可以登录,则指定角色可以进行的并发连接数。-1(默认值)表示没有限制。请注意,仅正常连接计入此限制。准备的事务和后台工作进程连接不计入此限制。 -
[
ENCRYPTED]PASSWORD'password'
PASSWORD NULL
设置角色的密码。(密码仅适用于具有LOGIN属性的角色,但您仍然可以为没有该属性的角色定义密码。)如果您不打算使用密码身份验证,则可以省略此选项。如果未指定密码,则密码将设置为null,并且该用户的密码身份验证将始终失败。可以将空密码明确地写为PASSWORD NULL。
若修改uxsinodb.conf文件的shared_preload_libraries参数为passwordcheck,可加载passwordcheck插件。使用passwordcheck插件可在创建用户时对设置的密码进行复杂度校验。默认密码策略为密码位数为8-32位,至少包含一位大写字母、一位小写字母、一位数字、一位特殊字符。也可修改密码参数的值来自定义密码复杂度策略。
使用current_password_policy()函数可查看当前设置的密码策略,语法格式如下:
select current_password_policy();
注意
指定空字符串也会将密码设置为null,但在UXsinoDB之前版本不是这种情况。在早期版本中,可以根据身份验证方法和确切版本使用空字符串或不使用空字符串,而libuxsql在任何情况下都会拒绝使用它。为避免歧义,应避免指定空字符串。
密码始终以加密形式存储在系统目录中。ENCRYPTED关键字没有任何效果,但是为了向后兼容而被接受。加密方法由配置参数password_encryption确定。如果呈现的密码字符串已经是MD5加密或SCRAM加密格式,则无论password_encryption如何,它都会按原样存储(因为系统无法解密指定的加密密码字符串,以便以不同格式进行加密)。这允许在转储/还原期间重新加载加密密码。
-
VALID UNTIL'timestamp'
VALID UNTIL子句设置角色密码不再有效的日期和时间。如果省略此子句,则密码将始终有效。 -
IN ROLErole_name
IN ROLE子句列出一个或多个现有角色,新角色将立即作为新成员添加到其中。(请注意,没有选项将新角色添加为管理员;请使用单独的GRANT命令执行此操作。) -
IN GROUProle_name
IN GROUP是IN ROLE的过时拼写。 -
ROLErole_name
ROLE子句列出一个或多个现有角色,这些角色将自动添加为新角色的成员。(实际上,这使新角色成为“组”。) -
ADMINrole_name
ADMIN子句类似于ROLE,但指定的角色将添加到新角色WITH ADMIN OPTION中,使它们有权将其他用户添加到此角色中。 -
USERrole_name
USER子句是ROLE子句的过时拼写。 -
SYSIDuid
SYSID子句被忽略,但为了向后兼容而被接受。
注释
使用ALTER ROLE更改角色的属性,使用DROP ROLE删除角色。CREATE ROLE指定的所有属性都可以通过后续的ALTER ROLE命令进行修改。
添加和删除用作组的角色成员的首选方法是使用GRANT和REVOKE。
VALID UNTIL子句仅为密码定义过期时间,而不是角色本身。特别地,使用非基于密码的身份验证方法登录时不强制执行过期时间。
INHERIT属性管理可授予的特权(即数据库对象和角色成员身份的访问特权)的继承。它不适用于CREATE ROLE和ALTER ROLE设置的特殊角色属性。例如,成为具有CREATEDB特权的角色的成员并不会立即授予创建数据库的能力,即使设置了INHERIT;在创建数据库之前,必须通过SET ROLE成为该角色。
INHERIT属性是向后兼容的默认值:在以前的UXsinoDB版本中,用户始终可以访问其成员的所有特权。但是,NOINHERIT提供了更接近于SQL标准指定的语义。
小心使用CREATEROLE特权。没有CREATEROLE角色的特权继承概念。这意味着即使角色没有某些特权,但允许创建其他角色,它也可以轻松地创建具有不同特权的其他角色(除了创建具有超级用户特权的角色)。例如,如果角色“user”具有CREATEROLE特权但没有CREATEDB特权,则仍然可以创建具有CREATEDB特权的新角色。因此,将具有CREATEROLE特权的角色视为几乎超级用户角色。
UXsinoDB 包括一个程序createuser,它具有与CREATE ROLE相同的功能(实际上,它调用此命令),但可以从命令shell运行。
CONNECTION LIMIT选项只是近似执行;如果在只剩下一个连接“槽”的情况下同时启动两个新会话,则可能会同时失败。此外,超级用户永远不会执行此限制。
使用此命令指定未加密密码时必须小心。密码将以明文形式传输到服务器,并且可能还会记录在客户端的命令历史记录或服务器日志中。但是,createuser命令会传输加密的密码。此外,uxsql包含一个命令\password,可用于安全地更改密码。
示例
创建一个可以登录的角色,但不要给它密码:
CREATE ROLE jonathan LOGIN;
创建一个带有密码的角色:
CREATE USER davide WITH PASSWORD 'jw8s0F4';
(`CREATE USER` 与 `CREATE ROLE` 相同,除了它意味着 `LOGIN`。)
创建一个带有密码的角色,该密码有效期至 2004 年底。在 2005年的第一秒后,密码将不再有效。
CREATE ROLE miriam WITH LOGIN PASSWORD 'jw8s0F4' VALID UNTIL '2005-01-01';
创建一个可以创建数据库和管理角色的角色:
CREATE ROLE admin WITH CREATEDB CREATEROLE;
兼容性
CREATE ROLE 语句在 SQL 标准中,但标准仅要求语法
CREATE ROLE name [ WITH ADMIN role_name ]
多个初始管理员和所有其他CREATE ROLE选项都是 UXsinoDB 扩展。
SQL标准定义了用户和角色的概念,但它将它们视为不同的概念,并将定义用户的所有命令留给每个数据库实现指定。在UXsinoDB中,我们选择将用户和角色统一为一种实体。因此,角色具有比标准中更多的可选属性。
SQL标准指定的行为最接近于给用户NOINHERIT属性,而将角色赋予INHERIT属性。
另请参阅
SET ROLE、ALTER ROLE、DROP ROLE 、GRANT、REVOKE
CREATE RULE
CREATE RULE — 定义新的重写规则
概要
CREATE [ OR REPLACE ] RULE name AS ON event
TO table_name [ WHERE condition ]
DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }
其中 event 可以是以下之一:
SELECT | INSERT | UPDATE | DELETE
描述
CREATE RULE定义适用于指定表或视图的新规则。CREATE OR REPLACE RULE将创建一个新规则,或者替换同名的现有规则,适用于同一表。
UXsinoDB规则系统允许定义在数据库表的插入、更新或删除时执行替代操作。粗略地说,规则会在执行给定表上的给定命令时执行附加命令。或者,INSTEAD规则可以将给定命令替换为另一个命令,或者根本不执行命令。规则也用于实现SQL视图。重要的是要意识到规则实际上是一个命令转换机制,或者命令宏。转换发生在命令开始执行之前。如果您实际上想要针对每个物理行独立触发的操作,您可能需要使用触发器,而不是规则。
目前,ON SELECT规则必须是无条件的INSTEAD规则,并且必须具有由单个SELECT命令组成的操作。因此,ON SELECT规则有效地将表转换为视图,其可见内容是规则的SELECT命令返回的行,而不是表中存储的任何内容(如果有)。编写CREATE VIEW命令比创建规则更好。
创建一个真实的表,并为其定义一个ON SELECT规则。您可以通过定义ON INSERT、ON UPDATE和ON DELETE规则(或任何足以满足您目的的子集)来创建可更新视图的幻象,以替换视图上的更新操作为其他表上的适当更新。如果您想支持INSERT RETURNING等操作,请确保在每个规则中放置适当的RETURNING子句。如果您尝试使用条件规则进行复杂视图更新,则必须为您希望允许的每个操作添加一个无条件的INSTEAD规则。如果规则是有条件的,或者不是INSTEAD,那么系统仍将拒绝尝试执行更新操作的尝试,因为它认为在某些情况下可能会尝试在视图的虚拟表上执行操作。如果您想在条件规则中处理所有有用的情况,请添加一个无条件的DO INSTEAD NOTHING规则,以确保系统理解它永远不会被调用以更新虚拟表。然后将条件规则设置为非INSTEAD;在应用它们的情况下,它们将添加到默认的INSTEAD NOTHING操作中。(但是,这种方法目前无法支持RETURNING查询。)
注意
简单到可以自动更新的视图(请参见CREATE VIEW)不需要用户创建的规则即可更新。虽然您仍然可以创建一个显式规则,但自动更新转换通常比显式规则更高效。
另一个值得考虑的选择是使用INSTEAD OF触发器(请参见CREATE TRIGGER)代替规则。
参数
-
name
要创建的规则的名称。这必须与同一表的任何其他规则的名称不同。对于相同的事件类型和表,多个规则按字母顺序应用。 -
event
事件是SELECT、INSERT、UPDATE或DELETE之一。请注意,包含ON CONFLICT子句的INSERT不能用于具有INSERT或UPDATE规则的表。考虑使用可更新视图。 -
table_name
适用规则的表或视图的名称(可选模式限定)。 -
condition
任何SQL条件表达式(返回boolean)。条件表达式不能引用除NEW和OLD之外的任何表,并且不能包含聚合函数。 -
INSTEAD
表示应该执行命令而不是原始命令。 -
ALSO
ALSO表示命令应该除了原始命令之外再执行。
如果没有指定 ALSO 或 INSTEAD,则 ALSO 是默认值。
command
规则操作所包含的命令。有效的命令包括SELECT、INSERT、UPDATE、DELETE或NOTIFY。
在 condition 和 command 中,特殊的表名NEW和OLD可以用于引用所引用的表中的值。NEW在ON INSERT和ON UPDATE规则中是有效的,用于引用正在插入或更新的新行。OLD在ON UPDATE和ON DELETE规则中是有效的,用于引用正在更新或删除的现有行。
注意事项
您必须是表的所有者才能为其创建或更改规则。
在视图的INSERT、UPDATE或DELETE规则中,您可以添加一个RETURNING子句,该子句会发出视图的列。如果规则由INSERTRETURNING、UPDATE RETURNING或DELETE RETURNING命令触发,则将使用此子句来计算输出。当规则由没有RETURNING的命令触发时,将忽略规则的RETURNING子句。当前的实现只允许无条件的INSTEAD规则包含RETURNING;此外,在同一事件的所有规则中最多只能有一个RETURNING子句。(这确保只有一个候选的RETURNING子句可用于计算结果。)如果没有可用规则中的RETURNING子句,则会拒绝视图上的RETURNING查询。
非常重要的是要注意避免循环规则。例如,尽管下面两个规则定义都被UXsinoDB接受,但SELECT命令会导致UXsinoDB报告错误,因为规则会递归扩展:
CREATE RULE "_RETURN" AS
ON SELECT TO t1
DO INSTEAD
SELECT * FROM t2;
CREATE RULE "_RETURN" AS
ON SELECT TO t2
DO INSTEAD
SELECT * FROM t1;
SELECT * FROM t1;
目前,如果规则操作包含NOTIFY命令,则NOTIFY命令将无条件执行,即使没有任何行应用规则也会发出NOTIFY。例如,在:
CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable;
UPDATE mytable SET name = 'foo' WHERE id = 42;
在UPDATE期间将发送一个NOTIFY事件,无论是否有任何行匹配条件id= 42。这是一个实现限制,可能在未来的版本中得到修复。
兼容性
CREATE RULE 是一个 UXsinoDB 语言扩展,整个查询重写系统也是如此。
另请参阅
CREATE SCHEMA
CREATE SCHEMA —定义一个新模式
概要
CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ]
CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ]
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ]
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification
其中 role_specification 可以是:
user_name
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
描述
CREATE SCHEMA将一个新模式添加到当前数据库中。模式名称必须与当前数据库中任何现有模式的名称不同。
模式本质上是一个命名空间:它包含命名对象(表、数据类型、函数和运算符),它们的名称可以与其他模式中现有对象的名称重复。命名对象可以通过在名称前加上模式名称作为前缀来访问,也可以通过设置包括所需模式的搜索路径来访问。指定未限定对象名称的CREATE命令将在当前模式(搜索路径前面的模式,可以使用函数current_schema确定)中创建对象。
可选地,CREATE SCHEMA可以包括子命令以在新模式中创建对象。子命令与在创建模式后发出的单独命令基本相同,但如果使用了AUTHORIZATION子句,则所有创建的对象都将归该用户所有。
参数
-
schema_name
要创建的模式的名称。如果省略此参数,则默认为当前用户的名称。 -
user_name
新模式的所有者的角色名称。如果省略,则默认为执行命令的用户。要创建由另一个角色拥有的模式,您必须是该角色的直接或间接成员,或者是超级用户。 -
schema_element
定义要在模式中创建的对象的SQL语句。目前,只有CREATE TABLE、CREATE VIEW、CREATE INDEX、CREATE SEQUENCE、CREATE TRIGGER和GRANT被接受作为CREATE SCHEMA中的子句。其他类型的对象可以在模式创建后通过单独的命令创建。 -
IF NOT EXISTS
如果具有相同名称的模式已经存在,则不执行任何操作(除了发出通知)。当使用此选项时,不能包括schema_element子命令。
注释
要创建模式,调用用户必须具有当前数据库的CREATE权限。(当然,超级用户可以绕过此检查。)
示例
创建一个模式:
CREATE SCHEMA myschema;
为用户joe创建一个模式;该模式也将被命名为joe:
CREATE SCHEMA AUTHORIZATION joe;
创建一个名为test的模式,该模式将由用户joe拥有,除非已经存在名为test的模式。(无论joe是否拥有预先存在的模式都无所谓。)
CREATE SCHEMA IF NOT EXISTS test AUTHORIZATION joe;
创建一个模式并在其中创建一个表和视图:
CREATE SCHEMA hollywood
CREATE TABLE films (title text, release date, awards text[])
CREATE VIEW winners AS
SELECT title, release FROM films WHERE awards IS NOT NULL;
请注意,各个子命令不以分号结尾。
以下是实现相同结果的等效方式:
CREATE SCHEMA hollywood;
CREATE TABLE hollywood.films (title text, release date, awards text[]);
CREATE VIEW hollywood.winners AS
SELECT title, release FROM hollywood.films WHERE awards IS NOT NULL;
兼容性
SQL标准允许在CREATE SCHEMA中使用DEFAULT CHARACTER SET子句,以及比目前被UXsinoDB 接受的更多子命令类型。
SQL标准指定CREATE SCHEMA中的子命令可以以任何顺序出现。目前的UXsinoDB实现无法处理子命令中的所有前向引用情况;有时需要重新排序子命令以避免前向引用。
根据SQL标准,模式的所有者始终拥有其中的所有对象。UXsinoDB允许模式包含由模式所有者以外的用户拥有的对象。只有当模式所有者授予这些对象的权限时,才会发生这种情况。将其模式上的CREATE权限授予其他人,或者超级用户选择在其中创建对象。
IF NOT EXISTS选项是UXsinoDB的扩展。
另请参阅
CREATE SEQUENCE
CREATE SEQUENCE —定义新的序列生成器
概要
CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] name
[ AS data_type ]
[ SHARING = { METADATA | DATA | NONE}]
[ INCREMENT [ BY ] increment ]
[ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
[ START [ WITH ] start ] [ CACHE cache | NOCACHE ] [ [ NO ] CYCLE | NOCYCLE ]
[ ORDER | NOORDER ]
[ KEEP | NOKEEP ][ SESSION | GLOBAL ]
[ OWNED BY { table_name.column_name | NONE } ]
描述
CREATE SEQUENCE创建一个新的序列号生成器。这涉及创建和初始化一个名为name的新特殊单行表。生成器将由发出命令的用户拥有。
如果给出模式名称,则序列将在指定模式中创建。否则,它将在当前模式中创建。临时序列存在于一个特殊的模式中,因此在创建临时序列时不能给出模式名称。序列名称必须与同一模式中的任何其他关系(表、序列、索引、视图、材料化视图或外部表)的名称不同。
创建序列后,您可以使用函数nextval、currval和setval来操作序列。
虽然您不能直接更新序列,但可以使用类似以下查询的查询:
SELECT * FROM name;
来检查序列的参数和当前状态。特别是,序列的last_value字段显示任何会话分配的最后一个值。(当然,如果其他会话正在积极地进行nextval调用,则该值可能已过时。)
序列对象(也叫序列生成器)就是用CREATE SEQUENCE创建的特殊的单行表。一个序列对象通常用于为行或者表生成唯一的标识符。
通过序列函数nextval获取序列的下一个数值,函数nextval递增序列对象到它的下一个数值并且返回该值。这个动作是自动完成的。
-- 语法1
seq.nextval
--语法2
nextval('seq')
参数
-
TEMPORARY或TEMP
如果指定,则序列对象仅为此会话创建,并在会话退出时自动删除。存在具有相同名称的永久序列时,在临时序列存在时不可见(在此会话中),除非使用模式限定名称引用它们。 -
UNLOGGED
如果指定,则将序列创建为未记录序列。对未记录序列的更改不会写入预写式日志。它们不是崩溃安全的:未记录序列在崩溃或非正常关闭后会自动重置为其初始状态。未记录序列也不会被复制到备用服务器。
与未记录表不同,未记录序列不提供显着的性能优势。此选项主要用于通过标识列或序列列与未记录表相关联的序列。在这些情况下,通常没有意义将序列WAL记录并复制,但不复制其关联表。
-
IF NOT EXISTS
如果具有相同名称的关系已经存在,则不会引发错误。在这种情况下发出通知。请注意,不能保证现有关系与将创建的序列有任何相似之处 -它甚至可能不是序列。 -
name
要创建的序列的名称(可选模式限定)。 -
data_type
可选的子句AS data_type指定序列的数据类型。有效类型为smallint、integer和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。 -
CACHEcache
NOCACHE
子句CACHE cache允许预分配序列号并将其存储在内存中以加快访问速度。最小值为1(一次只能生成一个值,即无缓存)。如果未指定,则将保留旧缓存值。
NOCACHE相当于缓存值为1,不会预先在内存里面存放sequence,可以避免数据库不正常关闭造成的sequence丢失。
CYCLE
NO CYCLE
NOCYCLE
CYCLE选项允许在升序或降序序列达到maxvalue或minvalue时,序列回绕。当升序序列达到最大值时,它会生成最小值minvalue。当降序序列达到最小值时,它会生成最大值maxvalue。
如果指定了NO CYCLE,则序列达到其最大值后调用nextval将返回错误。如果既未指定CYCLE也未指定NO CYCLE,则NO CYCLE是默认值。
使用NOCYCLE来指定序列在达到最大或最小值后不能再生成更多的值。这是默认行为。
-
OWNED BYtable_name.column_name
OWNED BY NONE
OWNED BY选项会使序列与特定表列相关联,因此如果删除该列(或整个表),序列也将自动删除。指定的表必须与序列具有相同的所有者并且位于相同的模式中。OWNEDBY NONE,即默认值,指定没有这种关联。 -
SHARING= {METADATA|DATA|NONE}
此子句适用于在应用程序根目录中创建序列时,此属性创建完成就不能再被更改。这种类型的序列被称为应用程序公共对象,可以与属于引用程序根的应用程序PDB共享,其中:
METADATA数据链接共享序列,共享序列的metadata,但是数据对于每个容器是独立唯一的,这种类型的序列被称为METADATA-LINKED应用程序公共对象。
DATA数据链路共享序列,这个数据对于所有程序容器是一样的。它的数据只会被存在程序根目录中。这种类型的序列被称为DATA-LINKED应用程序公共对象。
NONE序列不会被共享。
如果省略此子句,使用DEFAULT_SHARING初始化参数来确定共享属性,对于支持共享的,默认为METADATA,对于不支持共享属性的,默认为NONE。此语法是oracle用来管理多租户环境下cdb以及pdb数据访问策略的,uxdb默认不支持多租户场景。
ORDER
NOORDER
使用ORDER来保证序列号按照请求的顺序生成。如果你将序列号用作时间戳,这个选项非常有用。对于用于生成主键的序列,保证顺序通常不重要。
使用NOORDER来表示不保证序列号按照请求的顺序生成。这是默认行为。
KEEP
NOKEEP
Oracle用来更改序列的保留属性,当值为KEEP时,他的值在回滚时或撤销时不会被重置。通常用于需要保留连续序列值的特定业务需求。
当值为NOKEEP时,他的值会在回滚或撤销时重置。
SESSION
GLOBAL
SESSION:当序列对象的缓存级别设置为SESSION时,每个会话(session)都会有自己的序列缓存。每个会话在访问序列是都会使用自己的缓存值,不会影响其他会话的缓存。意味着不同会话之间的序列值是独立的,互不干扰的。Uxdb默认是这种模式。
GLOBAL:当序列对象的缓存级别设置为GLOBAL时,所有会话共享同一个序列缓存。多个会话在访问序列时会共享同一个序列缓存值。意味着不同会话之间的序列值是共享的,可能会出现序列值的竞争和冲突。
注意事项
使用DROP SEQUENCE删除序列。
序列基于bigint算术,因此范围不能超过八字节整数的范围(-9223372036854775808到9223372036854775807)。
由于nextval和setval调用永远不会回滚,因此如果需要序列号的“无间隙”分配,则无法使用序列对象。可以通过使用包含计数器的表的排他锁来构建无间隙分配;但是,这种解决方案比序列对象要昂贵得多,特别是如果许多事务需要同时使用序列号。
如果将用于多个会话同时使用的序列对象使用大于1的cache设置,则可能会获得意外的结果。每个会话将在访问序列对象期间分配和缓存连续的序列值,并相应地增加序列对象的last_value。然后,在该会话中的下一个cache-1次使用nextval仅返回预分配的值,而不会触及序列对象。因此,在会话结束时分配但未使用的任何数字都将丢失,导致序列中的“空洞”。
此外,虽然保证多个会话将分配不同的序列值,但是无法保证这些值是连续的,因为在一个会话中分配的值可能会在另一个会话中丢失。
不同的序列值,考虑到所有会话时,这些值可能会按顺序生成。例如,使用缓存设置为10,会话A可能会保留值1..10并返回nextval=1,然后会话B可能会保留值11..20并返回nextval=11,而会话A尚未生成nextval=2。因此,使用缓存设置为1,可以安全地假定nextval值是按顺序生成的;使用缓存设置大于1,您只应假定nextval值都是不同的,而不是纯粹按顺序生成的。此外,last_value将反映任何会话保留的最新值,无论它是否已由nextval返回。另一个考虑因素是,在这样的序列上执行的setval在其他会话使用它们缓存的任何预分配值之前不会被注意到。
示例
创建一个名为serial的升序序列,从101开始:
CREATE SEQUENCE serial START 101;
从这个序列中选取下一个数字:
SELECT nextval('serial');
nextval
----
101
再从这个序列中选取下一个数字,可使用如下方式。
SELECT serial.nextval;
nextval
----
102
在INSERT命令中使用此序列:
INSERT INTO distributors VALUES(nextval('serial'), 'nothing');
在COPY FROM之后更新序列值:
BEGIN;
COPY
distributors FROM 'input_file';
SELECT setval('serial', max(id)) FROMdistributors;
END;
使用ORDER/NOORDER、KEEP/NOKEEP、SHARING、SESSION/GLOBAL关键字创建序列,如下所示。
uxdb=# Create sequence test1 order keep cache 20 session sharing = data;
CREATE SEQUENCE
uxdb=# Create sequence test2 noorder nokeep cache 20 global sharing = metadata;
CREATE SEQUENCE
uxdb=# Create sequence test3 noorder nokeep cache 20 global sharing = none;
CREATE SEQUENCE
兼容性
CREATE SEQUENCE符合SQL标准,以下是例外情况:
-
使用
nextval()函数获取下一个值,而不是标准的NEXT VALUE FOR表达式。 -
OWNED BY子句是UXsinoDB的扩展。 -
新增关键字[
ORDER|NOORDER] [KEEP|NOKEEP] [SHARING= {NONE|METADATA|DATA} ] [SESSION|GLOBAL]由于使用场景限制在oracle的rac集群下,故目前只有语法层面的兼容。
另请参阅
ALTER SEQUENCE,DROP SEQUENCE 。
CREATE SERVER
CREATE SERVER —定义一个新的外部服务器
概述
CREATE SERVER [ IF NOT EXISTS ] server_name [ TYPE 'server_type' ] [ VERSION 'server_version' ]
FOREIGN DATA WRAPPER fdw_name
[ OPTIONS ( option 'value' [, ... ] ) ]
描述
CREATE SERVER定义一个新的外部服务器。定义服务器的用户成为其所有者。
外部服务器通常封装了外部数据资源访问所使用的外部数据包装器的连接信息。可以通过用户映射指定其他用户特定的连接信息。
服务器名称必须在数据库中唯一。
创建服务器需要对所使用的外部数据包装器具有USAGE权限。
参数
-
IF NOT EXISTS
如果已经存在同名服务器,则不会抛出错误。在这种情况下会发出通知。请注意,不能保证现有服务器与将要创建的服务器相似。 -
server_name
要创建的外部服务器的名称。 -
server_type
可选的服务器类型,对外部数据包装器可能有用。 -
server_version
可选的服务器版本,对外部数据包装器可能有用。 -
fdw_name
管理服务器的外部数据包装器的名称。 -
OPTIONS ( option'value' [, ... ] )
此子句指定服务器的选项。选项可以是键值对的形式,例如host'localhost'。
注意事项
使用dblink模块时,可以将外部服务器的名称用作dblink_connect函数的参数,以指示连接参数。在此方式中使用它需要对外部服务器具有USAGE特权。
示例
创建一个使用外部数据包装器uxdb_fdw的服务器myserver:
CREATE SERVER myserver FOREIGNDATA WRAPPER uxdb_fdw OPTIONS (host 'foo', dbname 'foodb', port'5432');
另请参见
ALTER SERVER、DROP SERVER、CREATE FOREIGN DATA WRAPPER、CREATE FOREIGN TABLE和CREATE USER MAPPING。
CREATE STATISTICS
CREATE STATISTICS — 定义扩展统计信息
概要
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
ON ( expression )
FROM table_name
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
[ ( statistics_kind [, ... ] ) ]
ON { column_name | ( expression ) }, { column_name | ( expression ) } [, ...]
FROM table_name
描述
CREATE STATISTICS将创建一个新的扩展统计信息对象,跟踪指定表、外部表或材料化视图的数据。统计对象将在当前数据库中创建,并由发出命令的用户拥有。
CREATE STATISTICS命令有两种基本形式。第一种形式允许收集单个表达式的单变量统计信息,提供类似于表达式索引的好处,而不需要索引维护的开销。此形式不允许指定统计信息类型,因为各种统计信息类型仅指多元统计信息。命令的第二种形式允许收集多元统计信息,涉及多个列或表达式,可选择指定要包括的统计信息类型。此形式还将自动导致在列表中包括的任何表达式上收集单变量统计信息。
如果给出模式名称(例如CREATE STATISTICS myschema.mystat...),则统计对象将在指定的模式中创建。否则,它将在当前模式中创建。统计对象的名称必须与同一模式中任何其他统计对象的名称不同。
参数
-
IF NOT EXISTS
如果具有相同名称的统计对象已经存在,则不要抛出错误。在这种情况下会发出通知。请注意,这里仅考虑统计对象的名称,而不考虑其定义的详细信息。 -
statistics_name
要创建的统计对象的名称(可选模式限定符)。 -
statistics_kind
要在此统计对象中计算的多元统计类型。当前支持的类型包括启用 n-distinct 统计的 ndistinct、启用函数依赖统计的dependencies 和启用最常见值列表的mcv。如果省略此子句,则统计对象包括所有支持的统计类型。如果统计定义包括任何复杂表达式而不仅仅是简单的列引用,则会自动构建单变量表达式统计。 -
column_name
要由计算出的统计数据覆盖的表列的名称。仅在构建多元统计时允许这样做。必须指定至少两个列名或表达式,它们的顺序不重要。 -
expression
要由计算出的统计数据覆盖的表达式。这可用于在单个表达式上构建单变量统计,或作为构建多元统计的多个列名或表达式列表的一部分。在后一种情况下,每个列表中的表达式都会自动构建单变量统计。 -
table_name
包含计算统计数据的列的表的名称(可选模式限定符);有关继承和分区处理的说明,请参见ANALYZE。
注意事项
要创建读取表的统计对象,您必须是该表的所有者。但是,一旦创建,统计对象的所有权与底层表无关。
表达式统计是按表达式计算的,类似于在表达式上创建索引,但它们避免了索引维护的开销。对于统计对象定义中的每个表达式,都会自动构建表达式统计。
示例
创建具有两个功能依赖列的表 t1,即,第一列的值足以确定另一列的值。然后在这些列上构建函数依赖统计:
CREATE TABLE t1 (
a int,
b int
);
INSERT INTO t1 SELECT i/100, i/500
FROM generate_series(1,1000000) s(i);
ANALYZE t1;
-- the number of matching rows will be drastically underestimated:
EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0);
CREATE STATISTICS s1 (dependencies) ON a, b FROM t1;
ANALYZE t1;
-- now the row count estimate is more accurate:
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列表为规划器提供了更详细的信息,包括表中常见的特定值以及不出现在表中的值组合的选择性的上限,从而使它能够在两种情况下生成更好的估计。
创建表t3,其中只有一个时间戳列,并使用该列上的表达式运行查询。如果没有扩展统计信息,规划器将不会了解表达式的数据分布情况,并使用默认估计值。规划器还没有意识到将日期截断到月份的值完全由截断到日期的值确定。然后,在这两个表达式上构建表达式和ndistinct统计信息:
CREATE TABLE t3 (
a timestamp
);
INSERT INTO t3 SELECT i FROM generate_series('2020-01-01'::timestamp,
'2020-12-31'::timestamp,
'1 minute'::interval) s(i);
ANALYZE t3;
-- 匹配行数将被严重低估:
EXPLAIN ANALYZE SELECT * FROM t3
WHERE date_trunc('month', a) = '2020-01-01'::timestamp;
EXPLAIN ANALYZE SELECT * FROM t3
WHERE date_trunc('day', a) BETWEEN '2020-01-01'::timestamp
AND '2020-06-30'::timestamp;
EXPLAIN ANALYZE SELECT date_trunc('month', a), date_trunc('day', a)
FROM t3 GROUP BY 1, 2;
-- 在这对表达式上构建ndistinct统计信息(自动构建每个表达式的统计信息)
CREATE STATISTICS s3 (ndistinct) ON date_trunc('month', a), date_trunc('day', a) FROM t3;
ANALYZE t3;
-- 现在行数估计更准确:
EXPLAIN ANALYZE SELECT * FROM t3
WHERE date_trunc('month', a) = '2020-01-01'::timestamp;
EXPLAIN ANALYZE SELECT * FROM t3
WHERE date_trunc('day', a) BETWEEN '2020-01-01'::timestamp
AND '2020-06-30'::timestamp;
EXPLAIN ANALYZE SELECT date_trunc('month', a), date_trunc('day', a)
FROM t3 GROUP BY 1, 2;
如果没有表达式和ndistinct统计信息,规划器将不会了解表达式的不同值的数量,并且必须依赖默认估计值。等式和范围条件被假定具有0.5%的选择性,并且表达式中的不同值数量被假定与列相同(即唯一)。这导致前两个查询的行数严重低估。此外,规划器没有关于表达式之间关系的信息,因此它假定两个WHERE和GROUP BY条件是独立的,并将它们的选择性相乘,得到一个严重高估的组数。这进一步加剧了表达式的准确统计信息的缺乏,迫使规划器为从列派生的表达式使用默认的ndistinct估计值。有了这样的统计信息,规划器识别出条件之间的相关性,并得出更准确的估计值。
兼容性
SQL标准中没有CREATE STATISTICS命令。
另请参阅
ALTER STATISTICS,DROP STATISTICS
CREATE SUBSCRIPTION
CREATE SUBSCRIPTION — 定义一个新的订阅
概要
CREATE SUBSCRIPTION subscription_name
CONNECTION 'conninfo'
PUBLICATION publication_name [, ...]
[ WITH ( subscription_parameter [= value] [, ... ] ) ]
描述
CREATE SUBSCRIPTION添加一个新的逻辑复制订阅。订阅名称必须与当前数据库中任何现有订阅的名称不同。
订阅表示与发布者的复制连接。因此,除了在本地目录中添加定义外,此命令通常还在发布者上创建一个复制插槽。
在运行此命令的事务提交时,将启动逻辑复制工作程序以复制新订阅的数据,除非订阅最初被禁用。
参数
-
subscription_name
新订阅的名称。 -
CONNECTION 'conninfo'
定义如何连接到发布者数据库的libuxsql连接字符串。 -
PUBLICATION publication_name[, ...]
要订阅的发布者上的出版物名称。 -
WITH( subscription_parameter[=value] [,... ])
此子句指定订阅的可选参数。
以下参数控制订阅创建期间发生的情况:
-
connect(boolean)
指定CREATE SUBSCRIPTION命令是否应连接到发布者。默认值为true。将其设置为false将强制执行值create_slot,enabled和copy_data为false。(您不能将设置connect为false与设置create_slot,enabled,或copy_data为true。)当此选项为
false时,不会建立连接,因此不会订阅任何表,因此在启用订阅后不会复制任何内容。您需要随后运行ALTER SUBSCRIPTION ... REFRESH PUBLICATION才能订阅表。 -
create_slot(boolean)
指定命令是否应在上创建复制插槽出版商。默认值为true。如果设置为false,则您负责以其他方式创建发布者的插槽。 -
enabled(boolean)
指定订阅是否应主动复制 或者它只是设置但尚未启动。默认值为true。 -
slot_name(string)
要使用的出版者复制插槽的名称。默认值为使用插槽名称的订阅名称。将
slot_nam设置为NONE意味着没有复制插槽与订阅相关联。在您将要稍后手动创建复制插槽时,请使用此选项。这样的订阅还必须同时设置enabled和create_slot为false。
以下参数控制订阅的复制创建后的行为:
-
binary(boolean)
指定订阅是否将请求发布者以二进制格式发送数据(而不是文本)。默认值为false。即使启用此选项,也只有具有二进制发送和接收函数的数据类型将以二进制形式传输。在进行跨版本复制时,可能会出现发布者具有某些数据类型的二进制发送函数,但是订阅者缺少该类型的二进制接收函数。在这种情况下,数据传输将失败,无法使用
binary选项。 -
copy_data(boolean)
指定是否在订阅开始时复制正在订阅的出版物中的现有数据。默认值为true。如果发布包含
WHERE子句,它将影响复制的数据。有关详细信息,请参阅CREATE SUBSCRIPTION中的“注释”。 -
streaming(boolean)
指定是否启用此订阅的正在进行的事务流式传输。默认情况下,所有事务都在发布者上完全解码,然后作为整体发送到订阅者。 -
synchronous_commit(enum)
此参数的值覆盖了此订阅的应用工作进程中的synchronous_commit设置。默认值为off。对于逻辑复制,使用
off是安全的:如果订阅者由于缺少同步而丢失事务,则数据将再次从发布者发送。在进行同步逻辑复制时,可能需要不同的设置。逻辑复制工作进程向发布者报告写入和刷新的位置,当使用同步复制时,发布者将等待实际的刷新。这意味着在订阅用于同步复制时,将
synchronous_commit设置为off可能会增加发布者上COMMIT的延迟。在这种情况下,将synchronous_commit设置为local或更高可能是有利的。 -
two_phase(boolean)
指定是否为此订阅启用两阶段提交。默认值为false。启用两阶段提交时,准备好的事务将在
PREPARE TRANSACTION时发送到订阅者,并在订阅者上作为两阶段事务处理。否则,只有在提交时才将准备好的事务发送到订阅者,然后由订阅者立即处理。实现两阶段提交要求复制已成功完成初始表同步阶段。因此,即使为订阅启用了
two_phase,内部两阶段状态仍然暂时保持为“pending”,直到初始化阶段完成。请参阅ux_subscription的subtwophasestate列,以了解实际的两阶段状态。 -
disable_on_error(boolean)
指定是否在订阅工作进程在从发布者复制数据时检测到任何错误时自动禁用订阅。默认值为false。
注释
创建复制槽(默认行为)时,CREATE SUBSCRIPTION不能在事务块内执行。
创建连接到同一数据库集群的订阅(例如,在同一集群中的数据库之间进行复制或在同一集群中进行复制)时,必须使用不同的订阅名称和不同的复制槽名称。
如果复制槽是作为同一命令的一部分创建的,则在同一数据库中创建订阅(即使用CREATE SUBSCRIPTION命令)将失败。否则,CREATE SUBSCRIPTION调用将挂起。为使其正常工作,请单独创建复制槽(使用插件名称uxoutput的函数ux_create_logical_replication_slot),并使用参数create_slot=false创建订阅。这是一种实现限制,可能会在将来的版本中取消。
如果发布中的任何表具有WHERE子句,则对于expression计算结果为false或null的行将不会被发布。如果订阅具有多个发布,其中同一表已使用不同的WHERE子句进行了发布,则如果满足任何一个(涉及该发布操作的表达式)表达式,则将发布一行。在不同的WHERE子句的情况下,如果其中一个发布没有WHERE子句(涉及该发布操作的表达式)或发布被声明为FOR ALL TABLES或FOR TABLES IN SCHEMA,则无论其他表达式的定义如何,都将始终发布行。如果订阅者是UXsinoDB2122之前的版本,则在初始数据同步阶段将忽略任何行过滤。对于这种情况,用户可能需要考虑删除任何最初复制的数据,因为这些数据与后续过滤不兼容。由于初始数据同步在复制现有表数据时不考虑发布publish参数,因此可能会复制一些不使用DML进行复制的行。
不支持具有多个发布的订阅,其中同一表已使用不同的列列表进行了发布。
我们允许指定不存在的发布,以便用户稍后添加。这意味着ux_subscription可以有不存在的发布。
示例
创建一个订阅到远程服务器,该服务器复制mypublication和insert_only中的表,并在提交时立即开始复制:
CREATE SUBSCRIPTION mysub
CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
PUBLICATION mypublication, insert_only;
创建一个订阅到远程服务器,该服务器复制insert_only中的表,并且在稍后启用时才开始复制。
CREATE SUBSCRIPTION mysub
CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
PUBLICATION insert_only
WITH (enabled = false);
兼容性
CREATE SUBSCRIPTION是UXsinoDB的扩展功能。
另请参阅
ALTER SUBSCRIPTION,DROP SUBSCRIPTION,CREATE PUBLICATION,ALTER PUBLICATION
CREATE SYNONYM
CREATE SYNONYM — 创建一个同义词
概要
CREATE SYNONYM synname FOR orgname
CREATE SYNONYM synname FOR funcname(arg, arg, ...)
描述
同义词(synonym)是表、索引、序列、视图、函数的一个别名,一个对象支持创建多个同义词。通过为模式对象创建同义词,可以隐藏对象的实际名称和所有者信息,由此为对象提提供一定的安全性保证。
参数
-
synname
用户自定义的同义词名称。 -
orgname
同义词属主的名称。 -
funcname(arg,arg,...)
函数对象名称及函数参数。 -
synname(arg,arg,...)
同义词函数名称及参数。
注释
-
不能更新同义词名称。
-
不能直接找出同义词与属主的映射关系。
-
删除属主时,会报有同义词依赖的错误。
示例
表t1创建同义词,如下所示。
create synonym synt1 for t1;
表test创建多个同义词,如下所示。
//创建表test:
create table test(id int, name varchar(20));
//创建表test同义词test_sy1:
create synonym test_sy1 for test;
//创建表test同义词test_sy2:
create synonym test_sy2 for test;
索引idx1创建同义词,如下所示。
create synonym syni1 for idx1;
序列seq1创建同义词,如下所示。
create synonym syn1 for seq1;
视图vw1创建同义词,如下所示。
create synonym synv1 for vw1;
函数add创建同义词,如下所示。
create synonym s1 for add(integer, integer, integer);
CREATE TABLE
CREATE TABLE —定义新表
概要
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
{ column_name data_type [ COMPRESSION compression_method ] [ ENCRYPTED [ { SALT | NO SALT } [ MAC | NO MAC ] ] ] [ 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 ] [, ... ] ) ]
Oracle模式
[ 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 } ]
[ ENCRYPTED USING 'encypt_method' ]
[ TABLESPACE tablespace_name ] | [ STORAGE ( ON tablespace_name, CLUSTERBTR ) ]
[ COMMENT [ = ] comment_info ] [,...]
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
OF type_name [ (
{ column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]
| table_constraint }
[, ... ]
) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
Oracle模式
[ 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 ] | [ STORAGE ( ON tablespace_name, CLUSTERBTR ) ]
[ COMMENT [ = ] comment_info ] [,...]
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
PARTITION 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 ] [, ... ] ) ]
Oracle模式
[ 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 ] | [ STORAGE ( ON tablespace_name, CLUSTERBTR ) ]
[ COMMENT [ = ] comment_info ] [,...]
Mysql模式兼容 CREATE { TEMPORARY | TEMP } TABLE[ IF NOT EXISTS ] table_name LIKE source_table
其中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 [ NULLS [ NOT ] DISTINCT ] index_parameters |
PRIMARY KEY index_parameters |
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
[ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ COMMENT comment_info ] [,...]
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
其中table_constraint是:
[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters |
[ NOT CLUSTER ] 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 DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
其中like_option是:
{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL | ENCRYPTED }
其中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 )|
VALUES LESS THAN ( { partition_bound_expr | MAXVALUE } [, ... ] )|
VALUES ( partition_bound_expr [, ... ] | DEFAULT )
其中subpartition_bound_spec是:
VALUES LESS THAN ( { partition_bound_expr | MAXVALUE } [, ... ] )|
VALUES ( partition_bound_expr [, ... ] | DEFAULT )
其中partition_extented_spec是:
[INTERVAL ( expression )] [ STORE IN ( tablespace_name [, ... ] ) ]
[ SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ] ]
[
( PARTITION [partition] [ partition_bound_spec ] [ TABLESPACE tablespace_name ]
[ ( SUBPARTITION [subpartition] [ subpartition_bound_spec ]
[ TABLESPACE tablespace_name ] [, ... ])
] [, ... ]
) | PARTITIONS numeric_literal [STORE IN ( tablespace_name [, ... ] ) ]
]
index_parameters在UNIQUE、PRIMARY KEY和EXCLUDE约束中是:
[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]
exclude_element在EXCLUDE约束中是:
{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
referential_action在FOREIGN KEY/REFERENCES约束中是:
{NO ACTION|RESTRICT|CASCADE|SET NULL[(column_name[,...])]|SET DEFAULT[(column_name[,...])]}
以下关键字或语法规则只支持在安全模式下指定:
ENCRYPTED
SALT
NO SALT
MAC
NO MAC
[ ENCRYPTED USING 'encypt_method' ]
描述
CREATE TABLE将在当前数据库中创建一个新的、最初为空的表。该表将由发出命令的用户拥有。
如果给出模式名称(例如,CREATE TABLE myschema.mytable...),则表将在指定的模式中创建。否则,它将在当前模式中创建。临时表存在于一个特殊的模式中,因此在创建临时表时不能给出模式名称。表的名称必须与同一模式中的任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。
CREATE TABLE还自动创建一个数据类型,表示与表中一行对应的组合类型。因此,表不能与同一模式中的任何现有数据类型具有相同的名称。
可选的约束子句指定新插入或更新的行必须满足的约束(测试),以使插入或更新操作成功。约束是帮助以各种方式定义表中有效值集的SQL对象。
有两种定义约束的方法:表约束和列约束。列约束定义为列定义的一部分。表约束定义不与特定列绑定,它可以包含多个列。每个列约束也可以写成表约束;当约束只影响一个列时,列约束只是一种符号方便。
要能够创建表,必须对所有列类型或OF子句中的类型具有USAGE权限。
参数
TEMPORARY或TEMP
如果指定,表将作为临时表创建。临时表在会话结束时自动删除,或者在当前事务结束时选择删除。以下是中文翻译:(见下面的ON COMMIT)。默认的搜索路径首先包括临时模式,因此在临时表存在时,不会选择已存在的同名永久表作为新计划,除非它们被引用为模式限定的名称。在临时表上创建的任何索引也自动成为临时索引。
自动清理守护程序无法访问临时表,因此无法对其进行清理或分析。因此,应通过会话SQL命令执行适当的清理和分析操作。例如,如果将在复杂查询中使用临时表,则最好在填充临时表后对其运行ANALYZE。
可选地,在TEMPORARY或TEMP之前可以写入GLOBAL或LOCAL。请参见下面的CREATE TABLE中的“兼容性”。
UNLOGGED
如果指定,则创建的表将作为未记录的表创建。写入未记录的表的数据不会写入预写日志,这使它们比普通表快得多。但是,它们不是崩溃安全的:在崩溃或不干净的关闭后,未记录的表会自动被截断。未记录表的内容也不会被复制到备用服务器。在未记录的表上创建的任何索引也自动成为未记录索引。
如果指定了这个选项,则与未记录表一起创建的任何序列(用于标识或序列列)也将被创建为未记录的。
-
IF NOT EXISTS
如果同名关系已经存在,则不会抛出错误。在这种情况下,会发出通知。请注意,不能保证现有关系与将要创建的关系相似。 -
table_name
要创建的表的名称(可选模式限定)。 -
OF type_name
创建一个类型化表,它从指定的组合类型(名称可选模式限定)中获取其结构。类型化表与其类型绑定;例如,如果删除类型(使用DROP TYPE ... CASCADE),则表也将被删除。当创建类型化表时,列的数据类型由基础组合类型确定,不由CREATE TABLE命令指定。但是,CREATE TABLE命令可以向表添加默认值和约束,并可以指定存储参数。 -
column_name
要在新表中创建的列的名称。 -
ON UPDATE NOW()
执行UPDATE语句时,当TIMESTAMP和TIMESTAMPTZ类型的列包含ON UPDATE NOW()属性时,该列会自动更新时间值,其中NOW()函数可以替换成与它同义的函数。
表 NOW()同义函数
| 时间函数 |
|---|
| CURRENT_TIMESTAMP |
| CURRENT_TIMESTAMP() |
| CURRENT_TIMESTAMP(0-6) |
| NOW(0-6) |
| LOCALTIME |
| LOCALTIME() |
| LOCALTIME(0-6) |
| LOCALTIMESTAMP |
| LOCALTIMESTAMP() |
| LOCALTIMESTAMP(0-6) |
在ON UPDATE NOW()自动更新为当前时间的语法中,将上面列出的函数均看做NOW()的同义函数,返回当前语句执行的时间,如果修饰的列类型为TIMESTAMP,返回不带时区的时间戳,如果修饰的列类型为TIMESTAMPTZ,返回带时区的时间戳。
表 支持的sql语句
| sql语句 |
|---|
CREATE TABLE t1 ( id int,ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); |
CREATE TABLE t1 ( id int,ts TIMESTAMP(p) ON UPDATE CURRENT_TIMESTAMP(p) ); |
CREATE TABLE t1 ( id int,ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0)); |
CREATE TABLE t1 ( id int,ts TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP); |
alter table t1 add ts1 TIMESTAMP on update CURRENT_TIMESTAMP; |
alter table t1 add ts1 TIMESTAMP(p) on update CURRENT_TIMESTAMP(p); |
alter table t1 add ts1 TIMESTAMP on update CURRENT_TIMESTAMP(0); |
alter table t1 alter ts1 set on update current_timestamp;ts1与current_timestamp的精度设置保持一致 |
alter table t1 alter ts1 drop on update current_timestamp;ts1与current_timestamp的精度设置保持一致 |
alter table t1 alter ts2 type TIMESTAMP on update current_timestamp;ts2的目标类型精度与current_timestamp的精度设置保持一致 |
-
表中p表示精度,取值范围为0-6。
-
表中的TIMESTAMP可以改成TIMESTAMPTZ,current_timestamp均可替换成同义函数。
-
uxdb对current_timestamp函数的精度不做校验,自动更新时,与修饰的时间列精度保持一致。
-
在未指定精度创建的表的前提下,mysql和uxdb插入或更新为当前时间的精度有差异:mysql的时间列显示的时间精度均为0,uxdb显示的时间精度在0-6之间,但是不固定。
CONSTRAINT index_name NOT CLUSTER PRIMARY KEY(column_name )
column_name data_type NOT CLUSTER PRIMARY KEY
以NOT CLUSTER PRIMARY KEY约束条件,实现建立非聚簇索引的表。创建表时候,在列名全部声明完之后使用。
CONSTRAINT约束语法建立NOT CLUSTER PRIMARY KEY约束column_name即作为主键,index_name表示索引名。或者在需要作为主键的列名后添加语法NOT CLUSTER PRIMARY KEY。
对于非聚簇索引的表,可使用CLUSTER TABLE_NAME [USING index_name]将非聚簇索引的表转换成聚簇索引的表。index_name是表的主键索引名。可通过\d table_name查看。
-
data_type
列的数据类型。这可以包括数组说明符。 -
COLLATE collation
COLLATE子句将排序规则分配给列。该列必须是可排序数据类型。如果未指定,则使用列数据类型的默认排序规则。COMPRESSION子句设置列的压缩方法。仅支持可变宽度数据类型,并且仅在列的存储模式为main或extended时使用。(有关列存储模式的信息,请参见ALTER TABLE。)为分区表设置此属性没有直接影响,因为这样的表没有自己的存储,但是新创建的分区将继承配置的值。支持的压缩方法是uxlz和lz4。(仅当构建UXsinoDB时使用了--with-lz4选项时,才可用lz4。)此外,compression_method可以是default,以明确指定默认行为,即在数据插入时查询default_toast_compression设置以确定要使用的方法。
可选的INHERITS子句指定新表自动继承所有列的表列表。父表可以是普通表或外部表。
使用INHERITS创建新子表与其父表之间创建了持久关系。父项的模式修改通常也会传播到子项,并且默认情况下,子表的数据包括在父项的扫描中。
如果相同的列名存在于多个父表中,则除非每个父表中列的数据类型匹配,否则将报告错误。如果没有冲突,则重复的列将合并为新表中的单个列。如果新表的列名列表包含继承的列名,则数据类型也必须匹配继承的列,并且列定义将合并为一个。如果新表为该列明确指定了默认值,则此默认值将覆盖列的继承声明中的任何默认值。否则,指定列的默认值的任何父项都必须全部指定相同的默认值,否则将报告错误。
CHECK约束与列基本上以相同的方式合并:如果多个父表或新表定义包含具有相同名称的CHECK约束,则这些约束必须具有相同的检查表达式,否则将报告错误。具有相同名称和表达式的约束将合并为一个副本。在父项中标记为NO INHERIT的约束将不予考虑。请注意,新表中的未命名CHECK约束永远不会合并,因为将始终为其选择唯一名称。列存储设置也从父表复制。如果父表中的列是标识列,则不会继承该属性。如果需要,可以声明子表中的列为标识列。
PARTITION BY { RANGE | LIST | HASH } ( { column_name| (expression) } [opclass] [, ...] )
可选的PARTITION BY子句指定了表的分区策略。因此创建的表称为分区表。括号中的列或表达式列表形成了表的分区键。在使用范围或哈希分区时,分区键可以包括多个列或表达式(最多32个,但在构建UXsinoDB 时可以更改此限制),但对于列表分区,分区键必须由单个列或表达式组成。分区键也可以是由GENERATED ALWAYS AS创建的生成列。
范围和列表分区需要btree操作符类,而哈希分区需要哈希操作符类。如果没有显式指定操作符类,则将使用适当类型的默认操作符类;如果没有默认操作符类,则会引发错误。使用哈希分区时,必须使用实现支持函数2的操作符类。
分区表被划分为子表(称为分区),这些子表使用单独的CREATE TABLE命令创建。分区表本身是空的。插入到表中的数据行根据分区键中的列或表达式的值路由到分区。如果没有现有分区与新行中的值匹配,则会报告错误。
分区表不支持EXCLUDE约束;但是,您可以在单个分区上定义这些约束。
PARTITION BY RANGE(column) INTERVAL(interval_expr) (PARTITION child_table VALUES LESS THAN (value) ...)
指定对表进行分区的策略interval分区(间隔分区),interval分区是range分区在扩展,interval分区不需要在插入数据之前先行建立目标分区,而是在插入数据过程中根据建表时指定的相关属性自动建立新分区并插入数据。功能上支持分区自动创建和满足条件的range分区与interval分区之间互相转换,如,interval分区转range分区:alter table partition_name set interval();range分区转interval分区:alter table partition_name set interval(1000);。
注意
- 为了保证自动创建子表的表名有效性,interval分区主表名限制最长不得超过52个字符;
- interval分区只能指定单一分区键;
- interval分区仅支持部分数字和时间类型做分区键(具体支持以下类型:int2/int4/int8/float4/float8/numeric/date/timestamp/timestamptz);
- 间隔定义的类型必须和分区键类型匹配,或支持隐式转换到匹配的类型。具体规则为:
a. int2/int4/int8/float4/float8/numeric类型的分区键间隔定义也必须为分区键对应类型或支持转换到对应类型;
b. date/timestamp/timestamptz类型的分区键必须为interval类型或支持转换到interval类型(对于uxdb date类型额外要求间隔定义必须大于等于一天)。 - interval分区表创建时必须指定一个或多个用户定义分区;
- 用户定义分区不能包含default属性;
- 用户定义分区不能包含MAXVALUE分区;
- 用户定义分区指定后不支持删除;
- 只有子分区起始点为MINVALUE,无分区空洞、无默认分区、终点不为MAXVALUE的range分区支持转换为interval分区。
PARTITION OF parent_table{ FOR VALUESpartition_bound_spec|DEFAULT }
将表创建为指定父表的分区。表可以通过使用FOR VALUES或使用DEFAULT作为默认分区来创建。在新分区上克隆任何索引、约束和用户定义的行级触发器,这些索引、约束和触发器存在于父表中。
partition_bound_spec 必须对应于父表的分区方法和分区键,并且不能与该父表的任何现有分区重叠。使用IN的形式用于列表分区,使用FROM和TO的形式用于范围分区,使用WITH的形式用于哈希分区。
partition_bound_expr是任何无变量表达式(子查询、窗口函数、聚合函数和返回集函数不允许)。它的数据类型必须与相应的分区键列的数据类型匹配。该表达式在表创建时仅计算一次,因此它甚至可以包含易失性表达式,例如CURRENT_TIMESTAMP。
在创建列表分区时,可以指定NULL,表示分区允许分区键列为空。但是,对于给定的父表,不能有多个这样的列表分区。NULL值不能用于范围或哈希分区。
PARTITION part1 {VALUES | VALUES LESS THAN} (value,...)
指定建立子分区part1,不同分区表的子分区名不可以相同。
VALUES (value, ...)用于列表分区。
VALUES LESS THAN (value, ...)用于范围分区,指定子分区的上边界(其中隐含了下边界为上一个分区的上边界,第一个分区的下边界为MINVALUE)。
-
SUBPARTITION BY { RANGE | LIST | HASH } …
可选的PARTITION BY子句指定了表的子分区策略,用于组合分区的语法。其他语法意义与分区相同。 -
STORE IN ( tablespace_name [, ... ] )
可选的STORE IN子句允许您指定一个或多个表空间,数据库将在其中存储间隔分区数据。可在创建interval分区时指定,表示自动创建的新分区的表空间为store in 后括号中表空间列表中的一个,在oracle12c中测试的指定逻辑为:第一个自动创建的新分区随机选取列表中的一个作为表空间,后续自动创建的新分区的表空间依次遍历表空间列表循环选取,类似循环链表。 -
PARTITIONS | SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ]
定义hash分区(子分区)的另一种方法是指定哈希分区的数量,在这种情况下,数据库会自动生成分区名称。STORE IN子句允许您指定要存储哈希分区数据的一个或多个表空间。表空间的数量不必等于分区的数量。如果分区的数量大于表空间的数量,则数据库会循环使用表空间的名称。
不指定分区名时,获取当前分区表的oid值,生成一个格式化的表名。
分区表的命名规则为:主表名_p+分区表oid
子分区的命名规则为:主表名_p+分区表oid_subp+子分区表oid
LIKE source_table [ like_option ... ]
LIKE指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。
和INHERITS不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表,并且不可能在原始表的扫描中包括新表的数据。
同样与INHERITS不同,用LIKE拷贝的列和约束不会和相似的命名列及约束融合。如果显式指定了相同的名称或者在另一个LIKE子句中指定了相同的名称,将会报错。
可选的like_option子句指定要复制的原始表的附加属性。指定INCLUDING复制该属性,指定EXCLUDING忽略该属性。EXCLUDING为默认值。如果对同一类型的对象指定了多个规范,则使用最后一个规范。可用的选项包括:
-
INCLUDING COMMENTS
将复制的列、约束和索引的注释复制。默认行为是排除注释,导致新表中复制的列和约束没有注释。 -
INCLUDING COMPRESSION
将复制的列的压缩方法复制。默认行为是排除压缩方法,导致列具有默认压缩方法。 -
INCLUDING CONSTRAINTS
将复制CHECK约束。不区分列约束和表约束。非空约束始终复制到新表中。 -
INCLUDING DEFAULTS
将复制的列定义的默认表达式复制。否则,默认表达式不会复制,导致新表中复制的列具有空默认值。请注意,复制调用数据库修改函数(例如nextval)的默认值可能会在原始表和新表之间创建功能链接。 -
INCLUDING GENERATED
将复制的列定义的任何生成表达式复制。默认情况下,新列将是常规基本列。 -
INCLUDING IDENTITY
将复制的列定义的任何标识规范复制。为新表的每个标识列创建一个新序列,与旧表关联的序列是分开的。 -
INCLUDING INDEXES
在新表上创建原始表上的索引、PRIMARY KEY、UNIQUE和EXCLUDE约束。根据默认规则选择新索引和约束的名称,而不考虑原始名称。(此行为避免了新索引可能出现重复名称失败的情况。) -
INCLUDING STATISTICS
将扩展统计信息复制到新表中。 -
INCLUDING STORAGE
将复制的列定义的STORAGE设置复制。默认行为是排除STORAGE设置,导致新表中复制的列具有类型特定的默认设置。 -
INCLUDING ALL
INCLUDING ALL是选择所有可用的单个选项的缩写形式。(在INCLUDING ALL之后编写单个EXCLUDING子句,以选择除某些特定选项之外的所有选项可能很有用。)
LIKE子句也可用于从视图、外部表或组合类型复制列定义。不适用的选项(例如从视图复制的INCLUDING INDEXES)将被忽略。
like source_table
执行create table ... like语句时,是基于某一表创建一个空表,目标表会保留在原始表中定义的所有列属性、注释信息、生成列信息和索引。
如果目标表中有表空间属性,创建的新表也会保留原表的表空间属性,并在定义的表空间中创建表。
若目标表为临时表时,创建的新表为基础表,不保留临时表特性;若想创建临时表,请使用create temporary table ... like。
目标表不保留原表相关的外键、触发器和函数。
-
CONSTRAINT constraint_name
一个列或表约束的可选名称。如果违反了约束条件,错误消息中会出现约束名称,因此可以使用类似于col must be positive的约束名称来向客户端应用程序传达有用的约束信息。(约束名称包含空格时需要使用双引号。)如果未指定约束名称,则系统会生成一个名称。 -
NOT NULL
该列不允许包含空值。 -
NULL
该列允许包含空值。这是默认设置。
此子句仅用于与非标准SQL数据库的兼容性。不建议在新应用程序中使用它。
CHECK(expression) [NO INHERIT]
CHECK子句指定一个产生布尔结果的表达式,新插入或更新的行必须满足该表达式才能成功进行插入或更新操作。评估为TRUE或UNKNOWN的表达式将成功。如果插入或更新操作的任何行产生FALSE结果,则会引发错误异常,插入或更新不会更改数据库。作为列约束指定的检查约束应仅引用该列的值,而出现在表约束中的表达式可以引用多个列。
目前,CHECK表达式不能包含子查询,也不能引用当前行的列以外的变量。系统列tableoid可以被引用,但不能引用任何其他系统列。
标记为NO INHERIT的约束将不会传播到子表。
当一个表有多个CHECK约束时,它们将按名称的字母顺序为每一行进行测试,在检查NOT NULL约束之后。
DEFAULT default_expr
DEFAULT子句为其所在列定义分配默认数据值。该值是任何无变量表达式(特别是不允许交叉引用当前表中的其他列)。子查询也不允许。默认表达式的数据类型必须与列的数据类型匹配。
默认表达式将在任何未指定该列值的插入操作中使用。如果没有列的默认值,则默认值为null。
GENERATED ALWAYS AS (generation_expr) STORED
此子句将列创建为生成列。该列不能被写入,当读取时,将返回指定表达式的结果。
关键字STORED是必需的,表示该列将在写入时计算并存储在磁盘上。
生成表达式可以引用表中的其他列,但不能引用其他生成列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。
GENERATED{ALWAYS|BY DEFAULT}AS IDENTITY[ (sequence_options)]
此子句将创建一个作为identity列的列。它将隐式附加一个序列,并且新行中的列将自动分配序列中的值。这样的列被隐式地视为NOT NULL。
子句ALWAYS和BY DEFAULT确定在INSERT和UPDATE命令中如何处理显式用户指定的值。
在INSERT命令中,如果选择了ALWAYS,则只有在INSERT语句指定OVERRIDING SYSTEM VALUE时,才接受用户指定的值。如果选择了BY DEFAULT,则用户指定的值优先。有关详细信息,请参见INSERT。(在COPY命令中,无论此设置如何,始终使用用户指定的值。)
在UPDATE命令中,如果选择了ALWAYS,则将拒绝将列更新为任何值,除了DEFAULT。如果选择了BY DEFAULT,则可以正常更新该列。(UPDATE命令没有OVERRIDING子句。)
可选的sequence_options子句可用于覆盖序列的选项。有关详细信息,请参见CREATE SEQUENCE。
UNIQUE [ NULLS [ NOT ] DISTINCT ](列约束)
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ](表约束)
UNIQUE约束指定表的一个或多个列组只能包含唯一值。唯一表约束的行为与唯一列约束相同,但具有跨多个列的附加功能。因此,该约束强制要求任何两行必须在这些列中至少有一个不同。
对于唯一约束,除非指定了NULLS NOT DISTINCT,否则不将空值视为相等。
每个唯一约束应命名一个与表定义的任何其他唯一或主键约束命名的列集不同的列集。(否则,将丢弃冗余的唯一约束。)
在为多级分区层次结构建立唯一约束时,必须在约束定义中包括目标分区表的分区键中的所有列,以及所有后代分区表的列。
添加唯一约束将自动在用于约束的列或列组上创建唯一的btree索引。
可选的INCLUDE子句将一个或多个仅为“有效负载”的列添加到该索引中:不对它们强制执行唯一性,并且不能根据这些列搜索索引。但是,它们可以通过索引扫描进行检索。请注意,虽然约束不强制执行包含的列,但它们仍然受到索引的限制。它仍然取决于它们。因此,对这些列进行的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。
PRIMARY KEY(列约束)
PRIMARY KEY(column_name[,...])[INCLUDE(column_name[,...])](表约束)
PRIMARY KEY约束指定表的一列或多列只能包含唯一(非重复),非空值。对于一个表,只能指定一个主键,无论是作为列约束还是表约束。
主键约束应该命名一个与为同一表定义的任何唯一约束命名的列集不同的列集。(否则,唯一约束是冗余的,并将被丢弃。)
PRIMARY KEY强制执行与UNIQUE和NOT NULL的组合相同的数据约束。但是,将一组列标识为主键还提供了有关模式设计的元数据,因为主键意味着其他表可以依赖于此列集作为行的唯一标识符。
当放置在分区表上时,PRIMARY KEY约束共享先前描述的UNIQUE约束的限制。
添加PRIMARY KEY约束将自动在用于约束的列或列组上创建唯一的btree索引。
可选的INCLUDE子句将一个或多个仅为“有效负载”的列添加到该索引中:不对它们强制执行唯一性,并且不能根据这些列搜索索引。但是,它们可以通过索引扫描检索。请注意,尽管未在包含的列上强制执行约束,但它仍然取决于它们。因此,对这些列进行的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。
EXCLUDE[USING index_method] (exclude_elementWITHoperator[,...])index_parameters[WHERE (predicate)]
EXCLUDE子句定义了一个排除约束,它保证如果使用指定的列或表达式和指定的运算符比较任何两行,则不会返回所有这些比较都为TRUE。如果所有指定的运算符都测试相等,则这相当于一个UNIQUE约束,尽管普通的唯一约束将更快。但是,排除约束可以指定比简单相等更一般的约束。例如,您可以使用&&运算符指定一个约束,即表中没有两行包含重叠的圆。
排除约束使用索引实现,因此每个指定的运算符必须与索引访问方法index_method相关联的适当运算符类。要求运算符是可交换的。每个exclude_element都可以选择指定操作符类或排序选项;这些在CREATE INDEX中有详细描述。
访问方法必须支持amgettuple;目前这意味着GIN不能使用。虽然允许使用B树或哈希索引来实现排除约束,但这并没有比普通唯一约束更好。因此,在实践中,访问方法将始终是GiST或SP-GiST。
predicate允许您在表的子集上指定排除约束;在内部,这将创建一个部分索引。请注意,括号必须放在谓词周围。
REFERENCES reftable[ (refcolumn) ] [ MATCHmatchtype][ ON DELETE referential_action] [ ON UPDATEreferential_action](列约束)
FOREIGN KEY(column_name[, ... ] ) REFERENCESreftable[ (refcolumn[, ... ] ) ] [ MATCHmatchtype] [ ON DELETEreferential_action] [ ON UPDATEreferential_action](表约束)
这些子句指定外键约束,要求新表的一个或多个列的组仅包含与引用表的某行的引用列中的值匹配的值。如果省略refcolumn列表,则使用reftable的主键。引用列必须是引用表中不可延迟的唯一约束或主键约束的列。用户必须具有对引用表(整个表或特定引用列)的REFERENCES权限。添加外键约束需要在引用表上进行SHARE ROW EXCLUSIVE锁定。请注意,临时表和永久表之间不能定义外键约束。
插入到引用列中的值使用给定的匹配类型与引用表和引用列中的值进行匹配。有三种匹配类型:MATCH FULL、MATCH PARTIAL和MATCH SIMPLE(默认)。MATCH FULL不允许多列外键的一列为空,除非所有外键列都为空;如果它们都为空,则不需要在引用表中匹配行。MATCH SIMPLE允许任何外键列为空;如果它们中的任何一个为空,则不需要在引用表中匹配行。MATCH PARTIAL尚未实现。(当然,可以对引用列应用NOT NULL约束,以防止出现这些情况。)
此外,当引用列中的数据发生更改时,在此表中对数据执行某些操作列。ON DELETE子句指定在引用表中的引用行正在被删除时执行的操作。同样,ON UPDATE子句指定在引用表中的引用列正在被更新为新值时执行的操作。如果更新了行,但实际上未更改引用列,则不执行任何操作。除非约束声明为可延迟,否则不能延迟参照动作检查以外的参照动作。每个子句有以下可能的操作:
-
NO ACTION
产生一个错误,指示删除或更新将创建外键约束违规。如果约束是延迟的,则如果仍存在任何引用行,则在约束检查时会产生此错误。这是默认操作。 -
RESTRICT
产生一个错误,指示删除或更新将创建外键约束违规。这与NO ACTION相同,只是检查不可延迟。 -
CASCADE
删除引用删除行的任何行,或将引用列的值更新为相应的引用列的新值。 -
SET NULL[ (column_name[, ... ] ) ]
将所有引用列或指定的一组引用列设置为null。只能为ON DELETE操作指定列的子集。 -
SET DEFAULT[ (column_name[, ... ] ) ]
将所有引用列或指定的一组引用列设置为它们的默认值。只能为ON DELETE操作指定列的子集。(如果默认值不为null,则引用表中必须有与默认值匹配的行,否则操作将失败。)
如果引用列经常更改,可能明智地向引用列添加索引,以便与外键约束相关的参照动作可以更有效地执行。
-
DEFERRABLE
NOT DEFERRABLE
这控制约束是否可以延迟。不可延迟的约束将在每个命令之后立即检查。可延迟约束的检查可以推迟到事务结束(使用 SET CONSTRAINTS命令)。NOT DEFERRABLE是默认值。目前,只有UNIQUE、PRIMARY KEY、EXCLUDE和REFERENCES(外键)约束接受此子句。NOT NULL和CHECK约束不可延迟。请注意,可延迟约束不能用作包含ON CONFLICT DO UPDATE子句的INSERT语句中的冲突仲裁器。 -
INITIALLY IMMEDIATE
INITIALLY DEFERRED
如果约束是可延迟的,则此子句指定检查约束的默认时间。如果约束是INITIALLY IMMEDIATE,它在每个语句之后都会被检查。这是默认设置。如果约束是INITIALLY DEFERRED,则仅在事务结束时进行检查。可以使用SET CONSTRAINTS命令更改约束检查时间。 -
USING method
此可选子句指定用于存储新表内容的表访问方法;该方法需要是类型为TABLE的访问方法。如果未指定此选项,则为新表选择默认表访问方法。 -
WITH(storage_parameter[=value] [, ... ])
此子句指定表或索引的可选存储参数;有关更多信息,请参见下面的CREATE TABLE中的“存储参数”。为了向后兼容,表的WITH子句还可以包括OIDS=FALSE,以指定新表的行不应包含OID(对象标识符),不再支持OIDS=TRUE。 -
WITHOUT OIDS
这是声明表WITHOUT OIDS的向后兼容语法,不再支持创建带有OID的表WITH OIDS。 -
ON COMMIT
可以使用ON COMMIT控制事务块结束时临时表的行为。有三个选项: -
PRESERVE ROWS
在事务结束时不采取任何特殊操作。这是默认行为。 -
DELETE ROWS
在每个事务块结束时,将删除临时表中的所有行。本质上,每次提交都会自动执行TRUNCATE。在分区表上使用时,不会级联到其分区。 -
DROP
在当前事务块结束时,将删除临时表。在分区表上使用时,此操作会删除其分区,在具有继承子项的表上使用时,它会删除相关子项。 -
TABLESPACE tablespace_name
tablespace_name是要创建新表的表空间的名称。如果未指定,则会查看default_tablespace,或者如果表是临时的,则查看temp_tablespaces。对于分区表,由于表本身不需要存储,因此指定的表空间会覆盖default_tablespace。当没有显式指定其他表空间时,此默认表空间将用作创建新分区时使用的表空间。 -
STORAGE
STORAGE语法可以指定创建表的表空间,表空间必须已存在,此语法缺省时为该用户的默认表空间。 -
CLUSTERBTR
当INI参数LIST_TABLE = 1时,指定CLUSTERBTR,则建立的表为普通B树表而非堆表;该参数保留。 -
USING INDEX TABLESPACE tablespace_name
此子句允许选择与UNIQUE、PRIMARY KEY或EXCLUDE约束关联的索引将被创建在哪个表空间中。如果未指定,则会查阅default_tablespace,或者如果表是临时表,则查阅temp_tablespaces。
存储参数
WITH 子句可以为表和与UNIQUE、PRIMARY KEY或EXCLUDE约束关联的索引指定存储参数。索引的存储参数在CREATE INDEX中有记录。当前可用于表的存储参数如下所示。对于其中许多参数,如所示,还有一个以toast.为前缀的同名参数,用于控制表的辅助TOAST表(如果有)的行为。如果设置了表参数值并且没有等效的 toast. 参数,则TOAST表将使用表的参数值。不支持为分区表指定这些参数,但可以为单个叶子分区指定这些参数。
-
fillfactor(integer)
表的填充因子是介于10和100之间的百分比。100(完全打包)是默认值。当指定较小的填充因子时,INSERT操作仅将表页打包到指定的百分比;每个页上剩余的空间保留用于更新该页上的行。这使得UPDATE有机会将更新后的行的副本放置在与原始行相同的页上,这比将其放置在不同的页上更有效,并使得仅堆元组更新更有可能发生。对于从不更新条目的表,完全打包是最佳选择,但在经常更新的表中,较小的填充因子是合适的。此参数不能为TOAST表设置。 -
toast_tuple_target(integer)
toast_tuple_target指定在我们尝试压缩或将长列值移动到TOAST表中之前所需的最小元组长度,并且也是我们尝试在开始TOAST时将长度减少到以下目标长度。这会影响标记为External(用于移动)、Main(用于压缩)或Extended(用于两者)的列,仅适用于新元组。对现有行没有影响。默认情况下,此参数设置为允许每个块至少有4个元组,这将是2040字节(使用默认块大小)。有效值介于128字节和(块大小-头)之间,默认为8160字节。更改此值可能对非常短或非常长的行无用。请注意,默认设置通常接近最佳状态,设置此参数可能在某些情况下产生负面影响。此参数无法设置为TOAST表。 -
parallel_workers(integer)
此设置表的并行扫描应使用的工作进程数。如果未设置,则系统将根据关系大小确定一个值。由规划器或使用并行扫描的实用程序语句选择的实际工作进程数量可能较少,例如由于设置了max_worker_processes。 -
autovacuum_enabled,toast.autovacuum_enabled(boolean)
启用或禁用特定表的自动清理守护程序。如果为true,则自动清理守护程序将在此表上执行自动VACUUM或ANALYZE操作。如果为false,则不会自动清理此表,除非为了防止事务ID环绕。请注意,如果 autovacuum参数为false,则自动清理守护程序根本不运行(除了防止事务ID环绕);设置单个表的存储参数不会覆盖该参数。因此,明确将此存储参数设置为true只有很少的意义,只有将其设置为false。 -
vacuum_index_cleanup,toast.vacuum_index_cleanup(enum)
强制启用或禁用在此表上运行VACUUM时的索引清理。默认值为AUTO。使用OFF禁用索引清理,使用ON启用索引清理,使用AUTO动态地做出决策,每次运行VACUUM时。动态行为允许VACUUM避免不必要地扫描索引以删除非常少的死元组。强制禁用所有索引清理可以显着加快VACUUM的速度,但如果表修改频繁,也可能导致索引严重膨胀。如果指定了VACUUM的INDEX_CLEANUP参数,则覆盖此选项的值。 -
vacuum_truncate,toast.vacuum_truncate(boolean)
启用或禁用VACUUM尝试截断此表末尾的任何空页面。默认值为true。如果为true,则VACUUM和自动清理将进行截断,并将截断页面的磁盘空间返回给操作系统。请注意,截断需要对表进行ACCESS EXCLUSIVE锁定。如果指定了VACUUM的TRUNCATE参数,则会覆盖此选项的值。 -
autovacuum_vacuum_threshold,toast.autovacuum_vacuum_threshold(integer)
autovacuum_vacuum_threshold参数的每个表值。 -
autovacuum_vacuum_scale_factor,toast.autovacuum_vacuum_scale_factor(floating point)
autovacuum_vacuum_scale_factor参数的每个表值。 -
autovacuum_vacuum_insert_threshold,toast.autovacuum_vacuum_insert_threshold(integer)
autovacuum_vacuum_insert_threshold参数的每个表值。特殊值-1可用于禁用表上的插入vacuum。 -
autovacuum_vacuum_insert_scale_factor,toast.autovacuum_vacuum_insert_scale_factor(floating point)
autovacuum_vacuum_insert_scale_factor参数的每个表值。 -
autovacuum_analyze_threshold(integer)
autovacuum_analyze_threshold参数的每个表值。 -
autovacuum_analyze_scale_factor(floating point)
autovacuum_analyze_scale_factor参数的每个表值。 -
autovacuum_vacuum_cost_delay,toast.autovacuum_vacuum_cost_delay(floating point)
autovacuum_vacuum_cost_delay参数的每个表值。 -
autovacuum_vacuum_cost_limit,toast.autovacuum_vacuum_cost_limit(integer)
autovacuum_vacuum_cost_limit参数的每个表值。 -
autovacuum_freeze_min_age,toast.autovacuum_freeze_min_age(integer)
vacuum_freeze_min_age参数的每个表值。请注意,自动清理将忽略大于系统范围内autovacuum_freeze_max_age设置一半的每个表autovacuum_freeze_min_age参数。 -
autovacuum_freeze_max_age,toast.autovacuum_freeze_max_age(integer)
autovacuum_freeze_max_age参数的每个表值。请注意,自动清理将忽略大于系统范围内的每个表autovacuum_freeze_max_age参数(它只能设置得更小)。 -
autovacuum_freeze_table_age,toast.autovacuum_freeze_table_age(integer)
vacuum_freeze_table_age参数的每个表值。 -
autovacuum_multixact_freeze_min_age,toast.autovacuum_multixact_freeze_min_age(integer)
vacuum_multixact_freeze_min_age参数的每个表值。请注意,自动清理将忽略大于系统范围内autovacuum_multixact_freeze_max_age设置一半的每个表autovacuum_multixact_freeze_min_age参数。 -
autovacuum_multixact_freeze_max_age,toast.autovacuum_multixact_freeze_max_age(integer)
autovacuum_multixact_freeze_max_age参数的每个表值。请注意,自动清理将忽略大于系统范围内的每个表autovacuum_multixact_freeze_max_age参数(它只能设置得更小)。 -
autovacuum_multixact_freeze_table_age,toast.autovacuum_multixact_freeze_table_age(integer)
vacuum_multixact_freeze_table_age参数的每个表值。 -
log_autovacuum_min_duration,toast.log_autovacuum_min_duration(integer)
每个表的log_autovacuum_min_duration参数的值。 -
user_catalog_table(boolean)
将该表声明为逻辑复制的附加目录表。此参数不能为TOAST表设置。
注释
UXsinoDB会自动为每个唯一约束和主键约束创建索引以强制唯一性。因此,不需要为主键列显式创建索引。(有关更多信息,请参见CREATE INDEX。)
在当前实现中,唯一约束和主键不会继承。这使得继承和唯一约束的组合相当不实用。
一个表不能有超过 1600 个列。(实际上,由于元组长度的限制,有效限制通常更低。)
示例
创建表 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)
);
为列名指定一个文字常数默认值,通过选择序列对象的下一个值来安排生成 column 的默认值,并使 modtime 的默认值成为插入行的时间:
CREATE TABLE distributors (
name varchar(40) DEFAULT 'Luso Films',
did integer DEFAULT nextval('distributors_serial'),
modtime timestamp DEFAULT current_timestamp
);
为列name分配一个字面常量默认值,安排列did的默认值通过选择序列对象的下一个值生成,并使len的默认值为'1 hour':
CREATE TABLE distributors (
did integer DEFAULT nextval('serial'),
name varchar(40) DEFAULT 'Anonymous',
len interval DEFAULT '1 hour'
);
在表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_y2016m07
PARTITION OF measurement (
unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');
创建一个具有多个列的分区键的范围分区表的几个分区:
CREATE TABLE measurement_ym_older
PARTITION OF measurement_year_month
FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);
CREATE TABLE measurement_ym_y2016m11
PARTITION OF measurement_year_month
FOR VALUES FROM (2016, 11) TO (2016, 12);
CREATE TABLE measurement_ym_y2016m12
PARTITION OF measurement_year_month
FOR VALUES FROM (2016, 12) TO (2017, 01);
CREATE TABLE measurement_ym_y2017m01
PARTITION OF measurement_year_month
FOR VALUES FROM (2017, 01) TO (2017, 02);
创建一个列表分区表的分区:
CREATE TABLE cities_ab
PARTITION OF cities (
CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b');
创建一个进一步分区的列表分区表分区并添加分区:
CREATE TABLE cities_ab
PARTITION 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_100000
PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);
创建哈希分区表的分区:
CREATE TABLE orders_p1 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 3);
创建默认分区:
CREATE TABLE cities_partdef
PARTITION OF cities DEFAULT;
建立非聚簇索引的表,如下所示。
create table test(id int,name varchar(20),constraint pk_test not cluster primary key (id));
create table cluster_table_on_1(id int not cluster primary key,name varchar(20));
storage语法使用,如下所示。
create table t_storage(id int) storage(on tblspc,clusterbtr);
\d+ t_storage;
ON UPDATE NOW()使用,如下所示。
create table test(id int, ts timestamp on update now());
建立以GENERATED ALWAYS AS生成列为分区建的分区表,如下所示。
CREATE TABLE gtest_parent3(f1 int, f2 int GENERATED ALWAYS AS(f1 * 10) STORED) PARTITION BY RANGE(f2);
创建interval分区表,如下所示。
create table interval_partition_test(id int) partition by range(id) interval(100) (partition nterval_partition_test_int_p1 values less than(100));
interval分区转range分区,如下所示。
alter table nterval_partition_test set interval();
range分区转interval分区,如下所示。
alter table rang_partition_test set interval(1000);
创建range分区,如下所示。
CREATE TABLE T_DB_PARTITION_USERINFO(
USID NUMBER(5),
USNAME VARCHAR2(10),
CREATEDATE DATE,
AGE NUMBER(3),
REMARK CLOB
)PARTITION BY RANGE(USID)(
PARTITION RANG_P1 VALUES LESS THAN(5) ,
PARTITION RANG_P2 VALUES LESS THAN(10),
PARTITION RANG_P3 VALUES LESS THAN(15),
PARTITION RANG_PMAX VALUES LESS THAN(MAXVALUE)
);
创建list分区,如下所示。
CREATE TABLE LIST_DEMO2
(
ID NUMBER,
NAME VARCHAR2(20),
ADDRESS VARCHAR2(100)
)
PARTITION BY LIST(ADDRESS)
(
PARTITION P_BeiJing VALUES ('beijing'),
PARTITION P_ShanXi VALUES ('shanxi'),
PARTITION P_ShanDong VALUES ('shandong'),
PARTITION P_Other VALUES ( DEFAULT )
);
创建表空间
create tablespace TETSTBS1 location '/home/uxdb/uxdb-ng/uxdb-2.1/src/test/regress/compatible_testcase/testtablespace';
create tablespace TETSTBS2 location '/home/uxdb/uxdb-ng/uxdb-2.1/src/test/regress/compatible_testcase/testtablespace2';
```sql
RANGE分区
```sql
create table range_test1(a int,b char(32)) partition by range(a) (partition p1 values less than (20) tablespace TETSTBS1 ,partition p2 values less than (40) tablespace TETSTBS2, partition p3 values less than (60) tablespace TETSTBS1);
insert into range_test1 values(10,'uxdb');
insert into range_test1 values(30,'oracle');
select * from range_test1 partition(p1);
A | B
----+----
10 | uxdb
(1 row)
select * from range_test1 partition(range_test1_p2);
A | B
----+----
30 | oracle
(1 row)
select SPCNAME from ux_class as a join UX_TABLESPACE as b on(a.RELTABLESPACE = b.oid and a.relname = 'RANGE_TEST1_P2');
SPCNAME
TETSTBS2
(1 row)
LIST分区
create table list_test(a int,b char(32)) partition by list(b) (partition p1 values ('uxdb','UXDB') tablespace TETSTBS1 ,partition p2 values ('oracle','ORACLE') tablespace TETSTBS2, partition p3 values (DEFAULT) tablespace MAIN);
insert into list_test values (18,'uxdb');
insert into list_test values (18,'ORACLE');
insert into list_test values (18,'abcd');
select * from list_test partition(p1);
A | B
----+----
18 | uxdb
(1 row)
select * from list_test partition(p2);
A | B
----+----
18 | ORACLE
(1 row)
select * from list_test partition(list_test_p3);
A | B
----+----
18 | abcd
(1 row)
drop table list_test;
```sql
HASH分区
```sql
create table hash_test1(a int,b char(32)) partition by hash(a) (partition p1 tablespace TETSTBS1 ,partition p2 tablespace TETSTBS2, partition p3 tablespace MAIN);
insert into hash_test1 values (1,'uxdb');
insert into hash_test1 values (3,'uxdb');
drop table hash_test1;
复合分区
RANGE组合分区
RANGE + RANGE组合分区
create table range_com_test1(a int,b int) partition by range(a) subpartition by range(b)(partition p1 values less than (20)(subpartition p1_1 values less than (100), subpartition p1_2 values less than (200)),partition p2 values less than (40)(subpartition p2_1 values less than (100), subpartition p2_2 values less than (200)));
insert into range_com_test1 values(18,88);
insert into range_com_test1 values(18,188);
insert into range_com_test1 values(28,88);
insert into range_com_test1 values(28,188);
select * from range_com_test1 partition(p1);
A | B
----+
18 | 88
18 | 188
(2 rows)
select * from range_com_test1 partition(range_com_test1_p2);
A | B
----+
28 | 88
28 | 188
(2 rows)
select * from range_com_test1 subpartition(range_com_test1_p1_p1_2);
A | B
----+
18 | 188
(1 row)
select * from range_com_test1 subpartition(p2_1);
A | B
----+----
28 | 88
(1 row)
```sql
RANGE + LIST组合分区
```sql
create table range_com_test3(a int,b char(32)) partition by range(a) subpartition by list(b)(partition p1 values less than (20)(subpartition p1_1 values('uxdb','UXDB'),subpartition p1_2 values('oracle','ORACLE'),subpartition p1_3 values('plsql','PLSQL')),partition p2 values less than (40)(subpartition p2_1 values('uxdb','UXDB'),subpartition p2_2 values('oracle','ORACLE'),subpartition p2_3 values('plsql','PLSQL')),partition p3 values less than (60)(subpartition p3_1 values('uxdb','UXDB'),subpartition p3_2 values('oracle','ORACLE'),subpartition p3_3 values('plsql','PLSQL')));
insert into range_com_test3 values(18,'uxdb');
insert into range_com_test3 values(18,'ORACLE');
insert into range_com_test3 values(58,'plsql');
select * from range_com_test3 subpartition(p3_3);
A | B
----+----
58 | plsql
(1 row)
select * from range_com_test3 subpartition(range_com_test3_p1_p1_2);
A | B
----+----
18 | ORACLE
(1 row)
drop table range_com_test3;
```sql
RANGE + HASH组合分区
```sql
create table range_com_test4(a int,b char(32)) partition by range(a) subpartition by hash(b)(partition p1 values less than (20)(subpartition p1_1 tablespace TETSTBS1, subpartition p1_2 tablespace TETSTBS2),partition p2 values less than (40)(subpartition p2_1 tablespace TETSTBS1, subpartition p2_2 tablespace TETSTBS2));
insert into range_com_test4 values(18,'uxdb');
insert into range_com_test4 values(18,'oracle');
drop table range_com_test4;
-- RANGE + HASH (hash subpartitions quantity)
create table range_com_test5(a int,b char(32)) partition by range(a) subpartition by hash(b) subpartitions 3 store in ( TETSTBS1,TETSTBS2,MAIN) (partition p1 values less than (20) ,partition p2 values less than (40));
insert into range_com_test5 values(18,'uxdb');
insert into range_com_test5 values(28,'oracle');
drop table range_com_test5;
```sql
INTERVAL组合分区
INTERVAL+ RANGE组合分区
```sql
create table interval_com_test1(a int,b int) partition by range(a) interval (20) store in (TETSTBS2,TETSTBS1,MAIN) subpartition by range(b)(partition p1 values less than (20)(subpartition p1_1 values less than (100), subpartition p1_2 values less than (200)));
insert into interval_com_test1 values(21,888);
select * from interval_com_test1;
A | B
----+
21 | 888
(1 row)
drop table interval_com_test1;
```sql
INTERVAL+ LIST组合分区
```sql
create table interval_com_test2(a int,b char(32)) partition by range(a) interval (20) store in (TETSTBS2,TETSTBS1,MAIN) subpartition by list(b)(partition p1 values less than (20)(subpartition p1_1 values ('uxdb'), subpartition p1_2 values ('oracle')));
insert into interval_com_test2 values(21,'plsql');
select * from interval_com_test2;
A | B
----+----
21 | plsql
(1 row)
```sql
INTERVAL+ HASH组合分区
```sql
create table interval_com_test3(a int,b int) partition by range(a) interval (20) store in (TETSTBS2,TETSTBS1,MAIN) subpartition by hash(b)(partition p1 values less than (20)(subpartition p1_1, subpartition p1_2 ));
insert into interval_com_test3 values(21,888);
select * from interval_com_test3;
A | B
----+
21 | 888
(1 row)
drop table interval_com_test3;
LIST组合分区
LIST + RANGE组合分区
create table list_com_test1(a char(32),b int) partition by list(a) subpartition by range(b)(partition p1 values ('uxdb','UXDB')(subpartition p1_1 values less than (100), subpartition p1_2 values less than (200)),partition p2 values ('oracle','ORACLE')(subpartition p2_1 values less than (100), subpartition p2_2 values less than (200)));
insert into list_com_test1 values('uxdb',188);
insert into list_com_test1 values('ORACLE',88);
select * from list_com_test1 partition(p1);
A | B
----+
uxdb | 188
(1 row)
select * from list_com_test1 subpartition(list_com_test1_p2_p2_1);
A | B
----+----
ORACLE | 88
(1 row)
drop table list_com_test1;
LIST + LIST组合分区
create table list_com_test2(a char(32),b char(32)) partition by list(a) subpartition by list(b)(partition p1 values ('uxdb','UXDB')(subpartition p1_1 values ('uxsql','UXSQL'), subpartition p1_2 values ('pluxsql','PLUXSQL')),partition p2 values ('oracle','ORACLE')(subpartition p2_1 values ('plsql','PLSQL'), subpartition p2_2 values ('orafce','ORAFCE')));
insert into list_com_test2 values('uxdb','uxsql');
insert into list_com_test2 values('oracle','orafce');
drop table list_com_test2;
-- LIST + HASH
create table list_com_test3(a char(32),b char(32)) partition by list(a) subpartition by hash(b)(partition p1 values ('uxdb','UXDB')(subpartition p1_1 tablespace TETSTBS1, subpartition p1_2 tablespace TETSTBS2),partition p2 values ('oracle','ORACLE')(subpartition p2_1 tablespace TETSTBS1, subpartition p2_2 tablespace TETSTBS2));
insert into list_com_test3 values('uxdb','uxsql');
insert into list_com_test3 values('ORACLE','orafce');
select * from list_com_test3;
A | B
----+----
ORACLE | orafce
uxdb | uxsql
(2 rows)
drop table list_com_test3;
LIST + HASH组合分区
-- LIST + HASH (hash subpartitions quantity)
create table list_com_test4(a char(32),b char(32)) partition by list(a) subpartition by hash(b) subpartitions 3 store in ( TETSTBS1,TETSTBS2,MAIN) (partition p1 values ('uxdb','UXDB') ,partition p2 values ('oracle','ORACLE'));
insert into list_com_test4 values('uxdb','uxsql');
insert into list_com_test4 values('ORACLE','orafce');
select * from list_com_test4;
A | B
----+----
ORACLE | orafce
uxdb | uxsql
(2 rows)
drop table list_com_test4;
LIST DEFAULT组合分区
create table list_com_test5(a char(32),b int) partition by list(a) subpartition by range(b)(partition p1 values ('uxdb','UXDB')(subpartition p1_1 values less than (100), subpartition p1_2 values less than (200)),partition p2 values (DEFAULT)(subpartition p2_1 values less than (100), subpartition p2_2 values less than (200)));
insert into list_com_test5 values('uxdb',88);
insert into list_com_test5 values('oracle',88);
insert into list_com_test5 values('kingbase',188);
select * from list_com_test5 partition(p2);
A | B
----+
oracle | 88
kingbase | 188
(2 rows)
select * from list_com_test5 subpartition(p2_1);
A | B
----+----
oracle | 88
(1 row)
select * from list_com_test5 subpartition(list_com_test5_p2_p2_2);
A | B
----+
kingbase | 188
(1 row)
drop table list_com_test5;
```sql
HASH组合分区
HASH +RANGE组合分区
```sql
create table hash_com_test1(a int,b int) partition by hash(a) subpartition by range(b)(partition p1 (subpartition p1_1 values less than (100), subpartition p1_2 values less than (200)),partition p2 (subpartition p2_1 values less than (100), subpartition p2_2 values less than (200)));
insert into hash_com_test1 values(18,88);
insert into hash_com_test1 values(88,188);
select * from hash_com_test1;
A | B
----+
18 | 88
88 | 188
(2 rows)
drop table hash_com_test1;
```sql
HASH +LIST组合分区
```sql
create table hash_com_test2(a int,b char(32)) partition by hash(a) subpartition by list(b)(partition p1 (subpartition p1_1 values ('uxdb','UXDB'), subpartition p1_2 values ('oracle','ORACLE')),partition p2 (subpartition p2_1 values ('uxdb','UXDB'), subpartition p2_2 values ('oracle','ORACLE')));
insert into hash_com_test2 values(18,'uxdb');
insert into hash_com_test2 values(88,'oracle');
select * from hash_com_test2;
A | B
----+----
88 | oracle
18 | uxdb
(2 rows)
drop table hash_com_test2;
```sql
HASH +HASH组合分区
-- HASH + HASH (hash subpartitions quantity)
create table hash_com_test3(a char(32),b int) partition by hash(a) subpartition by hash(b) subpartitions 3 store in ( TETSTBS1,TETSTBS2,MAIN) (partition p1 ,partition p2 );
insert into hash_com_test3 values('uxdb',88);
insert into hash_com_test3 values('oracle',188);
insert into hash_com_test3 values('kingbase',888);
select * from hash_com_test3;
A | B
----+
kingbase | 888
uxdb | 88
oracle | 188
(3 rows)
drop table hash_com_test3;
-- HASH (partitions quantity) + HASH (hash subpartitions quantity)
create table hash_com_test4(a char(32),b int) partition by hash(a) subpartition by hash(b) subpartitions 3 store in ( TETSTBS1,TETSTBS2,MAIN) partitions 2 store in ( TETSTBS1,TETSTBS2,MAIN);
insert into hash_com_test4 values('uxdb',88);
insert into hash_com_test4 values('oracle',188);
insert into hash_com_test4 values('kingbase',888);
select * from hash_com_test4;
A | B
----+
kingbase | 888
uxdb | 88
oracle | 188
(3 rows)
drop table hash_com_test4;
-- SPECIAL PARTITION TABLE
create table spe_com_test1 (
transaction_id number ,
transaction_date date,
amount varchar(10)
)
partition by range (transaction_id) interval (10)
subpartition by hash (transaction_date)
(partition sub_p1 values less than (2023)
(subpartition sub_p1_1 , subpartition sub_p1_2 ),
partition sub_p2 values less than (2024)
(subpartition sub_p2_1 , subpartition sub_p2_2 ),
partition sub_p3 values less than (2025)
(subpartition sub_p3_1 , subpartition sub_p3_2 ));
insert into spe_com_test1 values(2023,to_date('2020-01-01', 'yyyy-mm-dd'),'uxdb');
insert into spe_com_test1 values(2024,to_date('2021-01-01', 'yyyy-mm-dd'),'oracle');
insert into spe_com_test1 values(2023.5,to_date('2021-02-01', 'yyyy-mm-dd'),'kingbase');
select * from spe_com_test1 order by 1,2;
TRANSACTION_ID | TRANSACTION_DATE | AMOUNT
-+-+
2023 | Wed Jan 01 00:00:00 2020 | uxdb
2023.5 | Mon Feb 01 00:00:00 2021 | kingbase
2024 | Fri Jan 01 00:00:00 2021 | oracle
(3 rows)
select * from spe_com_test1 partition(sub_p2) order by 1,2;
TRANSACTION_ID | TRANSACTION_DATE | AMOUNT
-+-+
2023 | Wed Jan 01 00:00:00 2020 | uxdb
2023.5 | Mon Feb 01 00:00:00 2021 | kingbase
(2 rows)
select * from spe_com_test1_sub_p2 order by 1,2;
TRANSACTION_ID | TRANSACTION_DATE | AMOUNT
-+-+
2023 | Wed Jan 01 00:00:00 2020 | uxdb
2023.5 | Mon Feb 01 00:00:00 2021 | kingbase
(2 rows)
<a id="createtable_compatibility"></a>
## 兼容性**
`CREATE TABLE`命令符合SQL标准,以下是一些例外。
**临时表**
虽然`CREATE TEMPORARY TABLE`的语法类似于SQL标准,但效果不同。在标准中,临时表只定义一次,并在需要它们的每个会话中自动存在(从空内容开始)。UXsinoDB要求每个会话为要使用的每个临时表发出自己的`CREATE TEMPORARY TABLE`命令。这允许不同的会话为不同的目的使用相同的临时表名称,而标准的方法则限制了给定临时表名称的所有实例具有相同的表结构。
标准中关于临时表行为的定义经常被忽略。在这一点上,UXsinoDB的行为类似于其他几个SQL数据库。
SQL标准还区分全局和本地临时表,其中本地临时表对于每个会话中的每个SQL模块都有一个单独的内容集,尽管它的定义仍然在会话之间共享。由于UXsinoDB不支持SQL模块,因此这种区别在UXsinoDB中不相关。
临时表的`ON COMMIT`子句也和SQL标准相似,但是有一些不同。如果忽略`ON COMMIT`子句,SQL指定默认行为是`ON COMMIT DELETE ROWS`)。但是,UXDB中的默认行为是`ON COMMIT PRESERVE ROWS`。SQL中不存在`ON COMMIT DROP`选项。UXDB兼容模式下,默认行为为`ON COMMIT DELETE ROWS`。
使用`GLOBAL TEMPORARY`标识表是临时的,且定义对所有会话可见,数据只对插入数据的会话可见。
首次创建全局临时表时,表的元数据存在数据字典中,但是不对表的数据分配空间。空间的分配主要是在第一次执行DML(`insert`,`update`,`delete`)操作时。
只有在没有会话绑定的临时表上,可以执行ddl操作,即(`alter table` ,`drop table`,`create index`)。通常,表执行插入操作的时候,会话会绑定到临时表上;通过发送截断语句,或者会话终止,会话不再绑定到临时表。对于特定事务的临时表,则依赖提交或者回滚语句。
临时表的定义和普通表的定义一致,但是表段和表中包含的任何数据要么是特定于会话的数据,要么是特定于事务的数据。具体依赖于关键字`on commit`关键字。全局临时表有两种模式:一种是基于会话级别的(`ON COMMIT PRESERVE ROWS`),当会话结束时自动清空用户数据;一种是基于事务级别的(`ON COMMIT DELETE ROWS`), 当执行`commit`或`rollback`时自动清空用户数据。与本地临时表不同,全局临时表建表时可以指定非ux_temp_开头的schema。示例如下。
创建全局临时表films:
```sql
CREATE GLOBAL TEMPORARY 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
);
非延迟唯一性约束
当UNIQUE或PRIMARY KEY约束不可延迟时,UXsinoDB在插入或修改行时立即检查唯一性。SQL标准指出,唯一性应仅在语句结束时强制执行;例如,当单个命令更新多个键值时,这会产生差异。为了获得符合标准的行为,请将约束声明为
唯一性约束
SQL标准规定,唯一性约束可以是DEFERRABLE,但不能是延迟的(即INITIALLY IMMEDIATE)。请注意,这可能比立即检查唯一性要慢得多。
列检查约束
SQL标准规定,CHECK列约束只能引用它们所应用的列;只有CHECK表约束可以引用多个列。UXsinoDB不强制执行此限制;它将列和表检查约束视为同等。
EXCLUDE约束
EXCLUDE约束类型是UXsinoDB的扩展。
外键约束操作
在外键操作SET DEFAULT和SET NULL中指定列列表是UXsinoDB的扩展。
NULL约束
NULL约束(实际上是非约束)是SQL标准的UXsinoDB扩展,用于与其他一些数据库系统兼容(以及与NOT NULL约束对称)。由于它是任何列的默认值,因此它的存在只是噪音。
约束命名
SQL标准规定,表和域约束必须具有在包含表或域的模式中唯一的名称。UXsinoDB更宽松:它只需要约束名称在特定表或域附加的约束中是唯一的。但是,对于基于索引的约束(UNIQUE,PRIMARY KEY和EXCLUDE约束),不存在此额外的自由,因为关联的索引与约束同名,索引名称必须在同一模式中的所有关系中是唯一的。
目前,UXsinoDB根本不记录NOT NULL约束的名称,因此它们不受唯一性限制。这可能会在将来的版本中更改。
继承
通过INHERITS子句进行的多重继承是UXsinoDB的语言扩展。SQL:1999及更高版本使用不同的语法和不同的语义定义单一继承。SQL:1999风格的继承尚未得到UXsinoDB的支持。
零列表
UXsinoDB允许创建没有列的表(例如CREATE TABLE foo();)。这是SQL标准的扩展,不允许零列表。零列表本身并不是非常有用,但是禁止它们会为ALTER TABLE DROP COLUMN创建奇怪的特殊情况,因此忽略此规范限制似乎更清晰。
多个标识列
UXsinoDB允许表具有多个标识列。标准规定表最多只能有一个标识列。这主要是为了更灵活地进行模式更改或迁移而放宽的。请注意,这不会影响标准的SQL语义。
生成的列
选项STORED不是标准选项,但也被其他SQL实现使用。SQL标准没有指定生成列的存储方式。
LIKE 子句
虽然SQL标准存在LIKE子句,但是UXsinoDB接受的许多选项不在标准中,而且一些标准选项未被UXsinoDB实现。
WITH 子句
WITH子句是UXsinoDB的扩展;存储参数不在标准中。
表空间
UXsinoDB的表空间概念不是标准的一部分。因此,TABLESPACE和USING INDEX TABLESPACE子句是扩展。类型化表实现了SQL标准的子集。根据标准,类型化表具有与基础组合类型对应的列以及另一列,该列是“自引用列”。UXsinoDB不明确支持自引用列。
类型表
类型化表实现SQL标准的一个子集。根据标准,类型化表具有与底层组合类型对应的列,以及另一个“自引用列”。UXsinoDB不显式支持自引用列。
PARTITION BY 子句
PARTITION BY子句是UXsinoDB的扩展。
PARTITION OF 子句
PARTITION OF子句是UXsinoDB的扩展。
另请参阅
ALTER TABLE 、DROP TABLE、CREATE TABLE AS、CREATE TABLESPACE、CREATE TYPE
CREATE TABLE AS
CREATE TABLE AS —从查询结果定义一个新表
概要
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 ]
描述
CREATE TABLE AS创建一个表并填充数据,数据由SELECT命令计算得出。表的列名和数据类型与SELECT的输出列相关联(除非您通过提供新列名的显式列表来覆盖列名)。
CREATE TABLE AS与创建视图有些相似,但实际上是完全不同的:它创建一个新表并仅计算一次查询以初始化新表。新表不会跟踪查询源表的后续更改。相比之下,视图在每次查询时重新评估其定义的SELECT语句。
CREATE TABLE AS需要对用于表的模式具有CREATE特权。
参数
-
GLOBAL或LOCAL
为了兼容而被忽略。使用这些关键字已被弃用;有关详细信息,请参见CREATE TABLE。 -
TEMPORARY或TEMP
如果指定,则将表创建为临时表。请参见CREATE TABLE获取详细信息。 -
UNLOGGED
如果指定了,则创建的表将是非记录表。请参见CREATE TABLE获取详细信息。 -
IF NOT EXISTS
如果已经存在同名关系,则不会抛出错误;只会发出通知并保持表不变。 -
table_name
要创建的表的名称(可选模式限定符)。 -
column_name
新表中的列名。如果未提供列名,则从查询的输出列名中获取列名。 -
USING method
此可选子句指定用于存储新表内容的表访问方法;该方法需要是类型为TABLE的访问方法。如果未指定此选项,则为新表选择默认表访问方法。 -
WITH ( storage_parameter[=value] [, ... ])
此子句指定新表的可选存储参数;有关更多信息,请参见CREATE TABLE中的“存储参数”。为了向后兼容,表的WITH子句也可以包括OIDS=FALSE,以指定新表的行不应包含OID(对象标识符),不再支持OIDS=TRUE。 -
WITHOUT OIDS
这是声明表WITHOUT OIDS的向后兼容语法,不再支持创建带有OID的表。 -
ON COMMIT
可以使用ON COMMIT控制事务块结束时临时表的行为。有三个选项: -
PRESERVE ROWS
在事务结束时不采取任何特殊操作。这是默认行为。 -
DELETE ROWS在每个事务块结束时,将删除临时表中的所有行。实质上,在每个提交时都会自动执行TRUNCATE。 -
DROP当前事务块结束时,将删除临时表。 -
TABLESPACE tablespace_name
tablespace_name是表空间的名称。如果未指定,将查询default_tablespace或temp_tablespaces(如果表是临时表)中的表空间。 -
query
一个SELECT,TABLE 命令或VALUES命令,或运行准备好的SELECT,TABLE或VALUES查询的EXECUTE命令。 -
WITH [ NO ] DATA
此子句指定是否将查询生成的数据复制到新表中。如果不是,则仅复制表结构。默认情况下,将复制数据。
注释
此命令在功能上类似于SELECT INTO,但它更受欢迎,因为它不太可能与其他使用SELECT INTO语法的用法混淆。此外,CREATE TABLE AS提供了SELECT INTO提供的功能的超集。
示例
创建一个新表films_recent,其中只包含来自表films的最新条目:
CREATE TABLE films_recent AS
SELECT * FROM films WHERE date_prod >= '2002-01-01';
要完全复制表,还可以使用使用TABLE命令的简短形式:
CREATE TABLE films2 AS
TABLE films;
使用准备好的语句创建一个新的临时表films_recent,其中只包含来自表films的最新条目。新表将在提交时删除:
PREPARE recentfilms(date) AS
SELECT * FROM films WHERE date_prod > $1;
CREATE TEMP TABLE films_recent ON COMMIT DROP AS
EXECUTE recentfilms('2002-01-01');
兼容性
CREATE TABLE AS符合SQL标准。以下是非标准扩展:
-
标准要求在子查询子句周围加上括号;在UXsinoDB中,这些括号是可选的。
-
在标准中,
WITH [ NO ] DATA子句是必需的;在UXsinoDB中是可选的。 -
UXsinoDB以一种与标准非常不同的方式处理临时表;有关详细信息,请参见CREATE TABLE。
-
WITH子句是UXsinoDB的扩展;存储参数不在标准中。 -
表空间的UXsinoDB概念不是标准的一部分。因此,
TABLESPACE子句是一个扩展。
另请参阅
CREATE MATERIALIZED VIEW、CREATE TABLE、EXECUTE、SELECT、SELECT INTO、VALUES
CREATE TABLESPACE
CREATE TABLESPACE - 定义新的表空间
概要
CREATE TABLESPACE tablespace_name
[ OWNER { new_owner | CURRENT_USER | SESSION_USER } ]
LOCATION 'directory' [ ENCRYPTED ]
[ WITH ( tablespace_option = value [, ... ] ) ]
关键字ENCRYPTED只支持在安全模式下指定
描述
CREATE TABLESPACE注册一个新的集群级表空间。表空间名称必须与数据库集群中任何现有表空间的名称不同。
表空间允许超级用户定义一个备用位置,用于存放包含数据库对象(如表和索引)的数据文件。
具有适当权限的用户可以将tablespace_name传递给CREATE DATABASE、CREATE TABLE、CREATE INDEX或ADD CONSTRAINT,以使这些对象的数据文件存储在指定的表空间中。
警告
表空间不能独立于定义它的集群使用。
参数
-
tablespace_name
要创建的表空间的名称。名称不能以ux_开头,因为这样的名称保留给系统表空间。 -
user_name
将拥有表空间的用户的名称。如果省略,则默认为执行命令的用户。只有超级用户可以创建表空间,但他们可以将表空间的所有权分配给非超级用户。 -
directory
将用于表空间的目录。目录必须存在并且对于UXsinoDB服务器进程可读写。必须存在(CREATE TABLESPACE不会创建它),应该为空,并且必须由UXsinoDB系统用户拥有。目录必须由绝对路径名指定。 -
tablespace_option
要设置或重置的表空间参数。目前,唯一可用的参数是seq_page_cost、random_page_cost、effective_io_concurrency和maintenance_io_concurrency。为特定表空间设置这些值将覆盖规划器对从该表空间中的表读取页面的成本的通常估计,以及执行器的预取行为,就像同名的配置参数一样(参见seq_page_cost、random_page_cost、effective_io_concurrency、maintenance_io_concurrency)。如果一个表空间位于比其余I/O子系统更快或更慢的磁盘上,则这可能是有用的。
注意事项
表空间仅受支持符号链接的系统。
CREATE TABLESPACE无法在事务块内执行。
示例
要在文件系统位置/data/dbs创建表空间dbspace,请先使用操作系统工具创建目录并设置正确的所有权:
mkdir /data/dbs
chown uxdb:uxdb /data/dbs
然后在UXsinoDB中发出表空间创建命令:
CREATE TABLESPACE dbspace LOCATION '/data/dbs';
要创建由不同数据库用户拥有的表空间,请使用以下命令:
CREATE TABLESPACE indexspace OWNER genevieve LOCATION '/data/indexes';
兼容性
CREATE TABLESPACE是UXsinoDB的扩展。
另请参阅
CREATE DATABASE、CREATE TABLE、CREATE INDEX、DROP TABLESPACE、ALTER TABLESPACE
CREATE TEXT SEARCH CONFIGURATION
CREATE TEXT SEARCH CONFIGURATION — 定义新的文本搜索配置
概要
CREATE TEXT SEARCH CONFIGURATION name (
PARSER = parser_name |
COPY = source_config
)
描述
CREATE TEXT SEARCH CONFIGURATION创建新的文本搜索配置。文本搜索配置指定文本搜索解析器,该解析器可以将字符串分成标记,以及可用于确定哪些标记对于搜索是有用的字典。
如果仅指定解析器,则新的文本搜索配置最初没有从标记类型到字典的映射,因此将忽略所有单词。随后必须使用 ALTER TEXT SEARCH CONFIGURATION 命令创建映射以使配置有用。或者,可以复制现有的文本搜索配置。
如果给出模式名称,则在指定的模式中创建文本搜索配置。否则,将在当前模式中创建。
定义文本搜索配置的用户成为其所有者。
参数
-
name
要创建的文本搜索配置的名称。名称可以带有模式限定符。 -
parser_name
用于此配置的文本搜索解析器的名称。 -
source_config
要复制的现有文本搜索配置的名称。
注意事项
PARSER和COPY选项是互斥的,因为复制现有配置时,它的解析器选择也会被复制。
兼容性
SQL标准中没有CREATE TEXT SEARCH CONFIGURATION语句。
另请参阅
ALTER TEXT SEARCH CONFIGURATION ,DROP TEXT SEARCH CONFIGURATION
CREATE TEXT SEARCH DICTIONARY
CREATE TEXT SEARCH DICTIONARY — 定义一个新的文本搜索词典
概要
CREATE TEXT SEARCH DICTIONARY name (
TEMPLATE = template
[, option = value [, ... ]]
)
描述
CREATE TEXT SEARCH DICTIONARY创建一个新的文本搜索词典。文本搜索词典指定了一种识别有趣或无趣单词的方式以进行搜索。词典依赖于文本搜索模板,该模板指定实际执行工作的函数。通常,词典提供一些选项来控制模板函数的详细行为。
如果给出模式名称,则在指定的模式中创建文本搜索词典。否则,它将在当前模式中创建。
定义文本搜索词典的用户成为其所有者。
参数
-
name
要创建的文本搜索词典的名称。名称可以是模式限定的。 -
template
将定义此词典基本行为的文本搜索模板的名称。 -
option
要为此词典设置的特定于模板的选项的名称。 -
value
用于模板特定选项的值。如果值不是简单标识符或数字,则必须加引号(但如果您愿意,您总是可以引用它)。
选项可以以任何顺序出现。
示例
以下示例命令创建一个基于Snowball的词典。使用非标准的停用词列表创建文本搜索词典。
CREATE TEXT SEARCH DICTIONARY my_russian (
template = snowball,
language = russian,
stopwords = myrussian
);
兼容性
SQL标准中没有CREATE TEXT SEARCH DICTIONARY语句。
另请参阅
ALTER TEXT SEARCH DICTIONARY ,DROP TEXT SEARCH DICTIONARY
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 ]
)
描述
CREATE TEXT SEARCH PARSER创建新的文本搜索解析器。文本搜索解析器定义了一种将文本字符串分割为标记并为标记分配类型(类别)的方法。解析器本身并不特别有用,但必须与一些文本搜索字典一起绑定到文本搜索配置中,以用于搜索。
如果给出模式名称,则文本搜索解析器将在指定模式中创建。否则,它将在当前模式中创建。
您必须是超级用户才能使用CREATE TEXT SEARCH PARSER。(这个限制是因为错误的文本搜索解析器定义可能会混淆甚至崩溃服务器。)
参数
-
name
要创建的文本搜索解析器的名称。名称可以是模式限定的。 -
start_function
解析器的开始函数的名称。 -
gettoken_function
解析器的获取下一个标记函数的名称。 -
end_function
解析器的结束函数的名称。 -
lextypes_function
解析器的 lextypes 函数名称(返回其生成的令牌类型集的信息的函数名称)。 -
headline_function
解析器的标题函数名称(汇总一组令牌的函数)。
如果需要,函数名称可以是模式限定的。不给出参数类型,因为每种类型的函数的参数列表是预定的。除标题函数外,所有函数都是必需的。
参数可以以任何顺序出现,而不仅仅是上面显示的顺序。
兼容性
SQL标准中没有CREATE TEXT SEARCH PARSER语句。
另请参阅
ALTER TEXT SEARCH PARSER,DROP TEXT SEARCH PARSER
CREATE TEXT SEARCH TEMPLATE
CREATE TEXT SEARCH TEMPLATE — 定义新的文本搜索模板
概要
CREATE TEXT SEARCH TEMPLATE 名称 (
[ INIT = init_function , ]
LEXIZE = lexize_function
)
描述
CREATE TEXT SEARCH TEMPLATE创建新的文本搜索模板。文本搜索模板定义实现文本搜索字典的函数。模板本身并不有用,但必须实例化为字典才能使用。字典通常指定要给模板函数的参数。
如果给出模式名称,则在指定的模式中创建文本搜索模板。否则,它将在当前模式中创建。
您必须是超级用户才能使用CREATE TEXT SEARCH TEMPLATE。这个限制是因为错误的文本搜索模板定义可能会混淆甚至崩溃服务器。将模板与字典分开的原因是模板封装了定义字典的“不安全”方面。在定义字典时可以设置的参数对于非特权用户来说是安全的,因此创建字典不需要是特权操作。
参数
-
name
要创建的文本搜索模板的名称。名称可以是模式限定的。 -
init_function
模板的初始化函数的名称。 -
lexize_function
模板的词法分析函数的名称。
如果需要,函数名称可以是模式限定的。不给出参数类型,因为每种类型的函数的参数列表是固定的。Lexize函数是必需的,但init函数是可选的。
参数可以以任何顺序出现,而不仅仅是上面显示的那个。
兼容性
SQL标准中没有CREATE TEXT SEARCH TEMPLATE语句。
另请参阅
ALTER TEXT SEARCH TEMPLATE, DROP TEXT SEARCH TEMPLATE
CREATE TRANSFORM
CREATE TRANSFORM — 定义新的转换
概要
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 [, ...]) ]
);
描述
CREATE TRANSFORM定义新的转换。CREATE OR REPLACE TRANSFORM将创建一个新的转换或替换现有定义。
转换指定如何将数据类型适应到过程语言。例如,当使用PL/Python编写使用hstore类型的函数时,PL/Python没有先前的知识如何在Python环境中呈现hstore值。语言实现通常默认使用文本表示,但当关联数组或列表更合适时,这是不方便的。
转换指定两个函数:
-
一个从SQL环境转换类型到语言的“from SQL”函数。该函数将在使用该语言编写的函数的参数上调用。
-
一个从语言转换类型到SQL环境的“to SQL”函数。该函数将在使用该语言编写的函数的返回值上调用。
不需要提供这两个函数。如果未指定其中一个,则在必要时将使用语言特定的默认行为。(要完全防止某个方向的转换发生,您还可以编写一个总是出错的转换函数。)
要能够创建转换,您必须拥有并具有类型的USAGE权限,具有对使用的语言的EXECUTE权限,并且具有对使用的函数的EXECUTE权限。
USAGE权限在语言上,并且在指定的from-SQL和to-SQL函数上拥有和拥有EXECUTE权限(如果指定)。
参数
-
type_name
转换数据类型的名称。 -
lang_name
转换语言的名称。 -
from_sql_function_name[(argument_type[, ...])]
将类型从SQL环境转换为语言的函数名称。它必须接受一个类型为internal的参数,并返回类型为internal。实际参数将是转换的类型,函数应编写为如果是。(但是,不允许声明返回internal的SQL级函数,而没有至少一个类型为internal的参数。)实际返回值将是特定于语言实现的内容。如果未指定参数列表,则函数名称必须在其模式中唯一。 -
to_sql_function_name[(argument_type[, ...])]
将类型从语言转换为SQL环境的函数名称。它必须接受一个类型为internal的参数,并返回类型为转换的类型。实际参数值将是特定于语言实现的内容。如果未指定参数列表,则函数名称必须在其模式中唯一。
注释
使用DROP TRANSFORM删除转换。
示例
要为类型hstore和语言plpython3u创建转换,请首先设置类型和语言:
CREATE TYPE hstore ...;
CREATE EXTENSION plpython3u;
然后创建必要的函数:
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 plpython3u (
FROM SQL WITH FUNCTION hstore_to_plpython(internal),
TO SQL WITH FUNCTION plpython_to_hstore(internal)
);
实际上,这些命令将被包装在扩展中。
“contrib”部分包含许多提供转换的扩展,可以作为实际示例。
兼容性
这种形式的CREATE TRANSFORM是UXsinoDB扩展。SQL标准中有一个CREATE TRANSFORM命令,但它是用于将数据类型适应客户端语言的。UXsinoDB不支持该用法。
另请参阅
CREATE FUNCTION,CREATE LANGUAGE,CREATE TYPE, DROP TRANSFORM
CREATE TRIGGER
CREATE TRIGGER — 定义新触发器
概要
CREATE [ OR REPLACE ] [ 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 )
| DECLARE declaration_statements
BEGIN executable_statements EXCEPTION exception_handling_statements
END }
其中 event 可以是以下之一
INSERT
UPDATE [ OF column_name [, ... ] ]
DELETE
TRUNCATE
描述
CREATE TRIGGER创建新触发器。CREATE OR REPLACE TRIGGER将创建新触发器或替换现有触发器。触发器将与指定的表、视图或外部表相关联,并在执行特定操作时执行指定的函数function_name。
要替换现有触发器的当前定义,请使用CREATE OR REPLACE TRIGGER,指定现有触发器的名称和父表。所有其他属性都将被替换。
触发器可以指定在尝试对行执行操作之前(在检查约束和尝试INSERT、UPDATE或DELETE之前)触发操作;或在操作完成后(在检查约束和完成INSERT、UPDATE或DELETE后)触发操作;或代替操作(在视图上插入、更新或删除的情况下)。如果触发器在事件之前或代替事件触发,则触发器可以跳过操作。
触发器可以引用旧表和新表,以及过渡关系名称。触发器可以为每行或每个语句触发。
触发器可以在特定条件下触发,该条件由WHEN子句指定。
触发器可以是约束触发器或非约束触发器。约束触发器在违反表约束时触发,而非约束触发器在不违反表约束时触发。
对于当前行的操作,或更改正在插入的行(仅适用于INSERT和UPDATE操作)。如果触发器在事件之后触发,则包括其他触发器效果在内的所有更改都对触发器“可见”。标记为FOR EACH ROW的触发器将为操作修改的每一行调用一次。例如,影响10行的DELETE将导致目标关系上的任何ON DELETE触发器被调用10次,每次删除一行。相比之下,标记为FOR EACH STATEMENT的触发器仅对任何给定操作执行一次,无论它修改了多少行(特别是修改零行的操作仍将导致执行任何适用的FOREACH STATEMENT触发器)。
指定在触发器事件之前触发的触发器必须标记为FOR EACH ROW,并且只能在视图上定义。视图上的BEFORE和AFTER触发器必须标记为FOR EACH STATEMENT。
此外,可以定义触发器以触发TRUNCATE,但仅限于FOR EACH STATEMENT。
下表总结了可以在表、视图和外部表上使用哪些类型的触发器:
| 什么时候用 | 事件 | 行级 | 声明级别 |
|---|---|---|---|
| BEFORE | INSERT/UPDATE/DELETE | 表和外部表 | 表,视图和外部表 |
| BEFORE | TRUNCATE | — | 表 |
| AFTER | INSERT/UPDATE/DELETE | 表和外部表 | 表,视图和外部表 |
| AFTER | TRUNCATE | — | 表 |
| INSTEAD OF | INSERT/UPDATE/DELETE | 视图 | — |
| INSTEAD OF | TRUNCATE | — | — |
此外,触发器定义可以指定布尔值WHEN条件,该条件将被测试以确定是否应触发触发器。在行级触发器中,WHEN条件可以检查行的列的旧值或新值。语句级触发器也可以有WHEN条件,尽管该功能对它们不太有用,因为该条件不能引用表中的任何值。
如果为同一事件定义了多个相同类型的触发器,则它们将按名称的字母顺序进行触发。
当指定CONSTRAINT选项时,此命令将创建一个约束触发器。这与常规触发器相同。除了可以使用SET CONSTRAINTS来调整触发器触发的时间之外,约束触发器必须是普通表(而不是外部表)上的AFTER ROW触发器。它们可以在引发触发事件的语句结束时或包含事务结束时触发;在后一种情况下,它们被称为延迟触发器。可以使用SET CONSTRAINTS立即强制触发挂起的延迟触发器。约束触发器应在违反它们实现的约束时引发异常。
REFERENCING选项启用转换关系的收集,它们是包括当前SQL语句插入、删除或修改的所有行的行集。此功能使触发器能够看到语句的全局视图,而不仅仅是一行。此选项仅允许用于不是约束触发器的AFTER触发器;此外,如果触发器是UPDATE触发器,则不能指定column_name列表。只能为可以在UPDATE或DELETE上触发的触发器指定一次OLD TABLE;它创建一个包含语句更新或删除的所有行的before-images的转换关系。类似地,只能为可以在UPDATE或INSERT上触发的触发器指定一次NEW TABLE;它创建一个包含语句更新或插入的所有行的after-images的转换关系。
SELECT不修改任何行,因此无法创建SELECT触发器。规则和视图可能提供看似需要SELECT触发器的可行解决方案。
参数
-
name
新触发器的名称。这必须与同一表的任何其他触发器的名称不同。名称不能是模式限定的,触发器继承其表的模式。对于约束触发器,这也是使用SET CONSTRAINTS修改触发器行为时要使用的名称。 -
BEFORE
AFTER
INSTEAD OF
确定函数在事件之前、之后或代替事件调用。约束触发器只能指定为AFTER。 -
event
INSERT、UPDATE、DELETE或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
在触发器中用于此转换关系的(未限定的)名称。 -
FOR EACH ROW
FOR EACH STATEMENT
这指定触发器函数是否应针对触发事件影响的每一行触发一次,还是每个SQL语句只触发一次。如果没有指定任何一个,FOR EACH STATEMENT是默认值。只能为约束触发器指定FOR EACH ROW。 -
condition
一个布尔表达式,用于确定是否实际执行触发器函数。如果指定了WHEN,则只有在condition返回true时才会调用该函数。在FOR EACH ROW触发器中,WHEN条件可以通过写OLD/:OLD.column_name或NEW/:NEW.column_name来引用旧行值或新行值的列。当然,INSERT触发器不能引用OLD/:OLD,DELETE触发器不能引用NEW/:NEW。
INSTEAD OF触发器不支持WHEN条件。
目前,WHEN表达式不能包含子查询。
请注意,对于约束触发器,WHEN的评估条件不会被延迟,而是在行更新操作之后立即发生。如果条件不为真,则触发器不会被排队等待延迟执行。
-
function_name
一个用户提供的函数,声明为不带参数并返回类型为trigger,当触发器触发时执行。在CREATE TRIGGER的语法中,关键字FUNCTION和PROCEDURE是等效的,但是引用的函数必须是函数,而不是过程。这里使用关键字PROCEDURE是历史遗留问题,已经不推荐使用。 -
arguments
一个可选的逗号分隔的参数列表,当触发器执行时将提供给函数。这些参数是文本字符串常量。简单的名称和数字常量也可以写在这里,但它们都将被转换为字符串。请查看触发器函数的实现语言的描述,以了解如何在函数内访问这些参数;它可能与普通函数参数不同。 -
Declaration-statements
声明部分。 -
Executable-statements
执行部分。 -
Exception-handling-statements
异常处理部分。
注意事项
要在表上创建或替换触发器,用户必须具有表的TRIGGER权限。用户还必须具有触发器函数的EXECUTE权限。
使用DROP TRIGGER 删除触发器。
在分区表上创建行级触发器将导致在其现有分区的每个分区上创建一个相同的“克隆”触发器;以及稍后创建或附加的任何分区也将具有相同的触发器。如果子分区上已经存在具有冲突名称的触发器,则会发生错误,除非使用CREATE OR REPLACE TRIGGER,在这种情况下,该触发器将被替换为克隆触发器。当分区与其父分区分离时,其克隆触发器将被删除。
使用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条件不返回true时,不需要排队事件,也不需要在语句结束时重新获取行。如果触发器只需要针对少数行触发,则可以在修改许多行的语句中实现显著的加速。
在某些情况下,单个SQL命令可能会触发多种类型的触发器。例如,带有ON CONFLICT DO UPDATE子句的INSERT可能会导致插入和更新操作,因此将根据需要触发两种类型的触发器。提供给触发器的转换关系是特定于其事件类型的;因此,INSERT触发器只会看到插入的行,而UPDATE触发器只会看到更新的行。
由外键强制执行操作引起的行更新或删除,例如ON UPDATE CASCADE或ON DELETE SET NULL,被视为导致它们的SQL命令的一部分(请注意,此类操作永远不会被延迟)。将触发受影响表上的相关触发器,因此这提供了另一种SQL命令可能触发不直接匹配其类型的触发器的方式。在简单情况下,请求转换关系的触发器将把单个原始SQL命令引起的其表中的所有更改视为单个转换关系。但是,在存在请求转换关系的AFTER ROW触发器的情况下,将导致由单个SQL命令触发的外键强制执行操作被拆分为多个步骤,每个步骤都有自己的转换关系。在这种情况下,任何存在的语句级触发器都将在每个转换关系集的创建时触发一次,以确保触发器仅一次地看到每个受影响的行的转换关系。
对视图的语句级触发器仅在行级INSTEAD OF触发器处理视图的操作时触发。如果操作由INSTEAD规则处理,则规则发出的任何语句都将执行替换视图名称的原始语句,以便将触发器触发器的是替换语句中命名的表的触发器。类似地,如果视图是自动可更新的,则操作通过自动将语句重写为视图基表上的操作来处理,因此基表的语句级触发器是将被触发的触发器。
修改分区表或具有继承子项的表会触发附加到明确命名表的语句级触发器,但不会触发其分区或子表的语句级触发器。相反,行级触发器将在受影响的分区或子表中的行上触发,即使它们在查询中没有被明确命名。如果已使用REFERENCING子句定义了请求转换关系的语句级触发器,则所有受影响的分区或子表中都可以看到行的前后图像。在继承子项的情况下,行图像仅包括附加到触发器的表中存在的列。
目前,无法在分区或继承子表上定义具有转换关系的行级触发器。此外,分区表上的触发器可能不是INSTEAD OF。
目前,不支持将OR REPLACE选项用于约束触发器。
不建议在已经对触发器的表执行了更新操作的事务中替换现有触发器。触发器触发决策或部分触发决策可能已经被执行,这可能会导致不一致的结果。
已经做出的决定不会重新考虑,因此影响可能会令人惊讶。
有一些内置的触发器函数可以用来解决常见问题,而无需编写自己的触发器代码。
示例
每当表accounts的一行将要更新时,执行函数check_account_update:
CREATE TRIGGER check_update
BEFORE UPDATE ON accounts
FOR EACH ROW
EXECUTE FUNCTION check_account_update();
修改触发器定义,仅在UPDATE命令中指定列balance作为目标时才执行该函数:
CREATE OR REPLACE TRIGGER check_update
BEFORE UPDATE OF balance ON accounts
FOR EACH ROW
EXECUTE FUNCTION check_account_update();
仅在列balance实际更改值时才执行该函数:
CREATE TRIGGER check_update
BEFORE UPDATE ON accounts
FOR EACH ROW
WHEN (OLD.balance IS DISTINCT FROM NEW.balance)
EXECUTE FUNCTION check_account_update();
调用一个函数来记录accounts的更新,但仅在有变化时才记录:
CREATE TRIGGER log_update
AFTER UPDATE ON accounts
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE FUNCTION log_account_update();
每插入一行,就执行函数view_insert_row来将行插入视图下的表:
CREATE TRIGGER view_insert
INSTEAD OF INSERT ON my_view
FOR EACH ROW
EXECUTE FUNCTION view_insert_row();
每个语句都执行函数check_transfer_balances_to_zero,以确认transfer行的偏移量为零:
CREATE TRIGGER transfer_insert
AFTER INSERT ON transfer
REFERENCING NEW TABLE AS inserted
FOR EACH STATEMENT
EXECUTE FUNCTION check_transfer_balances_to_zero();
每行都执行函数check_matching_pairs,以确认同时对匹配对进行更改(由同一语句):
CREATE TRIGGER paired_items_update
AFTER UPDATE ON paired_items
REFERENCING NEW TABLE AS newtab OLD TABLE AS oldtab
FOR EACH ROW
EXECUTE FUNCTION check_matching_pairs();
将从一个表中删除的数据插入到另一个表中,如下所示。
CREATE TABLE student (id int PRIMARY KEY, name text, score number);
CREATE TABLE student_del (num int);
CREATE TRIGGER tri BEFORE DELETE ON student BEGIN insert into student_del values(1); END;
/
兼容性
UXsinoDB中的CREATE TRIGGER语句实现了SQL标准的一个子集。目前缺少以下功能:
-
虽然标准的
AFTER触发器使用REFERENCING子句指定了过渡表名称,但在FOR EACH ROW触发器中使用的行变量可能不会在REFERENCING子句中指定。它们以一种依赖于触发器函数所编写的语言的方式可用,但对于任何一种语言都是固定的。一些语言实际上的行为就像有一个REFERENCING子句,其中包含OLD ROW AS OLD NEW ROW AS NEW。 -
特定列的
UPDATE触发器,但是在过渡表中应该可见的行集取决于触发器的列列表。这在UXsinoDB中目前没有实现。 -
UXsinoDB仅允许执行用户定义的函数作为触发操作。标准允许执行许多其他SQL命令,例如
CREATE TABLE作为触发操作。通过创建执行所需命令的用户定义函数,这个限制不难解决。
标准允许使用过渡表与WHEN子句,但这些功能在UXsinoDB中不可用。
此外,CREATE TRIGGER语句的语法在不同的数据库管理系统中可能会有所不同。
SQL指定多个触发器应按创建时间顺序触发。UXsinoDB使用名称顺序,这被认为更方便。
SQL指定级联删除的BEFORE DELETE触发器在级联DELETE完成后触发。UXsinoDB的行为是BEFORE DELETE始终在删除操作之前触发,即使是级联操作也是如此。这被认为更一致。如果BEFORE触发器在引用操作引起的更新期间修改行或防止更新,则还存在非标准行为。这可能导致约束违规或存储的数据不符合引用约束。
使用OR为单个触发器指定多个操作的能力是SQL标准的UXsinoDB扩展。
为TRUNCATE触发器触发触发器的能力是SQL标准的UXsinoDB扩展,就像在视图上定义语句级触发器的能力一样。
CREATE CONSTRAINT TRIGGER是SQL标准的UXsinoDB扩展。OR REPLACE选项也是如此。
另请参阅
ALTER TRIGGER,DROP TRIGGER ,CREATE FUNCTION,SET CONSTRAINTS
CREATE TYPE
CREATE TYPE — 定义新的数据类型
概要
CREATE TYPE name { IS | AS} [OBJECT]
( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] )
CREATE TYPE name { IS | AS} ENUM
( [ 'label' [, ... ] ] )
CREATE TYPE name { IS | AS}AS RANGE (
SUBTYPE = subtype
[ , SUBTYPE_OPCLASS = subtype_operator_class ]
[ , COLLATION = collation ]
[ , CANONICAL = canonical_function ]
[ , SUBTYPE_DIFF = subtype_diff_function ]
[ , MULTIRANGE_TYPE_NAME = multirange_type_name ]
)
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 ]
[ , SUBSCRIPT = subscript_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 name
CREATE TYPE name { IS | AS}
{ TABLE | { VARRAY | VARYING ARRAY } ( size_limit ) } OF
data_type [ NOT NULL ]
描述
CREATE TYPE注册一个新的数据类型,以便在当前数据库中使用。定义类型的用户成为其所有者。
如果给出模式名称,则在指定模式中创建类型。否则,它将在当前模式中创建。类型名称必须与同一模式中任何现有类型或域的名称不同。(因为表具有关联的数据类型,所以类型名称还必须与同一模式中任何现有表的名称不同。)
如上面的语法所示,有六种形式的CREATE TYPE。它们分别创建组合类型、枚举类型、范围类型、基础类型、shell类型或者集合类型。下文将依次讨论前四种形式以及最后一种形式。shell类型只是一个稍后要定义的类型的占位符;它是通过除类型名称之外没有参数发出CREATE TYPE来创建的。在创建范围类型和基本类型时,需要 shell 类型作为前向引用,如这些部分中所讨论的那样。
组合类型
CREATE TYPE的第一种形式创建一个组合类型。组合类型由属性名称和数据类型列表指定。如果其数据类型是可排序的,则还可以指定属性的排序规则。组合类型本质上与表的行类型相同,但使用CREATE TYPE 避免了创建实际表的需要,当想要定义类型时。独立的组合类型很有用,例如作为函数的参数或返回类型。
要能够创建组合类型,您必须对所有属性类型具有 USAGE 权限。
枚举类型
CREATE TYPE 的第二种形式创建一个枚举类型。枚举类型采用引用标签的列表,每个标签必须少于 NAMEDATALEN 字节长(在标准的 UXsinoDB 构建中为 64字节)。(可以创建一个具有零个标签的枚举类型,但是这样的类型在使用 ALTER TYPE添加至少一个标签之前不能用于保存值。)
范围类型
CREATE TYPE 的第三种形式创建一个新的范围类型。
范围类型的 subtype 可以是任何具有关联 b-tree 操作符类的类型(以确定范围类型的值的排序)。通常使用子类型的默认b-tree 操作符类来确定排序;要使用非默认操作符类,请使用 subtype_opclass指定其名称。如果子类型是可排序的,并且您想在范围的排序中使用非默认排序规则,请使用collation 选项指定所需的排序规则。
可选的 canonical函数必须接受正在定义的范围类型的一个参数,并返回相同类型的值。这用于在适用时将范围值转换为规范形式。创建一个范围类型canonical函数有一些技巧,因为必须在声明范围类型之前定义它。为此,您必须首先创建一个shell类型,它是一个占位符类型,除了名称和所有者之外没有任何属性。这可以通过发出命令CREATE TYPE name 来完成,没有其他参数。然后,可以使用 shell类型作为参数和结果声明函数,最后使用相同的名称声明范围类型。这将自动用有效的范围类型替换shell 类型条目。
可选的 subtype_diff函数必须将两个 subtype类型的值作为参数,并返回表示两个给定值之间差异的double precision 值。虽然这是可选的,但提供它可以使范围类型的 GiST 索引的效率大大提高。
可选的multirange_type_name参数指定相应的多范围类型的名称。如果未指定,则将自动选择此名称,方法如下。如果范围类型名称包含子字符串range,则多范围类型名称是通过将范围子字符串替换为范围类型名称中的 multirange形成的。否则,多范围类型名称是通过在范围类型名称后附加_multirange 后缀形成的。
基本类型
CREATE TYPE的第四种形式创建新的基本类型(标量类型)。要创建新的基本类型,您必须是超级用户。(这个限制是因为错误的类型定义可能会混淆甚至崩溃服务器。)
参数可以以任何顺序出现,不仅仅是上面所示的顺序,大多数是可选的。在定义类型之前,必须注册两个或多个函数(使用 CREATE FUNCTION)。需要支持函数 input_function和 output_function,而函数receive_function、send_function、type_modifier_input_function、type_modifier_output_function、analyze_function和 subscript_function 是可选的。通常,这些函数必须用 C 或其他低级语言编写。
input_function将类型的外部文本表示转换为类型定义的运算符和函数使用的内部表示。output_function执行反向转换。输入函数可以声明为接受类型为 cstring 的一个参数,或者声明为接受类型为cstring、oid、integer 的三个参数。第一个参数是作为 C 字符串的输入文本,第二个参数是类型自己的OID(对于数组类型,它们接收其元素类型的 OID),第三个是目标列的 typmod(如果已知)(如果不知道,则将传递-1)。输入函数必须返回数据类型本身的值。通常,输入函数应声明为 STRICT;如果不是,则在读取 NULL 值时将使用NULL 作为第一个参数调用它。输入值。即使如此,该函数在这种情况下仍必须返回NULL,除非它引发错误。(这种情况主要用于支持域输入函数,这些函数可能需要拒绝NULL输入。)输出函数必须声明为接受新数据类型的一个参数。输出函数必须返回类型cstring。对于NULL值,不会调用输出函数。
可选的receive_function将类型的外部二进制表示转换为内部表示。如果未提供此函数,则该类型无法参与二进制输入。应选择便于转换为内部形式的二进制表示,同时具有合理的可移植性。(例如,标准整数数据类型使用网络字节顺序作为外部二进制表示,而内部表示在机器的本机字节顺序中。)接收函数应执行足够的检查以确保该值有效。接收函数可以声明为接受类型internal的一个参数,或者声明为接受类型internal、oid、integer的三个参数。第一个参数是指向包含接收的字节字符串的StringInfo缓冲区的指针;可选参数与文本输入函数相同。接收函数必须返回数据类型本身的值。通常,接收函数应声明为STRICT;如果没有,当读取NULL输入值时,它将使用NULL的第一个参数调用它。即使如此,该函数在这种情况下仍必须返回NULL,除非它引发错误。(这种情况主要用于支持域接收函数,这些函数可能需要拒绝NULL输入。)类似地,如果未提供send_function,则从内部表示转换为外部二进制表示。该类型无法参与二进制输出。发送函数必须声明为接受新数据类型的一个参数。发送函数必须返回类型bytea。对于NULL值,不会调用发送函数。
此时,您应该想知道如何声明输入和输出函数的结果或参数为新类型,因为必须在创建新类型之前创建它们。答案是,类型应首先定义为shell type,这是一个占位符类型,除了名称和所有者之外没有任何属性。这是通过发出命令CREATE TYPEname来完成的,不需要其他参数。然后,可以定义引用shell类型的C I/O函数。最后,使用完整定义的CREATETYPE替换shell条目,以获得完整的、有效的类型定义,之后可以正常使用新类型。
如果类型支持修饰符,即附加到类型声明的可选约束,例如char(5)或numeric(30,2),则需要可选的type_modifier_input_function和type_modifier_output_function。UXsinoDB允许用户定义的类型采用一个或多个简单的常量或标识符作为修饰符。但是,此信息必须能够被打包成一个单独的非负整数值,以便存储在系统目录中。type_modifier_input_function以cstring数组的形式传递声明的修饰符。它必须检查值的有效性(如果错误则抛出错误),如果它们正确,则返回单个非integer数,它将被存储在“typmod”列中。如果类型没有type_modifier_input_function,则会拒绝类型修饰符。type_modifier_output_function将内部整数typmod值转换回正确的形式以供用户显示。它必须返回一个cstring值,该值是要附加到类型名称的确切字符串,例如,numeric的函数可能返回(30,2)。如果默认的显示格式 就是只把存储的 typmod 整数值放在圆括号内,则允许省略 type_modifier_output_function。
可选的analyze_function执行特定于类型的统计信息收集,用于数据类型的列。默认情况下,ANALYZE将尝试使用类型的“equals”和“less-than”运算符收集统计信息,如果类型有默认的b-tree运算符类。对于非标量类型,此行为可能不适合,因此可以通过指定自定义分析函数来覆盖它。分析函数必须声明为接受类型为internal的单个参数,并返回一个boolean结果。有关分析函数的详细API,请参见src/include/commands/vacuum.h。
可选的subscript_function允许在SQL命令中对数据类型进行下标。指定此函数不会导致将该类型视为“真实的”数组类型;例如,它不会成为ARRAY[]构造的结果类型的候选项。但是,如果对该类型的值进行下标是提取数据的自然表示法,则可以编写subscript_function来定义其含义。下标函数必须声明为接受类型为internal的单个参数,并返回一个internal结果,该结果是指向实现下标的方法(函数)的结构的指针。有关下标函数的详细API,请参见src/include/nodes/subscripting.h。阅读src/backend/utils/adt/arraysubs.c中的数组实现或contrib/hstore/hstore_subs.c中的更简单的代码也可能很有用。
虽然新类型的内部表示的详细信息只有I/O函数和其他函数才知道,但是必须向UXsinoDB声明其内部表示的几个属性。其中最重要的是internallength。基本数据类型可以是固定长度的,在这种情况下,internallength是一个正整数,或者是可变长度的,通过将internallength设置为VARIABLE来表示。(在内部,这是通过将typlen设置为-1来表示。)所有可变长度类型的内部表示都必须以一个4字节的整数开头,该整数给出该类型值的总长度。(请注意,长度字段通常是编码的,直接访问它是不明智的。)
可选标志PASSEDBYVALUE表示该数据类型的值是按值传递而不是按引用传递的。按值传递的类型必须是固定长度的,其内部表示不能大于Datum类型的大小(在某些机器上为4字节,在其他机器上为8字节)。
alignment参数指定所需数据类型的存储对齐方式。允许的值等于1、2、4或8字节边界上的对齐方式。请注意,可变长度类型必须具有至少4的对齐方式,因为它们必然包含一个int4作为它们的第一个组件。
storage参数允许选择可变长度数据类型的存储策略。(对于固定长度类型,只允许plain。)plain指定该类型的数据始终存储在行内且不压缩。extended指定系统首先尝试压缩长数据值,如果仍然太长,则将该值移出主表行。external允许将值移出主表,但系统不会尝试压缩它。main允许压缩,但不鼓励将值移出主表。(具有此存储策略的数据项仍可能移出主表,如果没有其他方法使行适合,则会优先保留在主表中,而不是extended和external项。)
除plain之外的所有storage值都意味着数据类型的函数可以处理已经toasted的值。特定的其他值仅确定可烤数据类型的默认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子句携带排序信息。实际上利用排序信息的函数的实现取决于它们的实现;仅仅标记类型为可排序类型并不会自动发生这种情况。
集合类型
第六种形式的CREATE TYPE创建集合类型。
CRETE TYPE ... TABLE创建的是一个嵌套表类型;CREATE TYPE ... { VARRAY | VARYING ARRAY } 创建的是一个可变数组类型。
可选的NOT NULL表示集合类型中的元素是否可为NULL。
数组类型
每当创建用户定义类型时,UXsinoDB会自动创建一个相关的数组类型,其名称由元素类型的名称前缀下划线组成,如果必要,则截断该名称以使其长度小于NAMEDATALEN字节。(如果生成的名称与现有类型名称冲突,则重复此过程,直到找到一个非冲突名称。)此隐式创建的数组类型是可变长度的,并使用内置的输入和输出函数array_in和array_out。此外,该类型是系统在诸如ARRAY[]之类的构造中使用的用户定义类型。数组类型跟踪其元素类型的所有者或模式中的任何更改,并在元素类型被删除时删除。
您可能会合理地问为什么有一个ELEMENT选项,如果系统会自动创建正确的数组类型。使用ELEMENT的主要情况是当您正在创建一个固定长度类型,该类型在内部实际上是一组相同的东西的数组,并且您想要允许直接通过下标访问这些东西,除了您计划为整个类型提供的任何操作之外。例如,类型point表示为仅两个浮点数,可以使用point[0]和point[1]访问这些数。请注意,此功能仅适用于内部形式完全是一系列相同的固定长度字段的固定长度类型。由于历史原因(即,这显然是错误的,但是它太过常见,所以不能更改),在某些情况下,ELEMENT选项还可以用于指定数组类型的输入和输出函数。
CREATE TYPE命令用于创建新的数据类型,包括组合类型、枚举类型、范围类型和基本类型的别名。可以指定数据类型的各种属性,例如数据类型的名称、元素类型、默认值、输入/输出函数等。
组合类型是由多个命名属性组成的类型。每个属性都有一个名称和一个数据类型。枚举类型是由一组命名常量组成的类型。范围类型是由两个值组成的类型,表示一个范围。基本类型的别名是对现有基本类型的引用,可以用于简化数据类型的使用。
对于固定长度的数组类型,下标从零开始,而不是从一开始,这是无法更改的。指定SUBSCRIPT选项允许对数据类型进行下标操作,即使系统不将其视为数组类型。实际上,对于没有编写SUBSCRIPT的固定长度类型,实现了上述行为的是SUBSCRIPT处理程序函数raw_array_subscript_handler,该函数会自动使用ELEMENT。
在指定自定义SUBSCRIPT函数时,不需要指定ELEMENT,除非SUBSCRIPT处理程序函数需要查询typelem以查找要返回的内容。请注意,指定ELEMENT会导致系统假定新类型包含或在某种物理上依赖于元素类型;因此,例如,如果存在依赖类型的列,则不允许更改元素类型的属性。
参数
-
name
要创建的类型的名称(可选模式限定)。 -
attribute_name
组合类型的属性(列)的名称。 -
data_type
要成为组合类型的一个列或集合类型的元素类型的现有数据类型的名称。 -
collation
要与组合类型的列或范围类型关联的现有排序规则的名称。 -
label
表示枚举类型一个值的文本标签的字符串文字。 -
subtype
范围类型将表示范围的元素类型的名称。 -
subtype_operator_class
子类型的B-tree操作符类的名称。 -
canonical_function
范围类型的规范化函数的名称。 -
subtype_diff_function
子类型的差异函数的名称。 -
multirange_type_name
相应的多范围类型的名称。 -
input_function
将数据从类型的外部文本形式转换为其内部形式的函数的名称。 -
output_function
将数据从类型的内部形式转换为其外部文本形式的函数的名称。 -
receive_function
将数据从类型的外部二进制形式转换为其内部形式的函数的名称。 -
send_function
将数据从类型的内部形式转换为其外部二进制形式的函数的名称。 -
type_modifier_input_function
将类型的修饰符数组转换为内部形式的函数名称。 -
type_modifier_output_function
将类型的修饰符的内部形式转换为外部文本形式的函数名称。 -
analyze_function
执行数据类型的统计分析的函数名称。 -
subscript_function
定义数据类型值的下标操作的函数名称。 -
internallength
指定新类型的内部表示的字节数的数字常量。默认情况下,它是可变长度的。 -
alignment
数据类型的存储对齐要求。如果指定,必须是char、int2、int4或double;默认值为int4。 -
storage
数据类型的存储策略。如果指定,必须是plain、external、extended或main;默认值为plain。 -
like_type
新类型将具有与现有数据类型相同的表示形式。将从该类型复制internallength、passedbyvalue、alignment和storage的值,除非在此CREATE TYPE命令的其他位置明确指定覆盖。 -
category
此类型的类别代码(单个 ASCII 字符)。默认值为'U',表示“用户定义类型”。您还可以选择其他ASCII 字符以创建自定义类别。 -
preferred
如果此类型是其类型类别中的首选类型,则为 True,否则为 False。默认值为False。非常小心地在现有类型类别中创建新的首选类型,因为这可能会导致行为上的惊人变化。 -
default
数据类型的默认值。如果省略,则默认值为 null。 -
element
正在创建的类型是一个数组;这指定了数组元素的类型。 -
delimiter
在由此类型制成的数组中,在值之间使用的分隔符字符。 -
collatable
如果此类型的操作可以使用排序信息,则为 True。默认值为 False。 -
size_limit
可变数组的元素个数限制,目前暂无实际作用。范围:0~2147483647
注释
因为一旦创建了数据类型,就没有对其使用的限制,创建基本类型或范围类型等同于授予在类型定义中提到的函数的公共执行权限。这通常不是类型定义中有用的函数的问题。但是,在设计需要在将其转换为或从外部形式转换时使用“秘密”信息的类型时,您可能需要三思而后行。
在UXsinoDB之前的版本,生成的数组类型的名称始终是元素类型的名称,前面加上一个下划线字符(_)。(因此,类型名称的长度限制比其他名称少一个字符。)虽然这通常仍然是这种情况,但在最大长度名称或与以下划线开头的用户类型名称冲突的情况下,数组类型名称可能会有所不同。编写依赖于此约定的代码因此已被弃用。相反,请使用ux_type。typarray查找与给定类型相关联的数组类型。
建议避免使用以下划线开头的类型和表名称。虽然服务器将更改生成的数组类型名称以避免与用户给定名称冲突,但仍存在混淆的风险,特别是对于可能假定以下划线开头的类型名称始终表示数组的旧客户端软件。
创建新基本类型的方法是首先创建其输入函数。在这种方法中,UXsinoDB将首先看到新数据类型的名称作为输入函数的返回类型。在这种情况下,将隐式创建shell类型,然后可以在其余I/O函数的定义中引用它。这种方法仍然有效,但已被弃用,并且可能在将来的某个版本中被禁止。此外,为了避免在函数定义中出现简单的拼写错误而意外地使目录中充满shell类型,只有在输入函数以C编写时才会以这种方式创建shell类型。
创建集合类型时,目前只支持基础的数据类型和用户自定义的类型(集合类型除外)作为其数据元素的类型。
示例
此示例创建一个组合类型并在函数定义中使用它:
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);
此示例创建基本数据类型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
);
此示例创建一个大型对象类型,并在表定义中使用它:
CREATE TYPE bigobj (
INPUT = lo_filein, OUTPUT = lo_fileout, INTERNALLENGTH = VARIABLE );
CREATE TABLE big_objs ( id integer, obj bigobj );
这个例子创建了一个可变数组类型varray_type和嵌套表类型nesttable_type,它们的元素类型都是INT类型。
CREATE TYPE varray_type IS VARRAY(10) OF INT;
CREATE TYPE nesttable_type AS TABLE OF INT;
兼容性
创建组合类型的第一种形式的CREATE TYPE命令符合SQL标准;创建集合类型的第六种形式的CREATE TYPE,兼容ORACLE的创建集合类型命令。其他的形式都是UXDB扩展。
SQL 标准中的CREATE TYPE语句还定义了其他未在UXsinoDB中实现的形式。创建具有零个属性的组合类型的能力是UXsinoDB特定的偏差(类似于CREATE TABLE中的相同情况)。
参见
ALTER TYPE、CREATE DOMAIN、CREATE FUNCTION 和 DROP TYPE
CREATE USER
CREATE USER — 定义新的数据库角色
概要
CREATE USER name [ [ WITH ] option [ ... ] ]
其中 option 可以是:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
| IN ROLE role_name [, ...]
| IN GROUP role_name [, ...]
| ROLE role_name [, ...]
| ADMIN role_name [, ...]
| USER role_name [, ...]
| SYSID uid
描述
CREATE USER 现在是 CREATE ROLE 的别名。唯一的区别是当命令拼写为 CREATE USER 时,默认情况下假定为 LOGIN,而当命令拼写为CREATE ROLE 时假定为 NOLOGIN。
兼容性
CREATE USER 语句是 UXsinoDB 的扩展。SQL标准将用户的定义留给实现。
另请参阅
CREATE USER MAPPING
CREATE USER MAPPING — 定义用户到外部服务器的映射
概述
CREATE USER MAPPING [ IF NOT EXISTS ] FOR { user_name | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC }
SERVER server_name
[ OPTIONS ( option 'value' [ , ... ] ) ]
描述
CREATE USER MAPPING定义用户到外部服务器的映射。用户映射通常封装了外部数据包装器使用的连接信息,以及外部服务器封装的信息,以访问外部数据资源。
外部服务器的所有者可以为该服务器的任何用户创建用户映射。此外,如果已授予用户在服务器上的 USAGE权限,则用户可以为自己的用户名创建用户映射。
参数
-
IF NOT EXISTS
如果给定用户到给定外部服务器的映射已经存在,则不会抛出错误。在这种情况下,会发出通知。请注意,不能保证现有的用户映射与将创建的用户映射相似。 -
user_name
映射到外部服务器的现有用户的名称。CURRENT_ROLE、CURRENT_USER和USER与当前用户的名称匹配。当指定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)标准。
另请参阅
ALTER USER MAPPING,DROP USER MAPPING,CREATE FOREIGN DATA WRAPPER,CREATE SERVER
CREATE VIEW
CREATE VIEW —定义新视图
概要
CREATE [ OR REPLACE ] [ [ TEMP | TEMPORARY ] [ RECURSIVE ] ] | [ FORCE | NOFORCE ] VIEW name [ ( column_name [, ...] ) ]
[ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
AS query
[ WITH [ CASCADED | LOCAL ] CHECK OPTION [ CONSTRAINT [ cons_name ]] ]
描述
CREATE VIEW 定义一个查询的视图。视图不是物理材料化的。相反,每次在查询中引用视图时,都会运行查询。
CREATE OR REPLACE VIEW类似,但如果同名视图已经存在,则会被替换。新查询必须生成与现有视图查询生成的相同列(即相同的列名、相同的顺序和相同的数据类型),但可以在列表末尾添加其他列。产生输出列的计算可能完全不同。
如果给出模式名称(例如,CREATE VIEW myschema.myview...),则视图将在指定的模式中创建。否则,它将在当前模式中创建。临时视图存在于一个特殊的模式中,因此在创建临时视图时不能给出模式名称。视图的名称必须与同一模式中的任何其他关系(表、序列、索引、视图、材料化视图或外部表)的名称不同。
CREATE FORCE VIEW创建基表不存在,或者与基表结构不符的视图。
CREATE NOFORCE VIEW同普通视图。
参数
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或noforce
force可以创建基表不存在,或者与基表结构不符的视图;noforce同默认语法。
force、noforce语法仅影响创建的行为,和创建之后的行为无关。
force语法不支持临时视图、递归视图。
force语法允许创建视图或者修改基表时暂时将视图置为无效状态,基表重新被创建则恢复正常。
查询视图有效状态的两个方式,如下所示。
-
select * from sys.user_objects where object_name = '视图名';
-
select * from ux_viewdef;
ux_viewdef是用于记录视图定义相关内容的系统表。
-
name
要创建的视图名称(可选模式限定)。 -
column_name
视图列的可选名称列表。如果未给出,则从查询中推断列名。 -
WITH (view_option_name [=view_option_value] [, ...])
此子句指定视图的可选参数;支持以下参数: -
check_option(enum)
此参数可以是local或cascaded,等同于指定WITH [CASCADED | LOCAL] CHECK OPTION(见下文)。 -
security_barrier(boolean)
如果视图旨在提供行级安全性,则应使用此选项。 -
security_invoker(boolean)
此选项导致基础基本关系与视图用户的特权而不是视图所有者进行检查。有关完整详细信息,请参见下面的注释。
所有上述选项都可以使用ALTER VIEW更改现有视图。
-
query
提供视图的列和行的SELECT或VALUES命令。 -
WITH [CASCADED | LOCAL] CHECK OPTION
此选项控制自动更新视图的行为。当指定此选项时,将检查视图定义条件(即,将检查新行以确保它们通过视图可见)的视图上的INSERT和UPDATE命令。如果不是,则更新将被拒绝。如果未指定CHECK OPTION,则允许视图上的INSERT和UPDATE命令创建通过视图不可见的行。支持以下检查选项: -
LOCAL
新行仅根据视图本身中定义的条件进行检查。不会检查基础视图上定义的任何条件(除非它们也指定了CHECK OPTION)。 -
CASCADED
新行将根据视图和所有基础视图的条件进行检查。如果指定了CHECK OPTION,并且没有指定LOCAL或CASCADED,则假定为CASCADED。
CHECK OPTION 不能与 RECURSIVE 视图一起使用。
请注意,CHECK OPTION 仅支持自动更新的视图,并且没有 INSTEAD OF触发器或规则。如果在基础视图上定义了可自动更新的视图,并且该基础视图具有INSTEAD OF 触发器,则可以使用 LOCAL CHECK OPTION 来检查自动更新视图上的条件,但是具有 INSTEAD OF触发器的基础视图上的条件将不会被检查(级联检查选项不会级联到可触发器更新的视图,并且在可触发器更新的视图上直接定义的任何检查选项都将被忽略)。如果视图或其任何基础关系具有导致INSERT 或 UPDATE 命令被重写的 INSTEAD 规则,则在重写的查询中将忽略所有检查选项,包括在具有INSTEAD 规则的关系上定义的任何检查。
CONSTRAINT cons_name
指定视图约束名称。
注释
使用DROP VIEW语句来删除视图。
请注意,视图的列的名称和类型将按您想要的方式分配。例如:
CREATE VIEW vista AS SELECT 'Hello World';
是不好的形式,因为列名默认为 ?column?;此外,列数据类型默认为text,这可能不是您想要的。在视图结果中的字符串文字的更好样式是:
CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
默认情况下,对视图中引用的基础关系的访问权限由视图所有者的权限确定。在某些情况下,这可以用于提供对基础表的安全但受限制的访问。但是,并非所有视图都能防止篡改。
如果视图具有设置为 true 的 security_invoker属性,则对基础关系的访问权限由执行查询的用户的权限确定,而不是视图所有者的权限。因此,安全调用者视图的用户必须具有视图及其基础关系的相关权限。
如果任何基础关系是安全调用者视图,则将视为直接从原始查询访问。因此,安全调用者视图将始终使用当前用户的权限检查其基础关系,即使从没有security_invoker属性的视图中访问它也是如此。
如果任何基础关系中启用了行级安全性,则默认情况下会应用视图所有者的行级安全策略,并且对于那些策略引用的任何其他关系的访问权限由视图所有者的权限决定。但是,如果视图security_invoker设置为true,则将使用调用用户的策略和权限,就像直接从查询中使用视图引用基础关系一样。在视图中调用的函数与直接从使用视图的查询中调用的函数相同。因此,视图的用户必须具有调用视图使用的所有函数的权限。
视图中的函数使用执行查询的用户或函数所有者的权限执行。这取决于这些函数是否定义为SECURITY INVOKER或SECURITY DEFINER。因此,例如,在视图中直接调用CURRENT_USER将始终返回调用用户,而不是视图所有者。这不受视图的security_invoker设置的影响,因此将security_invoker设置为false的视图不等同于SECURITY DEFINER函数,这些概念不应混淆。
创建或替换视图的用户必须在视图查询中引用的任何模式上具有USAGE权限,以便在这些模式中查找引用的对象。但是,请注意,此查找仅在创建或替换视图时发生。因此,即使是安全调用者视图,视图的用户仅需要在包含视图的模式上具有USAGE权限,而不需要在视图查询中引用的模式上具有USAGE权限。当在现有视图上使用CREATE OR REPLACE VIEW时,仅更改视图的定义SELECT规则,以及任何WITH ( ...)参数和其CHECK OPTION。其他视图属性,包括所有权、权限和非SELECT规则,保持不变。您必须拥有视图才能替换它(这包括成为拥有角色的成员)。
更新视图
简单视图自动可更新:系统将允许在视图上使用INSERT、UPDATE和DELETE语句,就像在常规表上一样。如果视图满足以下所有条件,则自动更新视图:
-
视图的
FROM列表中必须恰好有一个条目,该条目必须是一个表或另一个可更新视图。 -
视图定义在顶层不包含
WITH、DISTINCT、GROUP BY、HAVING、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),但在实践中,触发器更容易理解和正确使用。
请注意,执行视图上的插入、更新或删除操作的用户必须具有视图相应的插入、更新或删除权限。此外,默认情况下,视图的所有者必须具有基础关系的相关权限,而执行更新的用户不需要基础关系的任何权限。但是,如果视图的security_invoker设置为true,则执行更新的用户而不是视图所有者必须具有基础关系的相关权限。
示例
创建一个包含所有喜剧电影的视图:
CREATE VIEW comedies AS
SELECT *
FROM films
WHERE kind = 'Comedy';
这将创建一个视图,其中包含在视图创建时在film表中的列。虽然使用了*来创建视图,但是稍后添加到表中的列将不会成为视图的一部分。
创建一个带有LOCAL CHECK OPTION的视图:
CREATE VIEW universal_comedies AS
SELECT *
FROM comedies
WHERE classification = 'U'
WITH LOCAL CHECK OPTION;
这将创建一个基于comedies视图的视图,仅显示kind = 'Comedy'和classification ='U'的电影。如果新行没有classification ='U',则任何尝试在视图中INSERT或UPDATE行都将被拒绝,但是电影kind将不会被检查。
创建一个带有CASCADED CHECK OPTION的视图:
CREATE VIEW ux_comedies AS
SELECT *
FROM comedies
WHERE classification = 'UX'
WITH CASCADED CHECK OPTION;
这将创建一个视图,检查新行的kind和classification。
创建一个包含可更新和不可更新列的视图:
CREATE VIEW comedies AS
SELECT f.*,
country_code_to_name(f.country_code) AS country,
(SELECT avg(r.rating)
FROM user_ratings r
WHERE r.film_id = f.id) AS avg_rating
FROM films f
WHERE f.kind = 'Comedy';
此视图将支持INSERT、UPDATE和DELETE。所有来自films表的列都将是可更新的,而计算列country和avg_rating将是只读的。
创建一个由数字1到100组成的递归视图:
CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
VALUES (1)
UNION ALL
SELECT n+1 FROM nums_1_100 WHERE n < 100;
请注意,尽管递归视图的名称在此CREATE中是模式限定的,但其内部自引用没有模式限定。这是因为隐式创建的CTE的名称不能是模式限定的。
兼容性
CREATE OR REPLACE VIEW是UXsinoDB语言扩展。临时视图的概念也是如此。WITH ( ...)子句也是扩展,安全屏障视图和安全调用者视图也是扩展。
另请参阅
ALTER VIEW、DROP VIEW、CREATE MATERIALIZED VIEW
DEALLOCATE
DEALLOCATE — 释放预处理语句
概要
DEALLOCATE [ PREPARE ] { name | ALL }
描述
DEALLOCATE 用于释放先前预处理的 SQL 语句。如果您没有显式释放预处理语句,则在会话结束时将释放它。
有关预处理语句的更多信息,请参见PREPARE。
参数
-
PREPARE
此关键字将被忽略。 -
name
要释放的预处理语句的名称。 -
ALL
释放所有预处理语句。
兼容性
SQL 标准包括一个 DEALLOCATE 语句,但仅用于嵌入式SQL。
另请参阅
DECLARE
DECLARE — 定义游标
概要
DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ]
CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
描述
DECLARE允许用户创建游标,用于从较大的查询中检索一小部分行。创建游标后,可以使用FETCH从中获取行。
注意
本页描述了在SQL命令级别上使用游标的用法。如果您正在尝试在PL/uxSQL函数内使用游标,则规则不同。
参数
-
name
要创建的游标的名称。 -
BINARY
使游标返回二进制数据而不是文本格式。 -
ASENSITIVE
INSENSITIVE
游标灵敏度确定在声明游标后在同一事务中对底层数据进行的更改是否在游标中可见。INSENSITIVE表示它们不可见,ASENSITIVE表示行为是实现相关的。第三种行为SENSITIVE,表示这些更改在游标中可见,不可用于UXsinoDB。在UXsinoDB中,所有游标都是不敏感的;因此,这些关键字没有效果,仅用于与SQL 标准兼容。
将INSENSITIVE与FOR UPDATE或FOR SHARE一起指定是错误的。
-
SCROLL
NO SCROLL
SCROLL指定光标可以以非顺序方式(例如向后)检索行。根据查询执行计划的复杂性,指定SCROLL可能会对查询的执行时间产生性能损失。NO SCROLL指定光标无法以非顺序方式检索行。默认情况下,在某些情况下允许滚动;这与指定SCROLL不同。有关详细信息,请参见下面的DECLARE中的“注释”。 -
WITH HOLD
WITHOUT HOLD
WITH HOLD指定事务成功提交后,可以继续使用创建它的光标。WITHOUT HOLD指定光标无法在创建它的事务之外使用。如果未指定WITHOUTHOLD或WITH HOLD,则WITHOUT HOLD是默认值。
关键字 ASENSITIVE、BINARY、INSENSITIVE 和 SCROLL 可以以任何顺序出现。
注释
普通光标以文本格式返回数据,与 SELECT 产生的格式相同。BINARY选项指定光标应以二进制格式返回数据。这减少了服务器和客户端的转换工作量,但需要更多的程序员工作来处理平台相关的二进制数据格式。例如,如果查询从整数列返回值为1,则默认光标将返回字符串 1,而二进制光标将返回包含该值的内部表示形式的 4字节字段(以大端字节顺序)。
应谨慎使用二进制光标。许多应用程序,包括uxsql,未准备好处理二进制光标,并期望数据以文本格式返回。
注意
当客户端应用程序使用“扩展查询”协议发出 FETCH命令时,绑定协议消息指定数据是以文本还是二进制格式检索的。此选择覆盖了光标的定义方式。因此,在使用扩展查询协议时,二进制光标的概念已过时,任何光标都可以视为文本或二进制。
除非指定了 WITH HOLD,否则此命令创建的光标只能在当前事务中使用。因此,DECLARE 不带 WITH HOLD在事务块之外是无用的:光标仅在语句完成时存活。因此,如果在事务块之外使用此类命令,则UXsinoDB报告错误。请使用BEGIN和COMMIT命令来控制事务。
如果指定了WITH HOLD,并且创建游标的事务成功提交,则该游标可以继续被同一会话中的后续事务访问。(但如果创建事务被中止,则游标将被删除。)使用WITH HOLD创建的游标在显式执行CLOSE命令或会话结束时关闭。在当前实现中,由持有游标表示的行将被复制到临时文件或内存区域中,以便它们在后续事务中仍然可用。
当查询包括FOR UPDATE或FOR SHARE时,不能指定WITH HOLD。
在定义将用于向后获取的游标时,应指定SCROLL选项。这是SQL标准所要求的。但是,为了与早期版本兼容,UXsinoDB将允许在没有SCROLL的情况下进行向后获取,如果游标的查询计划足够简单,不需要额外的开销来支持它。但是,建议应用程序开发人员不要依赖于从未使用SCROLL创建的游标进行向后获取。如果指定了NO SCROLL,则无论如何都不允许向后获取。
当查询包括FOR UPDATE或FOR SHARE时,也不允许向后获取;因此,在这种情况下不能指定SCROLL。
注意
如果滚动游标调用任何易失性函数,则可能会产生意外结果。当重新获取以前获取的行时,函数可能会被重新执行,从而导致与第一次不同的结果。对于涉及易失性函数的查询,最好指定NO SCROLL。如果不可行,一种解决方法是声明游标SCROLL WITH HOLD并在从中读取任何行之前提交事务。这将强制游标的整个输出被实例化到临时存储中,以便易失性函数对每行仅执行一次。
如果游标的查询包括FOR UPDATE或FOR SHARE,则返回的行在第一次获取时被锁定,就像使用这些选项的常规SELECT 命令一样。此外,返回的行将是最新版本。
注意
通常建议在游标打算与UPDATE ... WHERE CURRENT OF或DELETE ... WHERE CURRENT OF一起使用时使用FOR UPDATE。使用FOR UPDATE可以防止其他会话在获取行和更新行之间更改行。如果没有FOR UPDATE,则如果在创建游标后更改了行,则后续的WHERE CURRENT OF命令将无效。
使用FOR UPDATE的另一个原因是,如果游标查询不包括FOR UPDATE,则后续的WHERE CURRENT OF可能会失败,如果游标查询包括FOR UPDATE或FOR SHARE,则不允许向后获取;因此,在这种情况下不能指定SCROLL。不符合 SQL 标准的“简单可更新”规则(特别是,游标必须仅引用一个表且不使用分组或ORDER BY)。不简单可更新的游标可能会工作,也可能不工作,这取决于计划选择的细节;因此,在最坏的情况下,应用程序可能在测试中工作,然后在生产中失败。如果指定了FOR UPDATE,则保证游标可更新。
不使用WHERE CURRENT OF的FOR UPDATE的主要原因是如果需要游标可滚动或与并发更新隔离(即继续显示旧数据)。如果这是一个要求,请密切注意上面显示的警告。
SQL标准仅为嵌入式SQL中的游标提供规定。UXsinoDB服务器不实现游标的OPEN语句;当声明游标时,游标被认为是打开的。但是,UXsinoDB的嵌入式SQL预处理器ECUX支持标准SQL游标约定,包括涉及DECLARE和OPEN语句的约定。
您可以通过查询ux_cursors系统视图来查看所有可用的游标。
示例
声明游标:
DECLARE liahona CURSOR FOR SELECT * FROM films;
有关游标用法的更多示例,请参见FETCH。
兼容性
SQL标准仅允许在嵌入式SQL和模块中使用游标。UXsinoDB允许交互式使用游标。
根据SQL标准,对不敏感游标进行的UPDATE ... WHERE CURRENT OF和DELETE ... WHERE CURRENT OF语句所做的更改在同一游标中可见。UXsinoDB 将这些语句视为所有其他数据更改语句一样,即在不敏感游标中不可见。
二进制游标是UXsinoDB的扩展。
另请参阅
DELETE
DELETE — 删除表中的行
概要
[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE [ FROM ] [ ONLY ] table_name [ * ] [ [ AS ] alias ]
[ USING from_item [, ...] ]
[ WHERE condition | WHERE CURRENT OF cursor_name ]
[ ORDER BY column_name [ LIMIT limit_count ] ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
DELETE table_name [ * ] [ [ AS ] alias ]
FROM from_item [, ...]
[ WHERE condition ]
描述
DELETE 从指定的表中删除满足 WHERE 子句的行。如果没有 WHERE 子句,则效果是删除表中的所有行。结果是一个有效但为空的表。
DELETE不加FROM功能与delete from功能相同。
提示
TRUNCATE提供了一种更快的机制来从表中删除所有行。
使用其他数据库中的表中的信息删除表中的行有两种方法:使用子查询或在 USING 子句中指定其他表。哪种技术更合适取决于具体情况。
可选的RETURNING子句使DELETE基于实际删除的每行计算并返回值。可以计算使用表的列或在USING中提到的其他表的列的任何表达式。RETURNING列表的语法与SELECT的输出列表相同。
您必须对表具有DELETE权限才能从中删除,以及对USING子句中的任何表或在condition中读取其值的任何表具有SELECT权限。
一般需要在WHERE子句中指定条件来删除对应的记录,条件语句可以使用AND或OR运算符来指定一个或多个。
参数
-
with_query
WITH子句允许您指定一个或多个子查询,这些子查询可以在DELETE查询中通过名称引用。有关详细信息,请参见SELECT 。 -
table_name
要从中删除行的表的名称(可选模式限定符)。如果在表名之前指定了ONLY,则仅从指定的表中删除匹配的行。如果未指定ONLY,则还将从继承自指定表的任何表中删除匹配的行。可选地,在表名后可以指定*,以明确表示包括后代表。 -
alias
目标表的替代名称。提供别名时,它完全隐藏了表的实际名称。例如,给定DELETE FROM foo AS f,则DELETE语句的其余部分必须将此表称为f而不是foo。 -
from_item
表达式允许其他表的列出现在WHERE条件中。这使用与SELECT 语句的FROM子句相同的语法;例如,可以指定表名的别名。不要将目标表重复作为from_item,除非您希望设置自连接(在这种情况下,它必须在from_item中以别名出现)。 -
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 命令将返回一个命令标记,格式如下:
DELETE count
其中 count是删除的行数。
DELETE 命令用于从表中删除行。如果 DELETE 命令没有带 WHERE 子句,则将删除表中的所有行。否则,将删除满足WHERE 子句的行。
如果 DELETE 命令成功执行,则返回一个指示删除行数的消息。请注意,当通过 BEFORE DELETE触发器抑制删除时,删除的行数可能小于匹配 condition 的行数。如果count为 0,则查询未删除任何行(这不被视为错误)。
如果 DELETE 命令包含 RETURNING 子句,则结果类似于包含在 RETURNING 列表中定义的列和值上计算的删除行的SELECT 语句。
注释
UXsinoDB 允许您通过在 USING 子句中指定其他表来引用 WHERE条件中的其他表的列。例如,要删除由给定制片人制作的所有电影,可以执行以下操作:
DELETE FROM films USING producers
WHERE producer_id = producers.id AND producers.name = 'foo';
这里实际上发生的是 films 和 producers 之间的连接,所有成功连接的 films行都将被标记为删除。这种语法不是标准的。更标准的方法是:
DELETE FROM films
WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');
在某些情况下,连接样式比子选择样式更容易编写或更快执行。
mysql模式下,from_item部分出现JOIN子句时,表别名应该只在语句的from_item部分声明,在其它地方进行引用,且要删除的目标必须在from_item部分出现,否则将报错。出现JOIN子句时,DELETE删除数据的表现和mysql数据库相同。
示例
删除所有电影,但不包括音乐片:
DELETE FROM films WHERE kind <> 'Musical';
清空表 films:
DELETE FROM films;
删除已完成的任务,并返回已删除行的完整详细信息:
DELETE FROM tasks WHERE status = 'DONE' RETURNING *;
删除光标 c_tasks 当前所在的 tasks 行:
DELETE FROM tasks WHERE CURRENT OF c_tasks;
按照id排序后删除满足条件的前三条记录,如下所示。
delete from test where id<10 order by id limit 3
兼容性
该命令符合 SQL 标准,但 USING 和 RETURNING 子句是 UXsinoDB 扩展,使用 WITH 与DELETE 的能力也是如此。
另请参阅
DISCARD
DISCARD — 丢弃会话状态
概要
DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP }
描述
DISCARD 释放与数据库会话相关的内部资源。该命令用于部分或完全重置会话状态。有几个子命令用于释放不同类型的资源;DISCARD ALL 变体包含所有其他变体,并且还重置其他状态。
参数
-
PLANS
释放所有缓存的查询计划,强制重新计划在下次使用相关准备好的语句时发生。 -
SEQUENCES
丢弃所有缓存的序列相关状态,包括currval()/lastval()信息和尚未被nextval()返回的任何预分配序列值。(有关预分配序列值的说明,请参见CREATE SEQUENCE。) -
TEMPORARY或TEMP
删除当前会话中创建的所有临时表。 -
ALL
释放与当前会话相关的所有临时资源,并将会话重置为其初始状态。目前,这与执行以下语句序列具有相同的效果:
CLOSE ALL;
SET SESSION AUTHORIZATION DEFAULT;
RESET ALL;
DEALLOCATE ALL;
UNLISTEN *;
SELECT ux_advisory_unlock_all();
DISCARD PLANS;
DISCARD TEMP;
DISCARD SEQUENCES;
注意事项
DISCARD ALL 不能在事务块内执行。
兼容性
DISCARD 是 UXsinoDB 的扩展。
DO
DO — 执行匿名代码块
概要
DO [ LANGUAGE lang_name ] code
[ DECLARE [ declare_section ] ]
BEGIN
execution_section
END;
/
描述
DO 执行一个匿名代码块,或者说是一个过程语言中的临时匿名函数。DECLARE与DO执行匿名块语法的区别:语法上相当于DO执行匿名块语法只保留了code部分,功能上一致。
该代码块被视为没有参数的函数体,返回 void。它被解析并执行一次。
可选的 LANGUAGE 子句可以在代码块之前或之后编写。
参数
-
code
要执行的过程语言代码。必须将其指定为字符串文字,就像在CREATE FUNCTION中一样。建议使用美元引用的文字。 -
lang_name
编写代码的过程语言的名称。如果省略,则默认为pluxsql。 -
declare_section
声明变量,包括变量名和类型,例如“var int”。 -
execution_section
匿名块中要执行的语句。
注意事项
要使用的过程语言必须已通过 CREATE EXTENSION 安装到当前数据库中。pluxsql 是默认安装的,但其他语言不是。
用户必须具有过程语言的 USAGE 权限,或者如果语言是不受信任的,则必须是超级用户。这与在语言中创建函数的权限要求相同。
如果在事务块中执行 DO,则过程代码无法执行事务控制语句。只有在自己的事务中执行 DO 才允许事务控制语句。
当没有LANGUAGE lang_name指定语言时,选择default_pl_language参数配置的语言,默认值为pluxsql。
示例
授予角色 webuser 中模式 public 中的所有视图的所有权限:
DO $$DECLARE r record;
BEGIN
FOR r IN SELECT table_schema, table_name FROM information_schema.tables
WHERE table_type = 'VIEW' AND table_schema = 'public'
LOOP
EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser';
END LOOP;
END$$;
DECLARE VAR INT;
BEGIN
SELECT COUNT(*) INTO VAR FROM UX_CLASS;
RAISE NOTICE ‘%’, VAR;
END;
/
兼容性
SQL 标准中没有DO语句
另请参阅
DROP ACCESS METHOD
DROP ACCESS METHOD — 删除访问方法
概要
DROP ACCESS METHOD [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP ACCESS METHOD 删除现有的访问方法。只有超级用户才能删除访问方法。
参数
-
IF EXISTS
如果访问方法不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有访问方法的名称。 -
CASCADE
自动删除依赖于访问方法的对象(例如操作符类、操作符族和索引),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于访问方法,则拒绝删除访问方法。这是默认设置。
示例
删除访问方法heptree:
DROP ACCESS METHOD heptree;
兼容性
DROP ACCESS METHOD 是 UXsinoDB 的扩展。
另请参阅
DROP AGGREGATE
DROP AGGREGATE —删除聚合函数
概要
DROP AGGREGATE [ IF EXISTS ] name ( aggregate_signature ) [, ...] [ CASCADE | RESTRICT ]
其中 aggregate_signature 为:
* |
[ argmode ] [ argname ] argtype [ , ... ] |
[ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ]
描述
DROP AGGREGATE 用于删除现有的聚合函数。要执行此命令,当前用户必须是聚合函数的所有者。
参数
-
IF EXISTS
如果聚合函数不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有聚合函数的名称(可选模式限定)。 -
argmode
参数的模式:IN或VARIADIC。如果省略,则默认为IN。 -
argname
参数的名称。请注意,DROP AGGREGATE实际上不会关注参数名称,因为只需要参数数据类型即可确定聚合函数的标识。 -
argtype
聚合函数操作的输入数据类型。要引用零参数聚合函数,请在参数规范列表中写入*。要引用有序集聚合函数,请在直接和聚合参数规范之间写入ORDER BY。 -
CASCADE
自动删除依赖于聚合函数的对象(例如使用它的视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何视图依赖于它,则仅删除该聚合函数,跳过删除依赖它的视图,但是将依赖它的视图置为无效状态。这是默认设置。
注释
有关引用有序集聚合的替代语法,请参见ALTER AGGREGATE 。
示例
要删除类型为integer的聚合函数myavg:
DROP AGGREGATE myavg(integer);
要删除假设集聚合函数myrank, 它接受任意数量的排序列和匹配列表的直接参数:
DROP AGGREGATE myrank(VARIADIC "any" ORDER BY VARIADIC "any");
要在一个命令中删除多个聚合函数:
DROP AGGREGATE myavg(integer), myavg(bigint);
兼容性
SQL标准中没有DROP AGGREGATE语句。
另请参阅
ALTER AGGREGATE ,CREATE AGGREGATE
DROP CAST
DROP CAST —删除一个转换
概要
DROP CAST [ IF EXISTS ] (source_type AS target_type) [ CASCADE | RESTRICT ]
描述
DROP CAST 用于删除先前定义的转换。
要删除一个转换,您必须拥有源数据类型或目标数据类型的所有权。这些权限与创建转换所需的权限相同。
参数
-
IF EXISTS
如果转换不存在,则不会抛出错误。在这种情况下,会发出通知。 -
source_type
转换的源数据类型的名称。 -
target_type
转换的目标数据类型的名称。 -
CASCADE
RESTRICT
这些关键字没有任何作用,因为没有转换的依赖关系。
示例
要删除从类型 text 到类型 int 的转换:
DROP CAST (text AS int);
兼容性
DROP CAST 命令符合 SQL 标准。
另请参阅
DROP COLLATION
DROP COLLATION — 删除排序规则
概要
DROP COLLATION [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP COLLATION删除先前定义的排序规则。要删除排序规则,必须拥有该排序规则。
参数
-
IF EXISTS
如果排序规则不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
排序规则的名称。排序规则名称可以是模式限定的。 -
CASCADE
自动删除依赖于排序规则的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于排序规则,则拒绝删除排序规则。这是默认设置。
示例
要删除名为german的排序规则:
DROP COLLATION german;
兼容性
DROP COLLATION 命令符合 SQL 标准,除了 IF EXISTS 选项是 UXsinoDB 的扩展之外。
另请参阅
ALTER COLLATION,CREATE COLLATION
DROP CONVERSION
DROP CONVERSION — 删除转换
概要
DROP CONVERSION [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP CONVERSION 用于删除先前定义的转换。要删除转换,必须拥有该转换。
参数
-
IF EXISTS
如果转换不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
转换的名称。转换名称可以是模式限定的。 -
CASCADE
RESTRICT
这些关键字没有任何效果,因为没有依赖于转换。
示例
要删除名为myname的转换:
DROP CONVERSION myname;
兼容性
SQL标准中没有DROP CONVERSION语句,但有一个DROP TRANSLATION语句,与UXsinoDB中的CREATE CONVERSION语句类似。
另请参阅
ALTER CONVERSION,CREATE CONVERSION
DROP DATABASE
DROP DATABASE — 删除数据库
概要
DROP DATABASE [ IF EXISTS ] name [ [ WITH ] ( option [, ...] ) ]
其中 option 可以是:
FORCE
描述
DROP DATABASE用于删除数据库。它会删除数据库的目录和数据,并移除数据库的目录项。只有数据库所有者才能执行此命令。在连接到目标数据库时,无法执行此命令(请连接到uxdb 或其他数据库来执行此命令)。此外,如果其他用户连接到目标数据库,除非使用下面描述的 FORCE选项,否则此命令将失败。
DROP DATABASE 无法撤销。请谨慎使用!
参数
-
IF EXISTS
如果数据库不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的数据库的名称。 -
FORCE
尝试终止所有连接到目标数据库的现有连接。如果目标数据库中存在已准备好的事务、活动的逻辑复制插槽或订阅,则不会终止。
如果当前用户没有终止其他连接的权限,则此操作将失败。所需权限与ux_terminate_backend相同。如果我们无法终止连接,则此操作也将失败。
注意事项
无法在事务块内执行 DROP DATABASE 命令。
在连接到目标数据库时,无法执行此命令。因此,使用程序 dropdb 可能更方便。
使用dropdb命令的包装器代替此命令。
兼容性
SQL标准中没有DROP DATABASE语句。
另请参阅
DROP DATABASE LINK
DROP DATABASE LINK — 删除数据库链接
概要
DROP DATABASE LINK [ IF EXISTS ] [schema.]linkname
描述
删除数据库链接,UXDB数据库实现CREATE/DROP DATABASE LINK相关语法及功能支持场景参见CREATE DATABASE LINK。
参数
[schema.]linkname
dblink 名称,对于私有dblink,可以切换到对于的schema下去删除,也可以指定schema.linkname来删除。
DROP DOMAIN
DROP DOMAIN — 删除域
概要
DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP DOMAIN 用于删除域。只有域的所有者才能删除它。
参数
-
IF EXISTS
如果域不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有域的名称(可选架构限定)。 -
CASCADE
自动删除依赖于该域的对象(例如表列),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于该域,则拒绝删除该域。这是默认值。
示例
要删除域box:
DROP DOMAIN box;
兼容性
该命令符合SQL标准,但IF EXISTS选项是UXsinoDB的扩展。
另请参阅
DROP EVENT TRIGGER
DROP EVENT TRIGGER — 删除事件触发器
概要
DROP EVENT TRIGGER [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP EVENT TRIGGER 用于删除现有的事件触发器。要执行此命令,当前用户必须是事件触发器的所有者。
参数
-
IF EXISTS
如果事件触发器不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的事件触发器的名称。 -
CASCADE
自动删除依赖于触发器的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于触发器,则拒绝删除触发器。这是默认值。
示例
销毁触发器snitch:
DROP EVENT TRIGGER snitch;
兼容性
SQL标准中没有DROP EVENT TRIGGER语句。
另请参阅
CREATE EVENT TRIGGER,ALTER EVENT TRIGGER
DROP EXTENSION
DROP EXTENSION — 删除扩展
概要
DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP EXTENSION 从数据库中删除扩展。删除扩展会导致其成员对象和其他明确依赖的例程(参见ALTER ROUTINE, DEPENDS ON EXTENSION extension_name 操作)也被删除。
您必须拥有该扩展才能使用DROP EXTENSION。
参数
-
IF EXISTS
如果扩展不存在,则不会引发错误。在这种情况下会发出通知。 -
name
已安装扩展的名称。 -
CASCADE
自动删除依赖于该扩展的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
此选项会防止删除指定的扩展,如果除这些扩展、其成员和明确依赖的例程之外还有其他对象依赖它们。这是默认设置。
示例
要从当前数据库中删除扩展hstore:
DROP EXTENSION hstore;
如果hstore的任何对象在数据库中正在使用,例如如果任何表具有hstore类型的列,则此命令将失败。添加CASCADE选项以强制删除这些依赖对象。
兼容性
DROP EXTENSION 是 UXsinoDB 的一个扩展。
另请参阅
CREATE EXTENSION,ALTER EXTENSION
DROP FOREIGN DATA WRAPPER
DROP FOREIGN DATA WRAPPER — 删除外部数据包装器
概要
DROP FOREIGN DATA WRAPPER [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP FOREIGN DATA WRAPPER 用于删除现有的外部数据包装器。要执行此命令,当前用户必须是外部数据包装器的所有者。
参数
-
IF EXISTS
如果外部数据包装器不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有外部数据包装器的名称。 -
CASCADE
自动删除依赖于外部数据包装器的对象(例如外部表和服务器),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于外部数据包装器,则拒绝删除外部数据包装器。这是默认设置。
示例
删除外部数据包装器dbi:
DROP FOREIGN DATA WRAPPER dbi;
兼容性
DROP FOREIGN DATA WRAPPER 符合 ISO/IEC 9075-9 (SQL/MED)。IF EXISTS 子句是UXsinoDB 的扩展。
另请参阅
CREATE FOREIGN DATA WRAPPER,ALTER FOREIGN DATA WRAPPER
DROP FOREIGN TABLE
DROP FOREIGN TABLE — 删除外部表
概要
DROP FOREIGN TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP FOREIGN TABLE 用于删除外部表。只有外部表的所有者才能删除它。
参数
-
IF EXISTS
如果外部表不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的外部表的名称(可选带模式)。 -
CASCADE
自动删除依赖于外部表的对象(例如视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于外部表,则拒绝删除外部表。这是默认设置。
示例
要销毁两个外部表 films 和 distributors:
DROP FOREIGN TABLE films, distributors;
兼容性
此命令符合 ISO/IEC 9075-9 (SQL/MED) 标准,但标准仅允许一次命令删除一个外部表, 除了 IF EXISTS选项外,这是 UXsinoDB 的扩展。
另请参阅
ALTER FOREIGN TABLE ,CREATE FOREIGN TABLE
DROP FUNCTION
DROP FUNCTION —删除函数
概要
DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
[ CASCADE | RESTRICT ]
描述
DROP FUNCTION用于删除现有函数的定义。执行此命令的用户必须是函数的所有者。必须指定函数的参数类型,因为可能存在具有相同名称和不同参数列表的多个不同函数。
参数
-
IF EXISTS
如果函数不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有函数的名称(可选模式限定)。如果未指定参数列表,则名称必须在其模式中唯一。 -
argmode
参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。请注意,DROP FUNCTION实际上不会关注OUT参数,因为只需要输入参数即可确定函数的标识。因此,只需列出IN、INOUT和VARIADIC参数即可。 -
argname
参数的名称。请注意,DROP FUNCTION实际上不会关注参数名称,因为只需要参数数据类型即可确定函数的标识。 -
argtype
函数参数的数据类型(可选模式限定),如果有的话。 -
CASCADE
自动删除依赖于该函数的对象(例如操作符或触发器),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何视图依赖于它,则仅删除该函数,跳过删除依赖它的视图,但是将依赖它的视图置为无效状态。这是默认设置。
示例
此命令删除平方根函数:
DROP FUNCTION sqrt(integer);
在一个命令中删除多个函数:
DROP FUNCTION sqrt(integer), sqrt(bigint);
如果函数名称在其模式中是唯一的,则可以在不带参数列表的情况下引用它:
DROP FUNCTION update_employee_salaries;
请注意,这与以下命令不同:
DROP FUNCTION update_employee_salaries();
它引用具有零个参数的函数,而第一个变体可以引用具有任意数量的参数(包括零)的函数,只要名称是唯一的。
兼容性
此命令符合SQL标准,并具有以下UXsinoDB扩展:
-
标准只允许一次删除一个函数。
-
IF EXISTS选项 -
指定参数模式和名称的能力
另请参阅
CREATE FUNCTION、ALTER FUNCTION、DROP PROCEDURE、DROP ROUTINE
DROP GROUP
DROP GROUP — 删除数据库角色
概要
DROP GROUP [ IF EXISTS ] name [, ...]
描述
DROP GROUP现在是 DROP ROLE的别名。
兼容性
SQL标准中没有DROP GROUP语句。
另请参阅
DROP INDEX
DROP INDEX —删除索引
概要
DROP INDEX [ CONCURRENTLY ] [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP INDEX 从数据库系统中删除现有的索引。要执行此命令,您必须是索引的所有者。
参数
CONCURRENTLY
在不锁定索引表的并发选择、插入、更新和删除的情况下删除索引。普通的DROP INDEX会在表上获取一个ACCESS EXCLUSIVE锁,阻塞其他访问,直到索引删除完成。使用此选项,命令将等待冲突事务完成。
使用此选项时需要注意几个注意事项。只能指定一个索引名称,不支持CASCADE选项(因此,支持UNIQUE或PRIMARY KEY约束的索引无法以此方式删除)。此外,可以在事务块内执行常规的DROP INDEX命令,但不能执行DROP INDEX CONCURRENTLY。最后,分区表上的索引不能使用此选项删除。
对于临时表,DROP INDEX始终是非并发的,因为没有其他会话可以访问它们,非并发索引删除更便宜。
-
IF EXISTS
如果索引不存在,则不抛出错误。在这种情况下,会发出通知。 -
name
要删除的索引的名称(可选模式)。 -
CASCADE
自动删除依赖于该索引的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于它,则拒绝删除索引。这是默认设置。
示例
此命令将删除索引title_idx:
DROP INDEX title_idx;
兼容性
DROP INDEX是 UXsinoDB语言扩展。在SQL标准中没有索引的规定。
另请参阅
DROP LANGUAGE
DROP LANGUAGE — 删除过程语言
概要
DROP [ PROCEDURAL ] LANGUAGE [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP LANGUAGE 用于删除之前注册的过程语言的定义。您必须是超级用户或语言的所有者才能使用DROP LANGUAGE。
注意
多数过程语言已成为“扩展”,因此应使用 DROP EXTENSION而不是 DROP LANGUAGE来删除它们。
参数
-
IF EXISTS
如果语言不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有过程语言的名称。 -
CASCADE
自动删除依赖于该语言的对象(例如该语言中的函数),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于该语言,则拒绝删除该语言。这是默认设置。
示例
此命令将删除过程语言 plsample:
DROP LANGUAGE plsample;
兼容性
SQL 标准中没有 DROP LANGUAGE 语句。
另请参阅
ALTER LANGUAGE,CREATE LANGUAGE
DROP MATERIALIZED VIEW
DROP MATERIALIZED VIEW — 删除材料化视图
概要
DROP MATERIALIZED VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP MATERIALIZED VIEW 用于删除现有的材料化视图。要执行此命令,您必须是材料化视图的所有者。
参数
-
IF EXISTS
如果材料化视图不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
要删除的材料化视图的名称(可选架构限定符)。 -
CASCADE
自动删除依赖于材料化视图的对象(例如其他材料化视图或常规视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于材料化视图,则拒绝删除材料化视图。这是默认设置。
示例
此命令将删除名为order_summary的材料化视图:
DROP MATERIALIZED VIEW order_summary;
兼容性
DROP MATERIALIZED VIEW 是UXsinoDB的扩展功能。
另请参阅
CREATE MATERIALIZED VIEW,ALTER MATERIALIZED VIEW,REFRESH MATERIALIZED VIEW
DROP OPERATOR
DROP OPERATOR —删除一个操作符
概要
DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
描述
DROP OPERATOR 从数据库系统中删除一个现有的操作符。要执行此命令,您必须是操作符的所有者。
参数
-
IF EXISTS
如果操作符不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有操作符的名称(可选模式限定符)。 -
left_type
操作符左操作数的数据类型;如果操作符没有左操作数,则写入NONE。 -
right_type
操作符右操作数的数据类型。 -
CASCADE
自动删除依赖于操作符的对象(例如使用它的视图),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于操作符,则拒绝删除操作符。这是默认值。
示例
删除类型为integer的幂运算符a^b:
DROP OPERATOR ^ (integer, integer);
删除类型为bit的按位补码前缀运算符~b:
DROP OPERATOR ~ (none, bit);
一次删除多个操作符:
DROP OPERATOR ~ (none, bit), ^ (integer, integer);
兼容性
SQL标准中没有DROP OPERATOR语句。
另请参阅
CREATE OPERATOR,ALTER OPERATOR
DROP OPERATOR CLASS
DROP OPERATOR CLASS — 删除运算符类
概要
DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
描述
DROP OPERATOR CLASS 用于删除现有的运算符类。要执行此命令,您必须是运算符类的所有者。
DROP OPERATOR CLASS 不会删除类引用的任何运算符或函数。如果有任何依赖于运算符类的索引,您需要指定 CASCADE才能完成删除。
参数
-
IF EXISTS
如果运算符类不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有运算符类的名称(可选模式限定符)。 -
index_method
运算符类所用的索引访问方法的名称。 -
CASCADE
自动删除依赖于运算符类的对象(如索引),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于运算符类,则拒绝删除运算符类。这是默认设置。
注意事项
DROP OPERATOR CLASS 不会删除包含该类的运算符族, 即使该族中没有其他内容(特别是在运算符族是由 CREATE OPERATOR CLASS 隐式创建的情况下)。空运算符族是无害的,但为了整洁起见,您可能希望使用 DROP OPERATOR FAMILY 删除该族;或者最好一开始就使用DROP OPERATOR FAMILY。
示例
删除B-tree操作符类widget_ops:
DROP OPERATOR CLASS widget_ops USING btree;
如果存在使用操作符类的任何现有索引,则此命令将无法成功。添加CASCADE以与操作符类一起删除这些索引。
兼容性
SQL标准中没有DROP OPERATOR CLASS语句。
另请参阅
ALTER OPERATOR CLASS,CREATE OPERATOR CLASS,DROP OPERATOR FAMILY
DROP OPERATOR FAMILY
DROP OPERATOR FAMILY —删除操作符族
概要
DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
描述
DROP OPERATOR FAMILY 用于删除现有的操作符族。要执行此命令,您必须是操作符族的所有者。
DROP OPERATOR FAMILY包括删除操作符族中包含的任何操作符类,但不会删除操作符族引用的任何操作符或函数。如果有任何依赖于操作符族中的操作符类的索引,则需要指定CASCADE 才能完成删除。
参数
-
IF EXISTS
如果操作符族不存在,则不会抛出错误。在这种情况下,会发出通知。 -
name
现有操作符族的名称(可选模式限定符)。 -
index_method
操作符族所用的索引访问方法的名称。 -
CASCADE
自动删除依赖于操作符族的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于操作符族,则拒绝删除操作符族。这是默认设置。
示例
删除 B 树操作符族 float_ops:
DROP OPERATOR FAMILY float_ops USING btree;
如果存在使用操作符族中的操作符类的现有索引,则此命令将无法成功。添加 CASCADE 以删除与操作符族一起使用的这些索引。
兼容性
SQL标准中没有DROP OPERATOR FAMILY语句。
另请参阅
ALTER OPERATOR FAMILY、CREATE OPERATOR FAMILY、ALTER OPERATOR CLASS、CREATE OPERATOR CLASS、DROPOPERATOR CLASS
DROP OWNED**
DROP OWNED — 删除数据库角色拥有的数据库对象
概要
DROP OWNED BY { name | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]
描述
DROP OWNED删除当前数据库中由指定角色拥有的所有对象。同时,也会撤销这些角色在当前数据库或共享对象(如数据库、表空间、配置参数)上授予的任何权限。
参数
-
name
要删除其对象并撤销其权限的角色名称。 -
CASCADE
自动删除依赖于受影响对象的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果任何其他数据库对象依赖于受影响对象之一,则拒绝删除该角色拥有的对象。这是默认设置。
注意事项
DROP OWNED 经常用于准备删除一个或多个角色。由于 DROP OWNED只影响当前数据库中的对象,通常需要在包含要删除角色拥有的对象的每个数据库中执行此命令。
使用 CASCADE 选项可能会使命令递归到其他用户拥有的对象。
REASSIGN OWNED命令是一种替代方法,它重新分配一个或多个角色拥有的所有数据库对象的所有权。但是,REASSIGN OWNED 不处理其他对象的权限。
角色拥有的数据库和表空间不会被删除。
兼容性
DROP OWNED命令是UXsinoDB的扩展。
另请参阅
DROP POLICY
DROP POLICY — 从表中删除行级安全策略
概要
DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
描述
DROP POLICY 从表中删除指定的策略。请注意,如果为表删除了最后一个策略,并且该表仍通过 ALTER TABLE启用了行级安全,则将使用默认拒绝策略。无论该表是否存在表的策略,都可以使用 ALTER TABLE ...DISABLE ROW LEVEL SECURITY 来禁用表的行级安全。
参数
-
IF EXISTS
如果策略不存在,则不会引发错误。在这种情况下会发出通知。 -
name
要删除的策略的名称。 -
table_name
策略所在的表的名称(可选模式限定符)。 -
CASCADE
RESTRICT
这些关键字没有任何效果,因为没有策略的依赖关系。
示例
要从名为 my_table 的表中删除名为 p1 的策略:
DROP POLICY p1 ON my_table;
兼容性
DROP POLICY 是 UXsinoDB 的扩展。
另请参阅
DROP PROCEDURE
DROP PROCEDURE —删除存储过程
概要
DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
[ CASCADE | RESTRICT ]
描述
DROP PROCEDURE 用于删除一个或多个已存在的存储过程的定义。要执行此命令,用户必须是存储过程的所有者。通常需要指定存储过程的参数类型,因为同名但参数列表不同的多个存储过程可能存在。
参数
-
IF EXISTS
如果存储过程不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
现有存储过程的名称(可选模式限定符)。 -
argmode
参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN(但请参见下文)。 -
argname
参数的名称。请注意,DROP PROCEDURE实际上不会关注参数名称,因为只有参数数据类型用于确定存储过程的标识。 -
argtype
存储过程参数的数据类型(可选模式限定符)。有关详细信息,请参见下文。 -
CASCADE
自动删除依赖于存储过程的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于该过程,则拒绝删除该过程。这是默认设置。
注释
如果只有一个给定名称的过程,则可以省略参数列表。在这种情况下,也可以省略括号。
在 UXsinoDB 中,只需列出输入(包括 INOUT)参数即可,因为不允许同名的两个例程共享相同的输入参数列表。此外,DROP命令实际上不会检查您是否正确编写了 OUT 参数的类型;因此,明确标记为 OUT 的任何参数都只是噪音。但是,为了与相应的CREATE 命令保持一致,建议编写它们。
为了与 SQL 标准兼容,还可以写出所有参数数据类型(包括 OUT 参数的数据类型),而不带任何 argmode标记。这样做时,将验证过程的 OUT参数的类型是否与命令匹配。这个规定会产生歧义,因为当参数列表不包含任何argmode标记时,不清楚意图是哪个规则。DROP命令将尝试按两种方式进行查找,并在找到两个不同的过程时抛出错误。为避免这种歧义的风险,建议明确编写IN 标记,而不是让它们默认,从而强制使用传统的 UXsinoDB 解释。
刚才解释的查找规则也适用于其他操作现有过程的命令,例如 ALTER PROCEDURE 和 COMMENT ON PROCEDURE。
示例
如果只有一个名为 do_db_maintenance的过程,则此命令足以将其删除:
DROP PROCEDURE do_db_maintenance;
给定此过程定义:
CREATE PROCEDURE do_db_maintenance(IN target_schema text, OUT results text) ...
以下任何一个命令都可以将其删除:
DROP PROCEDURE do_db_maintenance(IN target_schema text, OUT results text);
DROP PROCEDURE do_db_maintenance(IN text, OUT text);
DROP PROCEDURE do_db_maintenance(IN text);
DROP PROCEDURE do_db_maintenance(text);
DROP PROCEDURE do_db_maintenance(text, text); -- 可能存在歧义
但是,如果还有以下内容,则最后一个示例将存在歧义:
CREATE PROCEDURE do_db_maintenance(IN target_schema text, IN options text) ...
兼容性
此命令符合 SQL 标准,并具有以下 UXsinoDB 扩展:
-
标准只允许一次命令删除一个过程。
-
IF EXISTS选项是一种扩展。 -
允许指定参数模式和名称是一种扩展。
扩展名和查找规则在给定模式时会有所不同。
另请参阅
CREATE PROCEDURE,ALTER PROCEDURE,DROP FUNCTION,DROP ROUTINE
DROP PUBLICATION
DROP PUBLICATION — 删除发布
概要
DROP PUBLICATION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP PUBLICATION 从数据库中删除现有的发布。
只有发布的所有者或超级用户才能删除发布。
参数
-
IF EXISTS
如果发布不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有发布的名称。 -
CASCADE
RESTRICT
这些关键字没有任何效果,因为发布没有依赖关系。
示例
删除发布:
DROP PUBLICATION mypublication;
兼容性
DROP PUBLICATION 是 UXsinoDB 的扩展。
另请参阅
CREATE PUBLICATION、ALTER PUBLICATION
DROP ROLE
DROP ROLE — 删除数据库角色
概要
DROP ROLE [ IF EXISTS ] name [, ...]
描述
DROP ROLE 删除指定的角色。要删除超级用户角色,您必须是超级用户; 要删除非超级用户角色,您必须具有 CREATEROLE权限。
如果角色仍然在集群的任何数据库中被引用,则无法删除角色;如果是这样,将引发错误。在删除角色之前,必须删除它拥有的所有对象(或重新分配它们的所有权),并撤销角色在其他对象上被授予的任何权限。REASSIGN OWNED 和DROP OWNED命令可用于此目的。
但是,不必删除涉及角色的角色成员身份;DROP ROLE自动撤销目标角色在其他角色中的任何成员身份,以及其他角色在目标角色中的任何成员身份。其他角色不会被删除或受到其他影响。
参数
-
IF EXISTS
如果角色不存在,则不会引发错误。在这种情况下会发出通知。 -
name
要删除的角色的名称。
注释
UXsinoDB 包括一个名为dropuser的程序,具有与此命令相同的功能(实际上,它调用此命令),但可以从命令 shell 运行。
示例
要删除一个角色:
DROP ROLE jonathan;
兼容性
SQL 标准定义了 DROP ROLE,但它只允许一次删除一个角色,并且它指定了不同于 UXsinoDB 使用的特权要求。
另请参阅
CREATE ROLE 、ALTER ROLE、SET ROLE
DROP ROUTINE
DROP ROUTINE —删除一个例程
概要
DROP ROUTINE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
[ CASCADE | RESTRICT ]
描述
DROP ROUTINE删除一个或多个现有例程的定义。术语“例程”包括聚合函数、普通函数和存储过程。有关参数的描述、更多示例和详细信息,请参见DROP AGGREGATE、DROP FUNCTION和DROP PROCEDURE。
注意事项
DROP ROUTINE 使用的查找规则基本上与DROP PROCEDURE相同;特别是,DROP ROUTINE共享该命令的行为,即将没有argmode标记的参数列表视为可能使用 SQL标准的定义,即OUT参数包含在列表中。(DROP AGGREGATE和DROP FUNCTION不这样做。)
在某些情况下,当不同类型的例程共享相同的名称时,DROP ROUTINE可能会因模棱两可而失败,而更具体的命令(DROP FUNCTION等)将起作用。更仔细地指定参数类型列表也将解决此类问题。
其他对现有例程进行操作的命令,如ALTER ROUTINE和COMMENT ON ROUTINE,也使用这些查找规则。
示例
要删除类型为integer的例程foo:
DROP ROUTINE foo(integer);
无论 foo 是聚合函数、函数还是存储过程,此命令都可以使用。
兼容性
此命令符合 SQL 标准,并具有以下 UXsinoDB 扩展:
-
标准只允许一次命令删除一个例程。
-
IF EXISTS选项是一种扩展。 -
指定参数模式和名称的能力是一种扩展,当给出模式时,查找规则会有所不同。
-
用户定义的聚合函数是一种扩展。
另请参阅
DROP AGGREGATE、DROP FUNCTION、DROP PROCEDURE、ALTER ROUTINE
请注意,没有 CREATE ROUTINE 命令。
DROP RULE
DROP RULE — 删除重写规则
概要
DROP RULE [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
描述
DROP RULE 用于删除重写规则。
参数
-
IF EXISTS
如果规则不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的规则的名称。 -
table_name
规则适用的表或视图的名称(可选模式限定)。 -
CASCADE
自动删除依赖于该规则的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于该规则,则拒绝删除该规则。这是默认设置。
示例
要删除重写规则newrule:
DROP RULE newrule ON mytable;
兼容性
DROP RULE 是 UXsinoDB 语言扩展,整个查询重写系统也是如此。
另请参阅
DROP SCHEMA
DROP SCHEMA — 删除模式
概要
DROP SCHEMA [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP SCHEMA 从数据库中删除模式。
只有模式的所有者或超级用户才能删除模式。请注意, 即使所有者不拥有模式中的某些对象,他们也可以删除模式(以及所有包含的对象)。
参数
-
IF EXISTS
如果模式不存在,则不会引发错误。在这种情况下会发出通知。 -
name
模式的名称。 -
CASCADE
自动删除包含在模式中的对象(表、函数等), 以及依赖于这些对象的所有对象。 -
RESTRICT
如果模式包含任何对象,则拒绝删除模式。这是默认值。
注意事项
使用 CASCADE 选项可能会使命令删除除命名模式之外的其他模式中的对象。
示例
要从数据库中删除模式 mystuff 以及它包含的所有内容:
DROP SCHEMA mystuff CASCADE;
兼容性
DROP SCHEMA 与 SQL 标准完全一致,除了标准仅允许一次删除一个模式,以及除了 IF EXISTS 选项是UXsinoDB 的扩展之外。
另请参阅
DROP SEQUENCE
DROP SEQUENCE — 删除序列
概要
DROP SEQUENCE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP SEQUENCE 用于删除序列号生成器。只有所有者或超级用户才能删除序列。
参数
-
IF EXISTS
如果序列不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
序列的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于序列的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于序列,则拒绝删除序列。这是默认设置。
示例
要删除序列serial:
DROP SEQUENCE serial;
兼容性
DROP SEQUENCE符合SQL标准,除了标准只允许一次删除一个序列,以及IF EXISTS选项是UXsinoDB的扩展。
另请参阅
CREATE SEQUENCE,ALTER SEQUENCE
DROP SERVER
DROP SERVER — 删除外部服务器描述符
概要
DROP SERVER [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP SERVER 删除现有的外部服务器描述符。要执行此命令,当前用户必须是服务器的所有者。
参数
-
IF EXISTS
如果服务器不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
现有服务器的名称。 -
CASCADE
自动删除依赖于服务器的对象(例如用户映射),以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于服务器,则拒绝删除服务器。这是默认设置。
示例
如果存在,则删除服务器foo:
DROP SERVER IF EXISTS foo;
兼容性
DROP SERVER 符合 ISO/IEC 9075-9(SQL/MED)标准。IF EXISTS子句是UXsinoDB的扩展。
另请参阅
DROP STATISTICS
DROP STATISTICS — 删除扩展统计信息
概要
DROP STATISTICS [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP STATISTICS 从数据库中删除统计对象。只有统计对象的所有者、模式所有者或超级用户才能删除统计对象。
参数
-
IF EXISTS
如果统计对象不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的统计对象的名称(可选模式限定)。 -
CASCADE
RESTRICT
这些关键字没有任何效果,因为没有统计依赖项。
示例
要销毁不同模式中的两个统计对象,而不会失败,如果它们不存在:
DROP STATISTICS IF EXISTS
accounting.users_uid_creation,
public.grants_user_role;
兼容性
SQL标准中没有DROP STATISTICS命令。
另请参阅
ALTER STATISTICS,CREATE STATISTICS
DROP SUBSCRIPTION
DROP SUBSCRIPTION — 删除订阅
概要
DROP SUBSCRIPTION [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP SUBSCRIPTION 从数据库集群中删除订阅。
只有超级用户才能删除订阅。
如果订阅与复制槽相关联,则无法在事务块内执行DROP SUBSCRIPTION。(您可以使用ALTER SUBSCRIPTION取消设置槽。)
参数
-
name
要删除的订阅的名称。 -
CASCADE
RESTRICT
这些关键字没有任何作用,因为没有依赖项与订阅相关。
注意事项
当删除与远程主机上的复制槽相关联的订阅(正常状态)时,DROP SUBSCRIPTION将连接到远程主机并尝试删除复制槽(以及任何剩余的表同步槽)作为其操作的一部分。这是必要的,以释放在远程主机上为订阅分配的资源。如果失败,要么是因为无法访问远程主机,要么是因为无法删除或不存在或从未存在过远程复制槽,则DROP SUBSCRIPTION 命令将失败。在这种情况下,通过执ALTER SUBSCRIPTION ... SET (slot_name =NONE)将订阅与复制槽分离。之后,DROP SUBSCRIPTION将不再尝试在远程主机上执行任何操作。请注意,如果远程复制槽仍然存在,则应手动删除它(以及任何相关的表同步槽);否则,它们将继续保留WAL,并最终可能导致磁盘填满。如果订阅与复制槽相关联,则无法在事务块内执行DROP SUBSCRIPTION。
示例
删除订阅:
DROP SUBSCRIPTION mysub;
兼容性
DROP SUBSCRIPTION是UXsinoDB的扩展。
另请参阅
CREATE SUBSCRIPTION,ALTER SUBSCRIPTION
DROP SYNONYM
DROP SYNONYM — 删除一个同义词
概要
DROP SYNONYM synname
DROP SYNONYM synname(arg, arg, ...)
描述
删除现有同义词。
参数
-
synname
用户自定义的同义词名称。 -
synname(arg,arg,...)
同义词函数名称及参数。
示例
删除索引idx1同义词,如下所示。
drop synonym syni1;
删除序列seq1同义词,如下所示。
drop synonym syn1;
删除视图vw1同义词,如下所示。
drop synonym synv1;
另请参阅
DROP TABLE
DROP TABLE — 删除表
概要
DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP TABLE 从数据库中删除表。只有表所有者、模式所有者和超级用户才能删除表。要清空表中的行而不破坏表,请使用DELETE或TRUNCATE。
DROP TABLE 总是删除目标表的任何索引、规则、触发器和约束。但是,要删除被视图或另一张表的外键约束引用的表,必须指定CASCADE。(CASCADE将完全删除依赖视图,但在外键情况下,它只会删除外键约束,而不是完全删除其他表。)
参数
-
IF EXISTS
如果表不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的表的名称(可选模式限定)。 -
CASCADE
自动删除依赖于该表的对象(如视图), 以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何视图依赖于该表,则仅删除基表,跳过删除依赖它的视图,但是将依赖它的视图置为无效状态。这是默认值。
示例
要销毁两个表films和distributors:
DROP TABLE films, distributors;
兼容性
该命令符合SQL标准,但标准仅规定了DROP TABLE的基本语法,而不是其详细行为。
允许每个命令删除一个表,除了IF EXISTS选项外,这是UXsinoDB的扩展。
另请参阅
DROP TABLESPACE
DROP TABLESPACE — 删除表空间
概要
DROP TABLESPACE [ IF EXISTS ] name
描述
DROP TABLESPACE 从系统中删除表空间。
只有所有者或超级用户才能删除表空间。在删除表空间之前,必须清空其中所有的数据库对象。即使当前数据库中没有使用表空间的对象,其他数据库中的对象仍可能驻留在表空间中。
此外,如果表空间在任何活动会话的temp_tablespaces设置中列出,则由于临时文件驻留在表空间中,DROP 可能会失败。
参数
-
IF EXISTS
如果表空间不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
表空间的名称。
注意事项
DROP TABLESPACE 不能在事务块内执行。
示例
要从系统中删除表空间 mystuff:
DROP TABLESPACE mystuff;
兼容性
DROP TABLESPACE 是 UXsinoDB 的扩展。
另请参阅
CREATE TABLESPACE,ALTER TABLESPACE
DROP TEXT SEARCH CONFIGURATION
DROP TEXT SEARCH CONFIGURATION — 删除文本搜索配置
概要
DROP TEXT SEARCH CONFIGURATION [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP TEXT SEARCH CONFIGURATION 用于删除现有的文本搜索配置。要执行此命令,您必须是该配置的所有者。
参数
-
IF EXISTS
如果文本搜索配置不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
现有文本搜索配置的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于文本搜索配置的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于文本搜索配置,则拒绝删除文本搜索配置。这是默认设置。
示例
删除文本搜索配置my_english:
DROP TEXT SEARCH CONFIGURATION my_english;
如果存在引用to_tsvector调用中的配置的任何现有索引,则此命令将无法成功。添加CASCADE以与文本搜索配置一起删除这些索引。
兼容性
SQL标准中没有DROP TEXT SEARCH CONFIGURATION语句。
另请参阅
ALTER TEXT SEARCH CONFIGURATION ,CREATE TEXT SEARCH CONFIGURATION
DROP TEXT SEARCH DICTIONARY
DROP TEXT SEARCH DICTIONARY — 删除文本搜索词典
概要
DROP TEXT SEARCH DICTIONARY [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP TEXT SEARCH DICTIONARY 用于删除现有的文本搜索词典。要执行此命令,您必须是该词典的所有者。
参数
-
IF EXISTS
如果文本搜索词典不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
现有文本搜索词典的名称(可选架构限定符)。 -
CASCADE
自动删除依赖于文本搜索词典的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于文本搜索词典,则拒绝删除该文本搜索词典。这是默认设置。
示例
删除文本搜索词典english:
DROP TEXT SEARCH DICTIONARY english;
如果存在使用该词典的任何现有文本搜索配置,则此命令将无法成功。添加CASCADE以与词典一起删除这些配置。
兼容性
SQL标准中没有DROP TEXT SEARCH DICTIONARY语句。
另请参阅
ALTER TEXT SEARCH DICTIONARY ,CREATE TEXT SEARCH DICTIONARY
DROP TEXT SEARCH PARSER
DROP TEXT SEARCH PARSER — 删除文本搜索解析器
概要
DROP TEXT SEARCH PARSER [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP TEXT SEARCH PARSER 用于删除现有的文本搜索解析器。您必须是超级用户才能使用此命令。
参数
-
IF EXISTS
如果文本搜索解析器不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有文本搜索解析器的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于文本搜索解析器的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于文本搜索解析器,则拒绝删除该文本搜索解析器。这是默认设置。
示例
删除文本搜索解析器my_parser:
DROP TEXT SEARCH PARSER my_parser;
如果存在使用该解析器的任何现有文本搜索配置,则此命令将无法成功。添加CASCADE以与解析器一起删除这些配置。
兼容性
SQL 标准中没有DROP TEXT SEARCH PARSER语句。
另请参阅
ALTER TEXT SEARCH PARSER,CREATE TEXT SEARCH PARSER
DROP TEXT SEARCH TEMPLATE
DROP TEXT SEARCH TEMPLATE — 删除文本搜索模板
概要
DROP TEXT SEARCH TEMPLATE [ IF EXISTS ] name [ CASCADE | RESTRICT ]
描述
DROP TEXT SEARCH TEMPLATE 用于删除现有的文本搜索模板。您必须是超级用户才能使用此命令。
参数
-
IF EXISTS
如果文本搜索模板不存在,则不会引发错误。在这种情况下会发出通知。 -
name
现有文本搜索模板的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于文本搜索模板的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于文本搜索模板,则拒绝删除该模板。这是默认设置。
示例
删除文本搜索模板thesaurus:
DROP TEXT SEARCH TEMPLATE thesaurus;
如果存在使用该模板的现有文本搜索字典,则此命令将无法成功。添加CASCADE以与模板一起删除这些字典。
兼容性
SQL标准中没有DROP TEXT SEARCH TEMPLATE语句。
另请参阅
ALTER TEXT SEARCH TEMPLATE,CREATE TEXT SEARCH TEMPLATE
DROP TRANSFORM
DROP TRANSFORM —删除转换
概要
DROP TRANSFORM [ IF EXISTS ] FOR type_name LANGUAGE lang_name [ CASCADE | RESTRICT ]
描述
DROP TRANSFORM 用于删除先前定义的转换。
要删除转换,您必须拥有该类型和语言。这些是创建转换所需的相同权限。
参数
-
IF EXISTS
如果转换不存在,则不会引发错误。在这种情况下会发出通知。 -
type_name
转换的数据类型名称。 -
lang_name
转换的语言名称。 -
CASCADE
自动删除依赖于转换的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于转换,则拒绝删除转换。这是默认设置。
示例
要删除类型为hstore,语言为plpython3u的转换:
DROP TRANSFORM FOR hstore LANGUAGE plpython3u;
兼容性
这种形式的DROP TRANSFORM是 UXsinoDB的扩展。有关详细信息,请参见CREATE TRANSFORM。
另请参阅
DROP TRIGGER
DROP TRIGGER — 删除触发器
概要
DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
描述
DROP TRIGGER 删除一个已存在的触发器定义。要执行此命令,当前用户必须是定义触发器的表的所有者。
参数
-
IF EXISTS
如果触发器不存在,则不会抛出错误。在这种情况下,会发出通知。 -
name
要删除的触发器的名称。 -
table_name
定义触发器的表的名称(可选模式限定)。 -
CASCADE
自动删除依赖于触发器的对象,以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于触发器,则拒绝删除触发器。这是默认设置。
示例
销毁表films上的触发器if_dist_exists:
DROP TRIGGER if_dist_exists ON films;
兼容性
在UXsinoDB中,DROP TRIGGER语句与SQL标准不兼容。在SQL标准中,触发器名称不是局部于表的,因此该命令只是DROP TRIGGER name。
另请参阅
DROP TYPE
DROP TYPE — 删除数据类型
概要
DROP TYPE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP TYPE 用于删除用户定义的数据类型。只有类型的所有者才能删除它。
参数
-
IF EXISTS
如果类型不存在,则不会抛出错误。在这种情况下会发出通知。 -
name
要删除的数据类型的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于该类型的对象(例如表列、函数和运算符), 以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何对象依赖于该类型,则拒绝删除该类型。这是默认值。
示例
要删除数据类型box:
DROP TYPE box;
兼容性
该命令类似于SQL标准中的相应命令,除了IF EXISTS选项是UXsinoDB的扩展。但请注意,CREATE TYPE命令和UXsinoDB中的数据类型扩展机制与SQL标准不同。
另请参阅
DROP USER
DROP USER — 删除数据库角色
概要
DROP USER [ IF EXISTS ] name [, ...]
描述
DROP USER 是DROP ROLE的另一种拼写方式。
兼容性
DROP USER 语句是 UXsinoDB 的扩展。SQL 标准将用户的定义留给实现。
另请参阅
DROP USER MAPPING
DROP USER MAPPING — 删除外部服务器的用户映射
概要
DROP USER MAPPING [ IF EXISTS ] FOR { user_name | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name
描述
DROP USER MAPPING 从外部服务器中删除现有的用户映射。
外部服务器的所有者可以为该服务器的任何用户删除用户映射。此外,如果已向用户授予服务器上的 USAGE权限,则用户可以删除其自己的用户名的用户映射。
参数
-
IF EXISTS
如果用户映射不存在,则不会引发错误。在这种情况下,会发出通知。 -
user_name
映射的用户名。CURRENT_ROLE、CURRENT_USER和USER与当前用户的名称匹配。PUBLIC用于匹配系统中所有现有和未来的用户名。 -
server_name
用户映射的服务器名称。
示例
如果存在,则删除用户映射 bob,服务器 foo:
DROP USER MAPPING IF EXISTS FOR bob SERVER foo;
兼容性
DROP USER MAPPING 符合 ISO/IEC 9075-9 (SQL/MED)。IF EXISTS 子句是UXsinoDB 的扩展。
另请参阅
CREATE USER MAPPING,ALTER USER MAPPING
DROP VIEW
DROP VIEW — 删除视图
概要
DROP VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
描述
DROP VIEW 用于删除现有视图。要执行此命令,您必须是该视图的所有者。
参数
-
IF EXISTS
如果视图不存在,则不会引发错误。在这种情况下,会发出通知。 -
name
要删除的视图的名称(可选模式限定符)。 -
CASCADE
自动删除依赖于该视图的对象(例如其他视图), 以及依赖于这些对象的所有对象。 -
RESTRICT
如果有任何其它视图依赖于该视图,则仅删除该视图,跳过删除依赖该视图的其它视图,但是将依赖该视图的其它视图置为无效状态。这是默认设置。
示例
此命令将删除名为kinds的视图:
DROP VIEW kinds;
兼容性
此命令符合SQL标准,但标准仅允许每个命令删除一个视图, 除了IF EXISTS选项外,这是UXsinoDB的扩展。
另请参阅
END — 提交当前事务
概要
END [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
描述
END 提交当前事务。事务所做的所有更改对其他人可见,并且如果发生崩溃,则保证是持久的。此命令是等效于COMMIT的 UXsinoDB 扩展。
参数
-
WORK
TRANSACTION
可选关键字。它们没有任何影响。 -
AND CHAIN
如果指定了AND CHAIN,则立即启动一个具有相同事务特性(参见SET TRANSACTION)的新事务。否则,不会启动新事务。
注意事项
使用ROLLBACK中止事务。
在不在事务内部时发出 END 不会造成任何伤害,但会引发警告消息。
示例
提交当前事务并使所有更改永久:
END;
兼容性
END 是 UXsinoDB 扩展,提供与 SQL 标准中指定的等效功能COMMIT。
另请参阅
EXECUTE
EXECUTE - 执行预处理语句
概要
EXECUTE name [ ( parameter [, ...] ) ]
描述
EXECUTE用于执行先前准备好的语句。由于预处理语句仅存在于会话期间,因此预处理语句必须是由当前会话中先前执行的PREPARE语句创建的。
如果创建语句的PREPARE语句指定了一些参数,则必须传递兼容的参数集到EXECUTE语句中,否则会引发错误。请注意(与函数不同),预处理语句不会根据其参数的类型或数量进行重载;预处理语句的名称必须在数据库会话中是唯一的。
有关预处理语句的创建和使用的更多信息,请参见PREPARE。
参数
-
name
要执行的预处理语句的名称。 -
parameter
预处理语句的参数的实际值。这必须是一个表达式,产生与此参数数据类型兼容的值,就像在创建预处理语句时确定的那样。
输出
EXECUTE 返回的命令标记是预处理语句的标记,而不是 EXECUTE。
示例
示例请参见PREPARE中的“示例”。
兼容性
SQL 标准包括一个 EXECUTE语句,但它只能在嵌入式SQL中使用。这个版本的EXECUTE语句也使用了稍微不同的语法。
另请参阅
EXPLAIN
EXPLAIN — 显示语句的执行计划
概要
EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
其中 option 可以是以下之一:
ANALYZE [ boolean ]
VERBOSE [ boolean ]
COSTS [ boolean ]
SETTINGS [ boolean ]
BUFFERS [ boolean ]
WAL [ boolean ]
TIMING [ boolean ]
SUMMARY [ boolean ]
FORMAT { TEXT | XML | JSON | YAML }
描述
此命令显示由 UXsinoDB 规划器为提供的语句生成的执行计划。执行计划显示如何扫描语句引用的表 - 通过纯顺序扫描、索引扫描等 -如果引用了多个表,则使用什么连接算法将每个输入表的所需行组合在一起。
显示中最关键的部分是估计的语句执行成本,这是规划器对运行语句需要多长时间的猜测(以任意的成本单位来衡量,但通常意味着磁盘页面获取)。实际上显示了两个数字:在返回第一行之前的启动成本和返回所有行的总成本。对于大多数查询,总成本是最重要的,但在诸如EXISTS 中的子查询上下文中,规划器将选择最小的启动成本而不是最小的总成本(因为执行器在获取一行后将停止)。此外,如果您使用LIMIT 子句限制要返回的行数,则规划器会在端点成本之间进行适当的插值,以估计哪个计划实际上是最便宜的。
ANALYZE选项会导致语句实际执行,而不仅仅是计划。然后,实际运行时统计信息将添加到执行计划中。显示包括每个计划节点内总经过时间(以毫秒为单位)和实际返回的总行数。这对于查看规划器的估计是否接近实际情况很有用。
请注意,只有在使用ANALYZE选项时才会实际执行语句。虽然EXPLAIN将丢弃SELECT将返回的任何输出,但语句的其他副作用将像往常一样发生。如果您希望在不影响数据的情况下在INSERT、UPDATE、DELETE、CREATE TABLE AS或EXECUTE语句上使用EXPLAIN ANALYZE,请使用以下方法:
BEGIN;
EXPLAIN ANALYZE...;
ROLLBACK;
只能指定ANALYZE和VERBOSE选项,并且只能按照该顺序,而不用在括号中包围选项列表。预计所有新选项都将仅支持括号语法。
参数
-
ANALYZE
执行命令并显示实际运行时间和其他统计信息。此参数默认为FALSE。 -
VERBOSE
显示有关计划的其他信息。具体来说,包括计划树中每个节点的输出列列表,模式限定表和函数名称,始终使用其范围表别名标记表达式中的变量,并始终打印显示统计信息的每个触发器的名称。如果计算了查询标识符,则还将显示查询标识符,请参见compute_query_id以获取更多详细信息。此参数默认为FALSE。 -
COSTS
包括有关每个计划节点的估计启动成本和总成本以及每行的估计行数和估计宽度的信息。此参数默认为TRUE。 -
SETTINGS
包括有关配置参数的信息。具体来说,包括具有与内置默认值不同的值的影响查询计划的选项。此参数默认为FALSE。 -
BUFFERS
包括有关缓冲区使用情况的信息。具体来说,包括共享块的命中、读取、脏化和写入次数,本地块的命中、读取、脏化和写入次数,临时块的读取和写入次数,以及读取和写入数据文件块和临时文件块所花费的时间(以毫秒为单位),如果启用了track_io_timing。命中表示在需要时已在缓存中找到块,因此避免了读取。共享块包含常规表和索引的数据;本地块包含临时表和索引的数据;而临时块包含在排序、哈希、Materialize计划节点和类似情况下使用的短期工作数据。脏块的数量表示此查询更改的以前未修改的块的数量;而块数写入表示此后端在查询处理期间从缓存中驱逐的先前脏块的数量。上级节点显示的块数包括所有子节点使用的块。在文本格式中,仅打印非零值。默认为FALSE。 -
WAL
包括WAL记录生成的信息。具体来说,包括记录数、全页映像(fpi)数和生成的WAL字节数。在文本格式中,仅打印非零值。此参数仅在启用ANALYZE时才能使用。默认为FALSE。 -
TIMING
在输出中包括实际启动时间和每个节点中花费的时间。在某些系统上,反复读取系统时钟的开销可能会严重减慢查询速度,因此当仅需要实际行计数而不需要精确时间时,将此参数设置为FALSE可能会有用。即使使用此选项关闭了节点级计时,整个语句的运行时间仍然会被测量。此参数仅在启用ANALYZE时才能使用。默认为TRUE。 -
SUMMARY
在查询计划之后包括摘要信息(例如总计时信息)。默认情况下,使用ANALYZE时包括摘要信息,但在其他情况下不包括摘要信息,但可以使用此选项启用。在EXPLAIN EXECUTE中的计划时间包括从缓存中获取计划所需的时间和重新计划所需的时间(如果需要)。 -
FORMAT
指定输出格式,可以是TEXT、XML、JSON或YAML。非文本输出包含与文本输出格式相同的信息,但更容易由程序解析。此参数默认为TEXT。 -
boolean
指定是否应启用或禁用所选选项。您可以写TRUE、ON或1以启用选项,写FALSE、OFF或0以禁用选项。也可以省略boolean值,在这种情况下,假定为TRUE。 -
statement
任何SELECT、INSERT、UPDATE、DELETE、VALUES、EXECUTE、DECLARE、CREATE TABLE AS或CREATE MATERIALIZED VIEW AS语句,您希望查看其执行计划。
输出
该命令的结果是所选statement的计划的文本描述,可选择附带执行统计信息。
注意事项
为了允许UXsinoDB查询规划器在优化查询时做出合理的决策,建议在执行查询之前使用EXPLAIN命令查看查询计划。
为了查询执行计划中每个节点的运行时成本,EXPLAIN ANALYZE的当前实现会增加查询执行的分析开销。因此,在某些情况下,运行EXPLAIN ANALYZE可能比正常执行查询要花费更长的时间。开销的大小取决于查询的性质以及所使用的平台。最坏的情况发生在计划节点本身每次执行需要很少的时间,并且在获取当前时间的操作系统调用相对较慢的机器上。
示例
要显示对具有单个integer列和10000行的表的简单查询的计划,请执行以下操作:
EXPLAIN SELECT * FROM foo;
QUERY PLAN
--
Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4)
(1 row)
下面是同样的查询,带有 JSON 输出格式:
EXPLAIN (FORMAT JSON) SELECT * FROM foo;
QUERY PLAN
--
[ +
{ +
"Plan": { +
"Node Type": "Seq Scan",+
"Relation Name": "foo", +
"Alias": "foo", +
"Startup Cost": 0.00, +
"Total Cost": 155.00, +
"Plan Rows": 10000, +
"Plan Width": 4 +
} +
} +
]
(1 row)
如果有一个索引并且我们使用一个可索引的WHERE条件的查询,EXPLAIN可能会显示不同的计划:
EXPLAIN SELECT * FROM foo WHERE i = 4;
QUERY PLAN
--
Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4)
Index Cond: (i = 4)
(2 rows)
XML格式留给读者作为练习。
下面是同样的计划,成本估算被压制:
EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
QUERY PLAN
---
Index Scan using fi on foo
Index Cond: (i = 4)
(2 rows)
以下是使用聚合函数的查询的查询计划示例:
EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;
QUERY PLAN
----
Aggregate (cost=23.93..23.93 rows=1 width=4)
-> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4)
Index Cond: (i < 10)
(3 rows)
以下是使用EXPLAIN EXECUTE显示准备查询的执行计划的示例:
PREPARE query(int, int) AS SELECT sum(bar) FROM test
WHERE id > $1 AND id < $2
GROUP BY foo;
EXPLAIN ANALYZE EXECUTE query(100, 200);
QUERY PLAN
-----
HashAggregate (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1)
Group Key: foo
-> Index Scan using test_pkey on test (cost=0.29..9.29 rows=50 width=8) (actual time=0.039..0.091 rows=99 loops=1)
Index Cond: ((id > $1) AND (id < $2))
Planning time: 0.197 ms
Execution time: 0.225 ms
(6 rows)
当然,这里显示的具体数字取决于涉及的表的实际内容。此外,请注意,由于规划器改进,数字甚至选择的查询策略可能会在UXsinoDB版本之间有所不同。此外,ANALYZE命令使用随机抽样来估计数据统计信息;因此,即使表中的实际数据分布没有更改,成本估计也可能在ANALYZE的新运行之后发生变化。
兼容性
SQL标准中没有定义EXPLAIN语句。
另请参阅
FETCH
FETCH — 使用游标从查询中检索行
概要
FETCH [ direction ] [ FROM | IN ] cursor_name
其中 direction 可以是以下之一:
NEXT
PRIOR
FIRST
LAST
ABSOLUTE count
RELATIVE count
count
ALL
FORWARD
FORWARD count
FORWARD ALL
BACKWARD
BACKWARD count
BACKWARD ALL
描述
FETCH 使用先前创建的游标检索行。
游标具有关联的位置,FETCH使用该位置。游标位置可以在查询结果的第一行之前、在结果的任何特定行上或在结果的最后一行之后。创建时,游标位于第一行之前。在获取一些行之后,游标位于最近检索的行上。如果FETCH 超出可用行的末尾,则游标将被定位在最后一行之后,或者在向后获取时定位在第一行之前。FETCH ALL或FETCH BACKWARD ALL将始终使游标定位在最后一行之后或第一行之前。
使用 NEXT、PRIOR、FIRST、LAST、ABSOLUTE、RELATIVE的形式将在适当移动游标后检索单个行。如果没有这样的行,则返回空结果,并将游标定位在第一行之前或最后一行之后。
使用 FORWARD 和 BACKWARD 的形式检索指定数量的行,向前或向后移动,将游标定位在最后返回的行上(如果count超过可用行数,则在所有行之后/之前)。
RELATIVE 0、FORWARD 0 和 BACKWARD 0 的形式不移动游标,但仍返回当前行。
BACKWARD 0所有请求获取当前行而不移动光标,即重新获取最近获取的行。这将成功,除非光标定位在第一行之前或最后一行之后;在这种情况下,不返回任何行。
注意
此页面描述了在 SQL 命令级别上使用游标的用法。如果您正在尝试在 PL/uxSQL 函数内使用游标,则规则是不同的。
参数
-
direction
direction定义获取方向和要获取的行数。它可以是以下之一: -
NEXT
获取下一行。如果省略direction,则默认为此选项。 -
PRIOR
获取前一行。 -
FIRST
获取查询的第一行(与ABSOLUTE 1相同)。 -
LAST
获取查询的最后一行(与ABSOLUTE -1相同)。 -
ABSOLUTE count
获取查询的第count行,或者如果count为负,则获取倒数第abs(count) 行。如果count超出范围,则定位在第一行之前或最后一行之后;特别地,ABSOLUTE 0定位在第一行之前。 -
RELATIVE count
获取第count个后继行,或者如果count为负,则获取倒数第abs(count)个前行。如果有,则RELATIVE 0重新获取当前行。 -
count
获取接下来的count行(与FORWARD count相同)。 -
ALL
获取所有剩余的行(与FORWARD ALL相同)。 -
FORWARD
获取下一行(与NEXT相同)。 -
FORWARD count
获取接下来的count行。如果FORWARD 0,则重新获取当前行。 -
FORWARD ALL
获取所有剩余的行。 -
BACKWARD
获取前一行(与PRIOR相同)。 -
BACKWARD count
获取前count行(扫描所有行,直到找到所需的行)。 -
BACKWARD ALL获取所有前面的行(向后扫描)。 -
count
count是一个可能带符号的整数常量,用于确定要抓取的行的位置或数量。对于FORWARD和BACKWARD情况,指定负数的count等同于改变FORWARD和BACKWARD的意义。 -
cursor_name
打开的游标名称。
输出
成功完成后,FETCH 命令返回一个命令标记,格式如下:
FETCH count
count 是抓取的行数(可能为零)。请注意,在 uxsql 中,实际上不会显示命令标记,因为 uxsql 显示抓取的行。
注意事项
如果打算使用除带有正数计数的 FETCH NEXT 或 FETCH FORWARD 之外的任何 FETCH 变体,则应使用SCROLL 选项声明游标。对于简单的查询,UXsinoDB 允许从未声明 SCROLL的游标向后抓取,但最好不要依赖此行为。如果使用 NO SCROLL 声明游标,则不允许向后抓取。
ABSOLUTE抓取并不比使用相对移动导航到所需行更快:底层实现必须遍历所有中间行。负绝对抓取甚至更糟:必须读取查询以找到最后一行,然后从那里向后遍历。但是,倒回到查询的开头(如使用
FETCH ABSOLUTE 0)很快。
使用DECLARE定义游标。使用MOVE更改游标位置而不检索数据。
示例
以下示例使用游标遍历表:
BEGIN WORK;
-- Set up a cursor:
DECLARE liahona SCROLL CURSOR FOR SELECT * FROM films;
-- Fetch the first 5 rows in the cursor liahona:
FETCH FORWARD 5 FROM liahona;
code | title | did | date_prod | kind | len
--+++--++--
BL101 | The Third Man | 101 | 1949-12-23 | Drama | 01:44
BL102 | The African Queen | 101 | 1951-08-11 | Romantic | 01:43
JL201 | Une Femme est une Femme | 102 | 1961-03-12 | Romantic | 01:25
P_301 | Vertigo | 103 | 1958-11-14 | Action | 02:08
P_302 | Becket | 103 | 1964-02-03 | Drama | 02:28
-- Fetch the previous row:
FETCH PRIOR FROM liahona;
code | title | did | date_prod | kind | len
--+----++--+---+--
P_301 | Vertigo | 103 | 1958-11-14 | Action | 02:08
-- Close the cursor and end the transaction:
CLOSE liahona;
COMMIT WORK;
兼容性
SQL 标准定义了 FETCH用于在此处描述的嵌入式SQL仅适用于FETCH变体,它将数据返回为SELECT结果,而不是将其放入主机变量中。除此之外,FETCH与SQL标准完全向上兼容。
涉及FORWARD和BACKWARD的FETCH形式,以及FETCH count和FETCH ALL形式,其中FORWARD是隐含的,都是UXsinoDB的扩展。
SQL标准仅允许在游标名称之前使用FROM;使用IN或完全省略它们的选项是一种扩展。
另请参阅
GRANT
GRANT —定义访问权限
概要
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )[, ...] | ALL [ PRIVILEGES ]
( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON { SEQUENCE sequence_name [, ...] ALL SEQUENCES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON DOMAIN domain_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER fdw_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER server_name [, ...]
TO role_specification [, ...]
[ WITH GRANT OPTION ][GRANTED BY role_specification]
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
ON { { FUNCTION | PROCEDURE | ROUTINE } routine_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
| ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON LANGUAGE lang_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
ON LARGE OBJECT loid [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { { SET | ALTER SYSTEM } [, ... ] | ALL [ PRIVILEGES ] }
ON PARAMETER configuration_parameter [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { CREATE | ALL [ PRIVILEGES ] }
ON SCHEMA schema_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { CREATE | ALL [ PRIVILEGES ] }
ON TABLESPACE tablespace_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON TYPE type_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[GRANTED BY role_specification]
GRANT role_name [, ...] TO role_specification [, ...]
[ WITH ADMIN OPTION ]
[GRANTED BY role_specification]
GRANT ALTER [, ...] ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION
其中 role_specification 可以是:
[ GROUP ] role_name
| PUBLIC
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
描述
GRANT命令有两种基本变体:一种是授予数据库对象(表、列、视图、外部表、序列、数据库、外部数据包装器、外部服务器、函数、过程、过程语言、大型对象、配置参数、模式、表空间或类型)的特定权限,另一种是授予角色的成员资格。这些变体在许多方面相似,但它们足够不同以分别描述。
授予角色的成员资格
GRANT 命令的这个变体将一个或多个角色的成员资格授予另一个角色。如果已经授予了这些角色的成员资格,则会添加这些角色的成员资格。
授予直接授予的特权、授予其当前成员角色的特权以及授予PUBLIC的特权。
如果指定了WITH GRANT OPTION,则特权的接收者可以将其转授给其他人。没有授予选项,接收者不能这样做。不能向PUBLIC授予授予选项。
如果指定了GRANTED BY,则指定的授权者必须是当前用户。目前,此子句仅以此形式存在以实现SQL兼容性。
不需要向对象的所有者(通常是创建它的用户)授予特权,因为所有者默认具有所有特权。(但是,所有者可以选择撤销自己的某些特权以确保安全。)
删除对象或以任何方式更改其定义的权利不被视为可授予的特权;它是所有者固有的,不能被授予或撤销。(但是,可以通过授予或撤销拥有对象的角色的成员身份来获得类似的效果;请参见下文。)所有者隐含地拥有对象的所有授予选项。
可能的特权包括:
-
SELECT
INSERT
UPDATE
DELETE
TRUNCATE
REFERENCES
TRIGGER
CREATE
CONNECT
TEMPORARY
EXECUTE
USAGE
SET
ALTER SYSTEM
特定类型的特权。 -
TEMP
TEMPORARY的替代拼写。 -
ALL PRIVILEGES
授予对象类型可用的所有特权。在UXsinoDB中,PRIVILEGES关键字是可选的,但在严格的SQL中是必需的。
FUNCTION语法适用于普通函数、聚合函数和窗口函数,但不适用于存储过程;对于存储过程,请使用PROCEDURE。或者,使用ROUTINE来引用函数、聚合函数、窗口函数或存储过程,而不管其具体类型。
还有一种选项可以授予同一或多个模式中相同类型的所有对象的特权。目前,此功能仅支持表、序列、函数和存储过程。ALL TABLES也会影响视图和外部表,就像特定对象的GRANT命令一样。ALL FUNCTIONS也会影响聚合函数和窗口函数,但不会影响存储过程,同样也像特定对象的GRANT命令一样。使用ALL ROUTINES来包括存储过程。
**角色的GRANT
这个GRANT命令的变体授予成员身份执行该命令的角色对一个或多个其他角色进行授权。成为角色的成员很重要,因为它向每个成员传达了授予角色的特权。
如果指定了WITH ADMIN OPTION,则成员可以反过来授予其他人角色的成员资格,并撤销角色的成员资格。没有管理员选项,普通用户无法执行此操作。角色不被认为在自身持有WITH ADMIN OPTION。数据库超级用户可以向任何人授予或撤销任何角色的成员资格。具有CREATEROLE特权的角色可以向任何非超级用户的角色授予或撤销成员资格。
如果指定了GRANTED BY,则授权将被记录为由指定的角色执行。只有数据库超级用户可以使用此选项,除非它命名了执行命令的相同角色。
与特权的情况不同,角色的成员资格不能授予PUBLIC。还要注意,此命令形式不允许在role_specification中使用噪声词GROUP。
注意
REVOKE命令用于撤销访问特权。
用户和组的概念已统一为称为角色的单个实体。因此,不再需要使用关键字GROUP来标识授权方是用户还是组。虽然命令中仍允许使用GROUP,但它是一个噪声词。
如果用户对列或整个表具有特权,则可以在列上执行SELECT、INSERT等操作。在表级别授予权限,然后在一列上撤销它将不会做出希望的操作:表级授予不受列级操作的影响。
当对象的非所有者尝试在对象上授予特权时,如果用户对对象没有任何特权,则该命令将直接失败。只要某些特权可用,命令就会继续进行,但它只会授予用户具有授权选项的那些特权。如果没有持有授权选项,则GRANTALL PRIVILEGES形式将发出警告消息,而其他形式将发出警告,如果命令中明确命名的任何特权的授权选项不被持有。
应该注意,数据库超级用户可以访问所有对象,而不管对象特权设置如何。这类似于Unix系统中的root的权限。与root一样,除非绝对必要,否则以超级用户身份操作是不明智的。
如果超级用户选择发出GRANT或REVOKE命令,则该命令将被执行,就好像它是由受影响对象的所有者发出的一样。特别是,通过这样的命令授予的特权将显示为已由对象所有者授予。(对于角色成员身份,成员身份似乎是由包含角色本身授予的。)
GRANT或REVOKE也可以由不是受影响对象所有者的角色执行,但是该角色是拥有对象的角色的成员,或者是拥有对象特权WITH GRANT OPTION的角色的成员。在这种情况下,特权将被记录为已由授予权限的角色授予。实际拥有对象或持有特权的角色可以使用WITH GRANT OPTION选项授予其他角色权限。例如,如果表t1属于角色g1,而角色u1是该角色的成员,则u1可以授予u2在t1上的权限,但这些权限将显示为由g1直接授予。角色g1的任何其他成员都可以随后撤销这些权限。
如果执行GRANT的角色通过多个角色成员路径间接持有所需的特权,则未指定将记录哪个包含角色已执行授予权限。在这种情况下,最好使用SET ROLE成为您想要执行GRANT的特定角色。
在表上授予权限不会自动扩展到表使用的任何序列,包括与 SERIAL列相关联的序列。必须单独设置序列的权限。
示例
授予所有用户在表 films 上插入权限:
GRANT INSERT ON films TO PUBLIC;
授予用户 manuel 在视图 kinds 上的所有可用权限:
GRANT ALL PRIVILEGES ON kinds TO manuel;
请注意,如果由超级用户或 kinds 的所有者执行上述操作,确实会授予所有权限,但是如果由其他人执行,则仅授予该其他人具有授予权限的权限。
将用户 joe 加入角色 admins:
GRANT admins TO joe;
兼容性
根据 SQL 标准,在 ALL PRIVILEGES 中需要使用关键字 PRIVILEGES。SQL 标准不支持在一个命令中设置多个对象的权限。
UXsinoDB 允许对象所有者撤销自己的普通权限:例如,表所有者可以通过撤销自己的 INSERT、UPDATE、DELETE 和TRUNCATE 权限使表对自己只读。这在 SQL 标准中是不可能的。原因是 UXsinoDB将所有者的权限视为所有者授予自己的权限;因此,他们也可以撤销它们。
在SQL 标准中,所有者的权限是由一个假定的实体 “_SYSTEM” 授予的。不是 “_SYSTEM”,所有者无法撤销这些权限。
根据 SQL标准,授予选项可以授予 PUBLIC;UXsinoDB 仅支持将授予选项授予角色。
SQL 标准允许 GRANTED BY选项仅指定 CURRENT_USER 或 CURRENT_ROLE。
其他变体是 UXsinoDB 的扩展。SQL 标准为其他类型的对象(字符集、排序规则、翻译)提供了 USAGE 权限。在 SQL 标准中,序列仅具有 USAGE权限。特权控制使用NEXT VALUE FOR表达式,该表达式相当于UXsinoDB中的nextval函数。序列特权SELECT和UPDATE是UXsinoDB的扩展。将序列USAGE特权应用于currval函数也是UXsinoDB的扩展(函数本身也是如此)。
对于数据库、表空间、模式、语言和配置参数的特权是UXsinoDB的扩展。
另请参阅
REVOKE,ALTER DEFAULT PRIVILEGES
IMPORT FOREIGN SCHEMA
IMPORT FOREIGN SCHEMA - 从一个外部服务器导入表定义
概要
IMPORT FOREIGN SCHEMA remote_schema
[ { LIMIT TO | EXCEPT } ( table_name [, ...] ) ]
FROM SERVER server_name
INTO local_schema
[ OPTIONS ( option 'value' [, ... ] ) ]
描述
IMPORT FOREIGN SCHEMA创建表示存在于 外部服务器上的表的外部表。新外部表将由发出该命令的用户所拥有并且用 匹配远程表的正确的列定义和选项创建。
默认情况下,存在于外部服务器上一个特定模式中的所有表和视图都会被导入。根据需要,表的列表可以被限制到一个指定的子集,或者可以排除特定的表。新外部表都被创建在一个必须已经存在的目标模式中。
要使用IMPORT FOREIGN SCHEMA,用户必 须具有外部服务器上的USAGE特权以及在目标模式上的CREATE特权。
参数
-
remote_schema
要从哪个远程模式导入。一个远程模式的特定含义依赖于所使用的外部数据包装器。 -
LIMIT TO ( table_name [, ...] )
只导入匹配给定表名之一的外部表。外部模式中其他的表将被忽略。 -
EXCEPT ( table_name [, ...] )
把指定的外部表排除在导入之外。除了列在这里的表之外,外部模式 中存在的所有表都将被导入。 -
server_name
要从哪个外部服务器导入。 -
local_schema
被导入的外部表将创建在其中的模式。 -
OPTIONS ( option 'value' [, ...] )
要在导入期间使用的选项。允许使用的选项名称和值与每一个外部数据包装器有关。
示例
从服务器film_server上的远程模式foreign_films 中导入表定义,把外部表创建在本地模式films中:
IMPORT FOREIGN SCHEMA foreign_films
FROM SERVER film_server INTO films;
同上,但是只导入两个表actors和 directors(如果存在):
IMPORT FOREIGN SCHEMA foreign_films LIMIT TO (actors, directors)
FROM SERVER film_server INTO films;
兼容性
IMPORT FOREIGN SCHEMA命令符合SQL标准,不过OPTIONS子句是一种UXDB扩展。
另请参阅
CREATE FOREIGN TABLE, CREATE SERVER
INSERT
INSERT — 在表中创建新行
概要
[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
[ OVERRIDING { SYSTEM | USER } VALUE ]
{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query | SET assignment_list }
[ { [ ON CONFLICT [ conflict_target ] conflict_action ] | [ ON DUPLICATE KEY UPDATE assignment_list ] } ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
[LOG ERRORS
[INTO [schema.]table]
[(simple_expression)
REJECT LIMIT UNLIMITED]]
Oracle模式
INSERT INTO table_name { [ AS ] alias } [ ( column_name [, ...] ) ] VALUES ( expression [, ...] );
INSERT ALL { insert_into_clause [ values_clause ] } [, ...] query INSERT { ALL | FIRST }
{ WHEN condition THEN { insert_into_clause [ values_clause ] } [, ...] } [, ...] [ ELSE {insert_into_clause [ values_clause ] } [, ...] ] query
其中assignment_list取值如下:
column_name = { constant_value | constant_expression } [, ...]
其中conflict_target取值如下:
( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
ON CONSTRAINT constraint_name
其中conflict_action取值如下:
DO NOTHING
DO UPDATE SET { column_name = { expression | DEFAULT } |
( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
( column_name [, ...] ) = ( sub-SELECT )
} [, ...]
[ WHERE condition ]
其中insert_into_clause取值如下:
INTO table_name [ ( column_name [, ...] ) ]
values_clause取值如下:
VALUES ( expression [, ...] )
描述
INSERT 在表中插入新行。可以通过值表达式插入一个或多个行,或者通过查询插入零个或多个行。
目标列名可以按任意顺序列出。如果根本没有给出列名列表,则默认为表的所有列按其声明顺序;或者前N列。如果VALUES子句query中只提供了N列,则可以省略列名。由VALUES子句或query提供的值将与显式或隐式列列表从左到右关联。
未在显式或隐式列列表中出现的每个列将填充默认值,即其声明的默认值或null(如果没有默认值)。
如果任何列的表达式不是正确的数据类型,则将尝试自动类型转换。
没有唯一索引的表的INSERT不会被并发活动阻塞。具有唯一索引的表可能会被阻塞,如果并发会话执行锁定或修改与插入的唯一索引值匹配的行,则会发生此情况。ON CONFLICT可用于指定替代操作以避免引发唯一约束或排除约束违规错误(请参见下面的INSERT中的ON CONFLICT Clause)。
可选的RETURNING子句使INSERT根据实际插入的每行计算并返回值(如果使用了ON CONFLICT DO UPDATE子句,则更新)。这主要用于获取由默认值提供的值,例如序列号。但是,允许使用使用表的列的任何表达式。RETURNING列表的语法与SELECT的输出列表完全相同。仅返回成功插入或更新的行。例如,如果由于未满足ON CONFLICT DO UPDATE ... WHERE子句condition而锁定但未更新行,则不会返回该行。
必须具有对表的INSERT权限才能插入表中。如果存在ON CONFLICT DO UPDATE,则还需要对表具有UPDATE权限。
如果指定了列列表,则仅需要对列具有INSERT权限。同样,当指定了ON CONFLICT DO UPDATE时,仅需要对要更新的列具有UPDATE权限。但是,ON CONFLICT DO UPDATE还需要对在ON CONFLICT DO UPDATE表达式或condition中读取其值的任何列具有SELECT权限。
使用RETURNING子句需要对RETURNING中提到的所有列具有SELECT权限。如果使用query子句从查询中插入行,则当然需要在查询中使用的任何表或列上具有SELECT权限。
可选的LOG ERRORS子句可将导致失败的记录转移,放入到一张错误记录表中,详细见后续描述。
ON DUPLICATE KEY UPDATE要插入的行数据与表中已有记录的唯一索引或主键产生冲突,那么就会发生旧行的更新;如果插入的行数据与表中已有记录的唯一索引或者主键不冲突,则会发生新记录的插入。
参数
插入
本节介绍仅插入新行时可能使用的参数。仅与ON CONFLICT子句一起使用的参数单独描述。
with_query
WITH子句允许您指定一个或多个子查询可以在INSERT查询中通过名称引用。有关详细信息,请参见SELECT 。
query(SELECT语句)也可以包含WITH子句。在这种情况下,可以在query中引用两组with_query,但是第二组优先级更高,因为它更紧密地嵌套。
-
table_name
现有表的名称(可选模式限定)。 -
alias
table_name的替代名称。提供别名时,它完全隐藏了表的实际名称。当ON CONFLICT DO UPDATE目标为名为excluded的表时,这特别有用,因为否则它将被视为代表插入建议的行的特殊表的名称。
在oracle兼容模式下,支持插入数据时,可以不带“as”对表名做重命名。
-
column_name
table_name中的列名。如果需要,列名可以限定为子字段名或数组下标。(仅插入复合列的某些字段会使其他字段为空。)在引用带有ON CONFLICT DO UPDATE的列时,请勿在目标列的规范中包括表的名称。例如,INSERT INTO table_name... ON CONFLICT DO UPDATE SET table_name.col= 1是无效的(这遵循UPDATE的一般行为)。 -
OVERRIDING SYSTEM VALUE
如果指定了此子句,则为标识列提供的任何值都将覆盖默认的序列生成值。
对于定义为GENERATED ALWAYS的标识列,如果没有指定OVERRIDING SYSTEM VALUE或OVERRIDING USER VALUE,则插入显式值(除DEFAULT之外)是错误的。(对于定义为GENERATED BY DEFAULT的标识列,OVERRIDING SYSTEM VALUE是正常行为,并且指定它不起作用,但是UXsinoDB允许它作为扩展。)
OVERRIDING USER VALUE
如果指定了此子句,则忽略为标识列提供的任何值,并应用默认的序列生成值。
例如,在表之间复制值时,此子句很有用。编写INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1将从tbl1复制所有不是tbl2中的标识列的列,而tbl2中的标识列的值将由与tbl2相关联的序列生成。
-
DEFAULT VALUES
所有列都将填充其默认值,就像为每个列显式指定了DEFAULT一样。(在此形式中,不允许使用OVERRIDING子句。) -
expression
要分配给相应列的表达式或值。 -
DEFAULT
相应的列将填充其默认值。标识列将填充由相关序列生成的新值。对于生成的列,允许指定此选项,但仅指定从其生成表达式计算列的正常行为。 -
query
提供要插入的行的查询(SELECT语句)。有关语法的说明,请参见SELECT 语句。 -
SET assignment_list
通过SET方式赋值,代替VALUES (val_1,…,val_n),示例:SET col_1=val_1,...,col_n=val_n。 -
output_expression
在每行插入或更新后由INSERT命令计算并返回的表达式。该表达式可以使用由table_name命名的表的任何列名称。编写*以返回插入或更新的所有行的所有列。 -
output_name
用于返回列的名称。 -
assignment_list
赋值列表,如col_1=val_1,...,col_n=val_n( 列值只能为常量或常量表达式)。
ON CONFLICT子句
可选的ON CONFLICT子句指定替代操作以避免引发唯一性冲突或排除约束冲突错误。对于每个提议插入的单个行,要么进行插入,要么如果由conflict_target指定的仲裁者约束或索引被违反,则采取替代的conflict_action。ON CONFLICT DO NOTHING仅避免插入行作为其替代操作。ON CONFLICT DO UPDATE更新与提议插入的行冲突的现有行作为其替代操作。
conflict_target可以执行唯一索引推断。在执行推断时,它由一个或多个index_column_name列或index_expression表达式以及一个可选的index_predicate组成。所有table_name唯一索引,不考虑顺序,都包含完全相同的conflict_target指定的列/表达式,都被推断(选择)为仲裁者索引。如果指定了index_predicate,则必须满足仲裁者索引的进一步要求才能进行推断。请注意,这意味着如果满足每个其他条件的非部分唯一索引(没有谓词的唯一索引)可用,则将推断(因此由ON CONFLICT使用)。如果推断尝试失败,则会引发错误。
ON CONFLICT DO UPDATE保证原子INSERT或UPDATE结果;在高并发情况下,即使存在独立错误,也保证其中两个结果之一,这也称为UPSERT — “UPDATE或INSERT”。
-
conflict_target
通过选择conflict_action 来指定ON CONFLICT采取的替代操作的冲突。可以执行唯一索引推断,也可以明确命名约束。对于ON CONFLICT DO NOTHING,可选指定conflict_target;当省略时,处理所有可用约束(和唯一索引)的冲突。对于ON CONFLICT DO UPDATE,必须提供conflict_target。 -
conflict_action
指定替代ON CONFLICT操作。它可以是DO NOTHING,也可以是一个DO UPDATE子句,指定在冲突情况下执行的UPDATE操作的确切细节。在ON CONFLICT DO UPDATE中,SET和WHERE子句可以使用表名(或别名)访问现有行,并使用特殊的excluded表访问插入提议的行。在目标表中,需要对任何列具有SELECT权限,其中相应的excluded列被读取。
请注意,所有每行BEFORE INSERT触发器的效果都反映在excluded值中,因为这些效果可能导致行被排除在插入之外。
-
index_column_name
是table_name列的名称。用于推断仲裁索引。遵循CREATEINDEX格式。需要对index_column_name具有SELECT权限。 -
index_expression
类似于index_column_name,但用于推断出现在索引定义中的table_name列上的表达式(而不是简单列)。遵循CREATE INDEX格式。需要对出现index_expression中的任何列具有SELECT权限。 -
collation
当指定时,强制相应的index_column_name或index_expression使用特定的排序规则以便在推断期间匹配。通常省略此选项,因为排序规则通常不会影响是否发生约束违规。遵循CREATE INDEX格式。 -
opclass
当指定时,强制相应的index_column_name或index_expression使用特定的操作符类以便在推断期间匹配。通常省略此选项,因为相等语义在类型的操作符类之间通常是等价的,或者因为可以信任定义的唯一索引具有相关的等价定义。遵循CREATE INDEX格式。 -
index_predicate
允许推断部分唯一索引。满足谓词的任何索引(实际上不需要是部分索引)都可以被推断。遵循CREATE INDEX格式。需要在index_predicate中出现的任何列上具有SELECT权限。 -
constraint_name
通过名称显式指定仲裁器约束,而不是推断约束或索引。 -
condition
返回boolean类型值的表达式。只有在此表达式返回true的行将被更新,尽管在执行ON CONFLICT DO UPDATE操作时,所有行都将被锁定。请注意,在确定冲突候选项之后,将最后评估condition。
请注意,排除约束不支持作为ON CONFLICT DO UPDATE的仲裁器。在所有情况下,仅支持NOT DEFERRABLE约束和唯一索引作为仲裁器。
带有ON CONFLICT DO UPDATE子句的INSERT是一个“确定性的”语句。这意味着该命令不会影响任何单个现有行超过一次;当出现这种情况时,将引发基数违规错误。建议插入的行不应在由仲裁器索引或约束约束的属性方面重复。
请注意,目前不支持将应用于分区表的ON CONFLICT DO UPDATE子句更新冲突行的分区键,以使其需要将行移动到新分区。
提示
通常最好使用唯一索引推断,而不是直接使用ON CONFLICT ON CONSTRAINT constraint_name命名约束。推断将在底层索引被另一个更或少等效的索引重叠替换时继续正确工作,例如在删除要替换的索引之前使用CREATE UNIQUE INDEX ... CONCURRENTLY。
ON DUPLICATE KEY UPDATE子句
可选的ON DUPLICATE KEY UPDATE子句指定替代操作,以避免引发唯一性冲突或排除约束冲突错误。对于每个插入的单个行,若违反约束或索引,则采取替代的assignment_list操作,进而更新目标表中指定列,否则直接插入。
输出
成功完成后,INSERT命令返回一个形式为
INSERT oid count
count是插入或更新的行数。oid始终为0(如果count恰好为1且目标表已声明为WITH OIDS,则它曾经是分配给插入行的OID,否则为0,但不再支持创建带有WITH OIDS的表)。
如果INSERT命令包含RETURNING子句,则结果将类似于包含在RETURNING列表中定义的列和值上计算的插入或更新的行的SELECT语句。
注意事项
如果指定的表是分区表,则将每行路由到相应的分区并插入其中。如果指定的表是一个分区,则如果输入行中有一个违反分区约束,则会出现错误。
您还可以考虑使用 MERGE,因为它允许在单个语句中混合使用 INSERT、UPDATE 和 DELETE。请参见MERGE。
示例
将单个行插入到表 films 中:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');
在此示例中,省略了 len 列,因此它将具有默认值:
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
此示例使用 DEFAULT 子句而不是指定值来设置日期列的默认值:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes');
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');
要插入一个完全由默认值组成的行:
INSERT INTO films DEFAULT VALUES;
要使用多行 VALUES 语法插入多行:
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
此示例从与 films 具有相同列布局的表 tmp_films 中插入一些行到表 films中:
INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';
此示例插入到数组列中:
-- Create an empty 3x3 gameboard for noughts-and-crosses
INSERT INTO tictactoe (game, board[1:3][1:3])
VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');
-- The subscripts in the above example aren't really needed
INSERT INTO tictactoe (game, board)
VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');
将单个行插入到表 distributors 中,并返回由 DEFAULT 子句生成的序列号:
INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
RETURNING did;
增加管理 Acme Corporation 帐户的销售员的销售计数,并将整个更新后的行以及当前时间记录在日志表中:
WITH upd AS (
UPDATE employees SET sales_count = sales_count + 1 WHERE id =
(SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')
RETURNING *
)
INSERT INTO employees_log SELECT *, current_timestamp FROM upd;
根据需要插入或更新新的分销商。假设已定义了一个唯一索引,该索引约束出现在 did 列中的值。请注意,特殊的 excluded表用于引用最初提出的插入值:
INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
插入分销商,或对于提议插入的行不执行任何操作,当存在现有的、被排除的行(在行插入触发器触发之前具有匹配约束列或列的行)时。示例假定已定义了唯一索引,该索引限制了出现在did列中的值:
INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
ON CONFLICT (did) DO NOTHING;
根据需要插入或更新新的分销商。示例假定已定义了唯一索引,该索引限制了出现在did列中的值。使用WHERE子句限制实际更新的行(任何未更新的现有行仍将被锁定):
-- Don't update existing distributors based in a certain ZIP code
INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution')
ON CONFLICT (did) DO UPDATE
SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')'
WHERE d.zipcode <> '21201';
-- Name a constraint directly in the statement (uses associated
-- index to arbitrate taking the DO NOTHING action)
INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;
Insert new distributor if possible; otherwise DO NOTHIN
如果可能,插入新的分销商;否则DO NOTHING。示例假定已定义了唯一索引,该索引限制了出现在did列中的值,该值在is_active布尔列评估为true的子集上:
-- This statement could infer a partial unique index on "did"
-- with a predicate of "WHERE is_active", but it could also
-- just use a regular unique constraint on "did"
INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
ON CONFLICT (did) WHERE is_active DO NOTHING;
如果test表中name列含有唯一或主键约束,如果表中name列已有待插入的值,则更新on duplicate key update后指定字段的值,如果没有重复值,则插入新纪录,如下所示。
insert test set name = 'Li' on duplicate key update email='2222';
Oracle模式下使用示例,如下所示。
uxdb=# create table test_alias(a int, b char(32));
CREATE TABLE
uxdb=# insert into TEST_ALIAS as a(a,b) values(1,'uxdb');
INSERT 0 1
uxdb=# insert into TEST_ALIAS a(a,b) values(2,'oracle');
INSERT 0 1
uxdb=# select * from TEST_ALIAS;
A | B
---+----
1 | uxdb
2 | oracle
(2 rows)
uxdb=# insert into TEST_ALIAS test_alias(a,b) values(3,'kingbase');
INSERT 0 1
uxdb=# select * from TEST_ALIAS;
A | B
---+----
1 | uxdb
2 | oracle
3 | kingbase
(3 rows)
LOG ERRORS子句
error_logging_clause 允许捕获 DML错误和受影响行的日志列值,并将它们保存在错误日志表中。
-
INTO table指定错误记录表的名称,schema指定表的模式。如果省略此子句,则数据库将分配默认名称,默认错误日志表名称为 ERR$_ ,后跟正在执行DML操作的表名称。如表为tab1 ,错误表为err$_tab1。 -
simple_expression指定要用作语句标记的值,以便在错误记录表中识别该语句中的错误。该表达式可以是文本、数字,如123,'错误子句'等。 -
REJECT LIMIT该子句允许指定一个整数作为错误日志记录的上限,当前仅提供UNLIMITED选项。
关于错误表
需要手动创建表中含有以下5列错误子句所需的系统列:
CREATE TABLE ERR$_xxx(
ORA_ERR_NUMBER$ TEXT, --记录错误号
ORA_ERR_MESG$ TEXT, --记录错误信息
ORA_ERR_ROWID$ INT, --暂无用
ORA_ERR_OPTYP$ TEXT, --错误操作,插入操作对应的 ‘i’
ORA_ERR_TAG$ TEXT); --记录错误标签,对应simple_expression
注意事项:
1.其中这5列必须存在且必须为前5列。
2.错误表中也可以大于5列,包含这5列和insert目标表同名列,可根据需要决定包含insert目标表0到多列。
3.错误子句在生效后将填充对应的错误表系统列,用户数据将根据错误表中对应的用户列进行填充。错误表中有对应列就填充。
4.使用错误子句时,用户需要有错误表的插入权限。无权限应报错
限制:
- 以下情况会导致语句失败并回滚,而不调用错误日志记录功能: 违反主键约束,唯一约束,排他约束; 不支持行级别after触发器,语句级触发器(after,before); 不支持栈溢出错误; 不支持除plsql创建函数过程及系统默认提供函数外的过程异常错误捕获; 不支持fdw
- 以下情况会无法使用错误子句: 语义解析优化阶段出现的错误,如将字符串转为整数类型的错误; 不受支持的数据类型将在语义分析阶段报错; 不支持insert values及insert all/first直接插入; 不支持insert all 及mysql 兼容模式的on duplicate key update语法;
支持场景:
- 列值太大,超过定义,如插入varchar(100) 至varchar(10)的这种错误
- 约束违规(非空、引用和检查约束)
- 子查询中的列与表中相应列之间的类型转换导致的错误(如insert select中涉及到类型转换错误都会记录)
- 分区映射错误
- 行级别触发器(仅before触发器)
支持数据类型
-
数值型类型:smallint,int,bigint,decimal numeric,real,double precision smallserial serial bigserial,oracle模式中的double,raw,rowid
-
Bool类型
-
字符串类型:Varchar,char,(text和name不会异常),Oracle模式中的nvarchar2,nchar
-
时间类型:Time,data,timestamp,Oracle模式中的data
错误子句使用示例,如下所示。
- 创建测试表。
CREATE TABLE I(I INT, II VARCHAR(6));
CREATE TABLE I_S(I VARCHAR,II VARCHAR(10));
INSERT INTO I_S VALUES(1,'ASD'),(2,'ASDFFFG'),('3C','ASDD'),('4D','ASDDCCCC');
- 创建错误表。
CREATE TABLE ERR$_I(ORA_ERR_NUMBER$ TEXT,ORA_ERR_MESG$ TEXT, ORA_ERR_ROWID$ INT, ORA_ERR_OPTYP$ TEXT, ORA_ERR_TAG$ TEXT, I TEXT,II TEXT);
- 执行错误子句
INSERT INTO I SELECT * FROM I_S LOG ERRORS REJECT LIMIT UNLIMITED;
- 查看目标表数据,满足目标表的数据插入,仅成功1条数据
SELECT * FROM I;
i | ii
---+
1 | ASD
(1 row)
- 查看错误表,错误表中记录错误的数据
SELECT * FROM ERR$_I;
ora_err_number$ | ora_err_mesg$ | ora_err_rowid$ | ora_err_optyp$ | ora_err_tag$ | i | ii
--+-+-+-+----+----+
22001 | value too long for type character varying(6) | | I | | 2 | ASDFFFG
22P02 | invalid input syntax for type integer: "3C" | | I | | 3C | ASDD
22P02 | invalid input syntax for type integer: "4D" | | I | | 4D | ASDDCCCC
(3 rows)
兼容性
INSERT符合SQL标准,但RETURNING子句是 UXsinoDB扩展,使用INSERT和指定替代操作的能力也是扩展的。此外,标准不允许省略列名列表,但并非所有列都从VALUES子句或query中填充。如果您喜欢比ON CONFLICT更符合SQL标准的语句,请参见MERGE。
SQL标准指定只有在始终存在生成的标识列时才能指定OVERRIDING SYSTEM VALUE。UXsinoDB允许在任何情况下使用该子句,并在不适用时忽略它。
query子句的可能限制在SELECT 中有文档记录。
mysql模式下INSERT后的INTO关键字为可选项。
INSERT ALL
INSERT ALL — 按照条件在多表中创建新行
概要
INSERT ALL insert_into_clause
[values_clause]
[insert_into_clause[ values_clause ] ]...
SELECTSTMT
INSERT ALL
[WHEN condition THEN] insert_into_clause[ values_clause ]
[[ WHEN condition THEN] insert_into_clause [ values_clause ]]...
[ ELSE insert_into_clause [ values_clause ]]
SELECTSTMT
描述
从一张表里面读取数据插入到多张表。
INSERT ALL(无WHEN条件):最基本的多表插入功能,实现单条SQL,单次select,对多张表插入数据。
INSERT ALL(带WHEN条件):在insert all(无when条件)的基础上,加上when条件判断。只有当when条件为真时,才执行后面的into子句,否则不做插入操作。后面的else子句否决之前所有的when条件。
参数
这个小节介绍了可以使用的参数。
-
condition
when条件表达式,是任一计算得到布尔类型结果的表达式。 -
insert_into_clause
into子句,例如into table1。 -
values_clause
values子句,例如values( id )。 -
SELECTSTMT
select查询子句,例如select * from table1。
输出
成功完成时,INSERT命令会返回以下形式的命令标签:
count rows created
count是被插入或更新的行数。
示例
-
安装模式为oracle的uxdb数据库,创建集群。
-
创建表准备数据。
create table sample_0
(
id varchar,
data real,
no int
);
create table sample_1
(
id varchar,
data real,
no int
);
create table sample_2
(
id varchar,
data real,
no int
);
create table sample_3
(
id varchar,
data real,
no int
);
- 插入数据。
insert into sample_0 (id,data,no) values ('111111', 11.11, 1);
insert into sample_0 (id,data,no) values ('222222', 22.22, 2);
insert into sample_0 (id,data,no) values ('333333', 33.33, 3);
insert into sample_0 (id,data,no) values ('444444', 44.44, 4);
insert into sample_0 (id,data,no) values ('555555', 55.55, 5);
insert into sample_0 (id,data,no) values ('666666', 66.66, 6);
insert into sample_0 (id,data,no) values ('777777', 77.77, 7);
insert into sample_0 (id,data,no) values ('888888', 88.88, 8);
- 执行对应语句。
a. 给样表插入数据,有两种方式。如下所示。
i. 选择其中语句之一执行。
insert all
into sample_1 (id,data,no) values(id,data,no)
into sample_2 (id,data,no) values(id,data,no)
into sample_3 (id,data,no) values(id,data,no)
select id,data,no from sample_0;
insert all
into sample_1 values(id,data,no)
into sample_2 values(id,data,no)
into sample_3 values(id,data,no)
select * from sample_0;
insert all
into sample_1 (id,data,no) values(id,data,no)
into sample_2 (id,data,no) values(id,data,no)
into sample_3 (id,data,no) values(id,data,no)
select id,data,no from sample_0;
insert all
into sample_1 values(id,data,no)
into sample_2 values(id,data,no)
into sample_3 values(id,data,no)
select * from sample_0;
ii. 查看样表数据。
sample_1插入来自sample_0的8条数据;sample_2插入来自sample_0的8条数据; sample_3插入来自sample_0的8条数据。
uxdb=# select * from sample_1;
id | data | no
---+--+----
111111 | 11.11 | 1
222222 | 22.22 | 2
333333 | 33.33 | 3
444444 | 44.44 | 4
555555 | 55.55 | 5
666666 | 66.66 | 6
777777 | 77.77 | 7
888888 | 88.88 | 8
(8 rows)
uxdb=# select * from sample_2;
id | data | no
---+--+----
111111 | 11.11 | 1
222222 | 22.22 | 2
333333 | 33.33 | 3
444444 | 44.44 | 4
555555 | 55.55 | 5
666666 | 66.66 | 6
777777 | 77.77 | 7
888888 | 88.88 | 8
(8 rows)
uxdb=# select * from sample_3;
id | data | no
---+--+----
111111 | 11.11 | 1
222222 | 22.22 | 2
333333 | 33.33 | 3
444444 | 44.44 | 4
555555 | 55.55 | 5
666666 | 66.66 | 6
777777 | 77.77 | 7
888888 | 88.88 | 8
(8 rows)
iii. 清空测试表数据(可选)。
truncate sample_1;
truncate sample_2;
truncate sample_3;
b. insert all(带when条件)如果某个when关键字后面的表达式为真,则执行then后面的into操作。如下所示。
i. 选择其中语句之一执行。
insert all
when no < 5 then into sample_1 (id,data,no) values(id,data,no)
when data < 70 then into sample_2 (id,data,no) values(id,data,no)
else into sample_3 (id,data,no) values(id,data,no)
select id,data,no from sample_0;
insert all
when no < 5 then into sample_1 values(id,data,no)
when data < 70 then into sample_2 values(id,data,no)
else into sample_3 values(id,data,no)
select * from sample_0;
insert all
when no < 5 then into sample_1 (id,data,no) values(id,data,no)
when data < 70 then into sample_2 (id,data,no) values(id,data,no)
else into sample_3 (id,data,no) values(id,data,no)
select id,data,no from sample_0;
ii. 查看样表数据。
sample_1插入四条no < 5的数据,也就是源表的前四条; sample_2插入六条data < 70的数据,也就是源表的前六条; sample_3插入之前没有插入过的数据,也就是源表的第七、八条。
uxdb=# select * from sample_1;
id | data | no
---+--+----
111111 | 11.11 | 1
222222 | 22.22 | 2
333333 | 33.33 | 3
444444 | 44.44 | 4
(4 rows)
uxdb=# select * from sample_2;
id | data | no
---+--+----
111111 | 11.11 | 1
222222 | 22.22 | 2
333333 | 33.33 | 3
444444 | 44.44 | 4
555555 | 55.55 | 5
666666 | 66.66 | 6
(6 rows)
uxdb=# select * from sample_3;
id | data | no
---+--+----
777777 | 77.77 | 7
888888 | 88.88 | 8
(2 rows)
INSERT FIRST
INSERT FIRST — 按照条件在单表中创建新行
概要
INSERT FIRST
[WHEN condition THEN] insert_into_clause[ values_clause ]
[[ WHEN condition THEN] insert_into_clause[ values_clause ]]...
[ ELSE insert_into_clause [ values_clause ]]
SELECTSTMT
描述
INSERT FIRST在INSERT ALL(带when条件)的基础上,实现每条数据只会插入第一次。即,每条数据只有在第一次满足WHEN条件时执行插入操作。后面即便再次满足了某条WHEN条件,也不会执行插入。
参数
这个小节介绍了可以使用的参数。
-
condition
when条件表达式,是任一计算得到布尔类型结果的表达式。 -
insert_into_clause
into子句,例如into table1。 -
values_clause
values子句,例如values( id )。 -
SELECTSTMT
select查询子句,例如select * from table1。
输出
成功完成时,INSERT命令会返回以下形式的命令标签:
count rows created
count是被插入或更新的行数。
示例
-
安装模式为oracle的uxdb数据库,创建集群。
-
创建表准备数据。
create table sample_0 ( id varchar, data real, no int ); create table sample_1 ( id varchar, data real, no int ); create table sample_2 ( id varchar, data real, no int ); create table sample_3 ( id varchar, data real, no int ); -
插入数据。
insert into sample_0 (id,data,no) values ('111111', 11.11, 1); insert into sample_0 (id,data,no) values ('222222', 22.22, 2); insert into sample_0 (id,data,no) values ('333333', 33.33, 3); insert into sample_0 (id,data,no) values ('444444', 44.44, 4); insert into sample_0 (id,data,no) values ('555555', 55.55, 5); insert into sample_0 (id,data,no) values ('666666', 66.66, 6); insert into sample_0 (id,data,no) values ('777777', 77.77, 7); insert into sample_0 (id,data,no) values ('888888', 88.88, 8); -
insert first:是考虑先后关系的,如果有数据满足第一个when条件又满足第二个when条件,则执行第一个then插入语句,第二个then就不插入第一个then已经插入过的数据了。如下所示。a. 选择其中语句之一执行。
insert first when no < 5 then into sample_1 (id,data,no) values(id,data,no) when data < 70 then into sample_2 (id,data,no) values(id,data,no) else into sample_3 (id,data,no) values(id,data,no) select id,data,no from sample_0; insert first when no < 5 then into sample_1 (id,data,no) values(id,data,no) when data < 70 then into sample_2 (id,data,no) values(id,data,no) else into sample_3 (id,data,no) values(id,data,no) select * from sample_0; insert first when no < 5 then into sample_1 (id,data,no) values(id,data,no) when data < 70 then into sample_2 (id,data,no) values(id,data,no) else into sample_3 (id,data,no) values(id,data,no) select * from sample_0;b. 查看样表数据。
sample_1插入四条no < 5的数据,也就是源表的前四条; sample_2插入两条data < 70并且之前没有插入过的数据,也就是源表的第五、六条; sample_3插入之前没有插入过的数据,也就是源表的第七、八条。
uxdb=# select * from sample_1; id | data | no ---+--+---- 111111 | 11.11 | 1 222222 | 22.22 | 2 333333 | 33.33 | 3 444444 | 44.44 | 4 (4 rows) uxdb=# select * from sample_2; id | data | no ---+--+---- 555555 | 55.55 | 5 666666 | 66.66 | 6 (2 rows) uxdb=# select * from sample_3; id | data | no ---+--+---- 777777 | 77.77 | 7 888888 | 88.88 | 8 (2 rows)c. 清空测试表数据(可选)。
truncate sample_1; truncate sample_2; truncate sample_3;
LISTEN
LISTEN — 监听通知
概要
lISTEN channel
描述
LISTEN 注册当前会话作为名称为 channel 的通知通道的监听器。如果当前会话已经注册为该通知通道的监听器,则不执行任何操作。
每当命令 NOTIFY channel被调用时,无论是由该会话还是由连接到同一数据库的另一个会话调用,都会通知当前正在监听该通知通道的所有会话,并且每个会话将依次通知其连接的客户端应用程序。
可以使用 UNLISTEN 命令取消给定通知通道的会话注册。会话的监听注册在会话结束时自动清除。
客户端应用程序必须使用哪种方法来检测通知事件取决于其使用的 UXsinoDB 应用程序编程接口。使用 libuxsql 库时,应用程序将LISTEN 作为普通 SQL 命令发出,然后必须定期调用函数 UXSQLnotifies 以查找是否收到任何通知事件。其他接口(如libuxtcl)提供了更高级别的处理通知事件的方法;实际上,使用 libuxtcl 时,应用程序员甚至不应直接发出 LISTEN 或UNLISTEN。
参数
channel
通知通道的名称(任何标识符)。
注意事项
LISTEN 在事务提交时生效。如果在稍后回滚的事务中执行了 LISTEN 或 UNLISTEN,则监听的通知通道集合不会更改。
执行了LISTEN的事务不能为两阶段提交做准备。在首次设置监听会话时存在竞争条件:如果同时提交事务发送通知事件,那么新的监听会话将接收到哪些事件?答案是会话将接收到在事务提交步骤期间之后提交的所有事件。但是,这比事务在查询中观察到的任何数据库状态稍晚。这导致使用LISTEN的以下规则:首先执行(并提交!)该命令,然后在新的事务中根据应用程序逻辑需要检查数据库状态,然后依靠通知了解数据库状态的后续更改。最初接收到的几个通知可能涉及到已经在初始数据库检查中观察到的更新,但这通常是无害的。
NOTIFY包含了更详细的关于使用LISTEN和NOTIFY的讨论。
示例
从uxsql配置和执行监听/通知序列的示例:
lISTEN virtual;
NOTIFY virtual;
Asynchronous notification "virtual" received from server process with PID 8448.
兼容性
SQL标准中没有LISTEN语句。
另请参阅
LOAD
LOAD —加载共享库文件
概要
lOAD 'filename'
描述
该命令将共享库文件加载到UXsinoDB服务器的地址空间中。如果文件已经被加载,则该命令不执行任何操作。包含C函数的共享库文件在调用它们的函数时会自动加载。因此,通常只需要显式地使用LOAD来加载通过“挂钩”修改服务器行为的库,而不是提供一组函数的库。
库文件名通常只给出裸文件名,该文件名在服务器的库搜索路径中寻找(由dynamic_library_path设置)。或者可以给出完整路径名。在任一情况下,平台的标准共享库文件名扩展名都可以省略。
非超级用户只能将LOAD应用于位于$libdir/plugins/中的库文件——指定的filename必须以该字符串开头。(数据库管理员有责任确保只安装了“安全”的库。)
兼容性
LOAD是UXsinoDB的扩展。
另请参阅
LOCK
LOCK — 锁定表
概述
lOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
其中 lockmode 可以是以下之一:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
描述
LOCK TABLE 获取表级锁,如果有任何冲突的锁需要等待,则会等待。如果指定了NOWAIT,LOCK TABLE不会等待获取所需的锁:如果无法立即获取,则命令会中止并发出错误。一旦获取,锁将在当前事务的剩余时间内保持。(没有UNLOCK TABLE命令;锁始终在事务结束时释放。)
当锁定视图时,视图定义查询中出现的所有关系也会以相同的锁模式递归锁定。
在引用表的命令自动获取锁时,UXsinoDB 总是使用最不限制的锁模式。LOCK TABLE适用于可能需要更严格锁定的情况。例如,假设应用程序在READ COMMITTED 隔离级别下运行事务,并且需要确保表中的数据在事务的持续时间内保持稳定。为了实现这一点,您可以在查询之前获得SHARE 锁定模式。这将防止并发数据更改,并确保表的后续读取看到提交数据的稳定视图,因为 SHARE 锁定模式与写入者获取的 ROW EXCLUSIVE 锁定模式冲突,您的 LOCK TABLE name IN SHARE MODE语句将等待任何并发的 ROW EXCLUSIVE 模式锁定持有者提交或回滚。因此,一旦获得锁定,就没有未提交的写入;此外,在释放锁定之前,也不会开始任何写入。
在运行事务的同时实现类似效果时,可以使用 SELECT ... FOR UPDATE 或 SELECT ... FOR SHARE语句。这些语句将锁定查询中的行,以确保它们在事务的持续时间内保持稳定。这些语句还可以与其他表达式一起使用,以在锁定行时计算值。这些语句的详细信息,请参见SELECT 。
如果使用REPEATABLE READ或SERIALIZABLE隔离级别,必须在执行任何SELECT或数据修改语句之前执行LOCK TABLE语句。当SELECT或数据修改语句开始时,REPEATABLE READ或SERIALIZABLE事务对数据的视图将被冻结。事务中后面的LOCK TABLE仍将防止并发写入,但它不能确保事务读取的内容对应于最新提交的值。如果此类事务将更改表中的数据,则应使用SHARE ROW EXCLUSIVE锁定模式,而不是SHARE模式。这确保只有一个此类型的事务在任何时候运行。否则,可能会发生死锁:两个事务可能都获取SHARE模式,然后无法获取ROW EXCLUSIVE模式来执行它们的更新。(请注意,事务自己的锁永远不会冲突,因此当事务持有SHARE模式时,它可以获取ROW EXCLUSIVE模式,但如果其他人持有SHARE模式,则不能获取ROW EXCLUSIVE模式。)为避免死锁,请确保所有事务以相同的顺序在相同的对象上获取锁,并且如果单个对象涉及多个锁定模式,则事务应始终首先获取最严格的模式。
参数
name
现有表的名称(可选模式限定)。如果在表名之前指定了ONLY,则仅锁定该表。如果未指定ONLY,则锁定该表及其所有后代表(如果有)。可以在表名后面明确指定*,以表示包括后代表。
命令LOCK TABLE a, b;等同于LOCK TABLE a; LOCK TABLE b;。表按LOCK TABLE命令中指定的顺序逐个锁定。
lockmode
锁定模式指定此锁定与哪些锁定冲突。
如果未指定锁定模式,则使用最严格的模式ACCESS EXCLUSIVE。
NOWAIT
指定LOCK TABLE不应等待任何冲突的锁定:如果不能立即获取指定的锁定而无需等待,则事务将中止。
注意事项
LOCK TABLE ... IN ACCESS SHARE MODE需要在目标表上具有SELECT权限。LOCK TABLE ...IN ROW EXCLUSIVE MODE需要在目标表上具有INSERT、UPDATE、DELETE或TRUNCATE权限。所有其他形式的LOCK需要表级别的UPDATE、DELETE或TRUNCATE权限。
执行视图锁定的用户必须对视图具有相应的权限。此外,默认情况下,视图的所有者必须对基础关系具有相关权限,而执行锁定的用户不需要对基础关系具有任何权限。但是,如果视图的security_invoker设置为true(请参见CREATE VIEW),则执行锁定的用户而不是视图所有者必须对基础关系具有相关权限。
在事务块之外,LOCK TABLE是无用的:锁定仅保持到语句完成。因此,如果在事务块之外使用LOCK,UXsinoDB会报告错误。使用BEGIN和COMMIT(或ROLLBACK)来定义事务块。
LOCK TABLE仅处理表级别锁定,因此涉及ROW的模式名称都是错误的。这些模式名称通常应被解释为指示用户在锁定表内获取行级别锁定的意图。此外,ROW EXCLUSIVE模式是可共享的表锁。请记住,就LOCK TABLE而言,所有锁定模式的语义都是相同的,只有在哪些模式冲突的规则方面有所不同。有关如何获取实际行级锁定的信息,请参见SELECT 中的“锁定子句”。
示例
在将记录插入到外键表中时,在主键表上获取SHARE锁定:
BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- 如果未返回记录,则执行ROLLBACK
INSERT INTO films_user_comments VALUES
(_id_, 'GREAT! I was waiting for it for so long!');
COMMIT WORK;
在执行删除操作时,在主键表上获取SHARE ROW EXCLUSIVE锁定:
BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
(SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;
兼容性
SQL标准中没有LOCK TABLE,而是使用SET TRANSACTION在事务上指定并发级别。UXsinoDB也支持这一点;有关详细信息,请参见SET TRANSACTION。
除了ACCESS SHARE、ACCESS EXCLUSIVE和SHARE UPDATE EXCLUSIVE锁定模式外,UXsinoDB锁定模式和SQL标准中的锁定模式相同。LOCK TABLE语法与 Oracle 中的语法兼容。
MERGE
MERGE — 有条件地插入、更新或删除表中的行
概要
[ WITH with_query [, ...] ]
MERGE INTO target_table_name [ [ AS ] target_alias ]
USING data_source ON join_condition
when_clause [...]
其中 data_source 为:
{ source_table_name | ( source_query ) } [ [ AS ] source_alias ]
而 when_clause 为:
{ WHEN MATCHED [ AND condition ] THEN { merge_update | merge_delete | DO NOTHING } |
WHEN NOT MATCHED [ AND condition ] THEN { merge_insert | DO NOTHING } }
而 merge_insert 为:
INSERT [( column_name [, ...] )]
[ OVERRIDING { SYSTEM | USER } VALUE ]
{ VALUES ( { expression | DEFAULT } [, ...] ) | DEFAULT VALUES }
而 merge_update 为:
UPDATE SET { column_name = { expression | DEFAULT } |
( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...]
而 merge_delete 为:
DELETE
描述
MERGE 使用 data_source 对 target_table_name 中的行执行修改操作。MERGE提供了一个单一的 SQL 语句,可以有条件地插入、更新或删除行,这是一个任务。否则需要多个过程语言语句的操作。
首先,MERGE 命令执行一个连接操作,从 data_source 到target_table_name,生成零个或多个候选更改行。对于每个候选更改行,MATCHED或 NOT MATCHED 的状态只设置一次,之后按指定顺序评估 WHEN 子句。对于每个候选更改行,执行第一个评估为true的子句。对于任何候选更改行,最多只执行一个WHEN子句。
MERGE 操作与同名的常规UPDATE、INSERT或DELETE命令具有相同的效果。这些命令的语法不同,特别是没有WHERE子句,也没有指定表名。所有操作都涉及到target_table_name,但可以使用触发器对其他表进行修改。
当指定DO NOTHING时,源行将被跳过。由于操作按照指定顺序进行评估,因此在进行更细粒度的处理之前,使用DO NOTHING跳过不感兴趣的源行非常方便。
没有单独的 MERGE 权限。如果指定了更新操作,则必须具有 target_table_name 中在 SET 子句中引用的列的UPDATE 权限。如果指定了插入操作,则必须具有 target_table_name 的 INSERT权限。如果指定了删除操作,则必须具有 target_table_name 的DELETE 权限。权限在语句开始时进行测试,无论是否执行特定的WHEN子句都会进行检查。您需要在 condition 中引用data_source和任何列的target_table_name,因此需要具有SELECT权限。
如果 target_table_name 是材料化视图、外部表或者有规则定义,则不支持 MERGE。
参数
-
target_table_name
要合并到的目标表的名称(可选模式限定符)。 -
target_alias
目标表的替代名称。当提供别名时,它完全隐藏了表的实际名称。例如,给定MERGE INTO foo AS f,MERGE语句的其余部分必须将此表称为f而不是foo。 -
source_table_name
源表、视图或过渡表的名称(可选模式限定符)。 -
source_query
提供要合并到target_table_name中的行的查询(SELECT语句或VALUES语句)。
-
source_alias
数据源的替代名称。当提供别名时,它完全隐藏了表的实际名称或查询的事实。 -
join_condition
join_condition是一个表达式,其结果为boolean类型的值(类似于WHERE子句),指定哪些行在data_source中与target_table_name中的行匹配。
警告
只有来自target_table_name的列尝试匹配data_source行的列才应出现在join_condition中。仅引用target_table_name列的join_condition子表达式可能会以意想不到的方式影响采取的操作。
when_clause
至少需要一个WHEN子句。
如果 WHEN 子句指定了 WHEN MATCHED,并且候选更改行与target_table_name中的行匹配,则在缺少condition 或其计算结果为 true 的情况下执行 WHEN 子句。
相反,如果 WHEN 子句指定了WHEN NOT MATCHED,并且候选更改行与target_table_name中的行不匹配,则在缺少condition或其计算结果为 true 的情况下执行 WHEN 子句。
condition
返回boolean类型值的表达式。如果此表达式为WHEN子句返回true,则对于该行执行该子句的操作。
WHEN MATCHED 子句上的条件可以引用源和目标关系中的列。WHEN NOT MATCHED子句上的条件只能引用源关系中的列,因为根据定义,没有匹配的目标行。只有目标表中的系统属性是可访问的。
merge_insert
指定将一行插入目标表的INSERT操作。目标列名可以以任何顺序列出。如果根本没有给出列名列表,则默认为表的所有列按其声明顺序排列。
未在显式或隐式列列表中出现的每个列都将填充默认值,即其声明的默认值或 null(如果没有)。
如果 target_table_name 是分区表,则每行都会路由到适当的分区并插入其中。如果target_table_name是分区,则如果任何输入行违反了分区键的唯一性,则会出现错误。分区约束。
列名不能重复指定。INSERT 操作不能包含子查询。
只能指定一个 VALUES 子句。VALUES 子句只能引用源关系中的列,因为根据定义,没有匹配的目标行。
merge_update
指定一个UPDATE操作,更新target_table_name的当前行。列名不能重复指定。
不允许指定表名或 WHERE 子句。
-
merge_delete
指定一个DELETE操作,删除target_table_name的当前行。不要包括表名或任何其他子句,就像使用DELETE命令一样。 -
column_name
target_table_name中的列名。如果需要,列名可以带有子字段名或数组下标。(仅插入复合列的某些字段会使其他字段为空。)不要在目标列的规范中包括表名。 -
OVERRIDING SYSTEM VALUE
如果没有此子句,则为定义为GENERATED ALWAYS的标识列指定显式值(除了DEFAULT)是错误的。此子句覆盖了该限制。 -
OVERRIDING USER VALUE
如果指定了此子句,则忽略为定义为GENERATED BY DEFAULT的标识列提供的任何值,并应用默认的序列生成值。 -
DEFAULT VALUES
所有列都将填充其默认值。(此形式不允许使用OVERRIDING子句。) -
expression
要分配给列的表达式。如果在WHEN MATCHED子句中使用,则表达式可以使用目标表中原始行和data_source行中的值。如果在WHEN NOT MATCHED子句中使用,则表达式可以使用data_source中的值。 -
DEFAULT
将列设置为其默认值(如果没有为其分配特定的默认表达式,则为NULL)。 -
with_query
WITH子句允许您指定一个或多个子查询,这些子查询可以在MERGE查询中按名称引用。有关详细信息,请参见SELECT 。
输出
成功完成后,MERGE 命令将返回一个命令标记,格式如下:
MERGE total_count
total_count 是所有行的总数(无论是插入、更新还是删除)。如果 total_count 为 0,则没有任何行被更改。
在执行 MERGE 期间,将执行以下步骤:
-
对于所有指定的操作,无论其
WHEN子句是否匹配,都执行任何BEFORE STATEMENT触发器。 -
从源表到目标表执行连接。生成的查询将按照正常方式进行优化,并生成一组候选更改行。对于每个候选更改行,
a.评估每行是
MATCHED还是NOT MATCHED。b.按指定顺序测试每个
WHEN条件,直到其中一个返回 true。c. 当条件返回 true 时,执行以下操作:
i. 为操作的事件类型执行任何
BEFORE ROW触发器。ii.执行指定的操作,调用目标表上的任何检查约束。
iii. 为操作的事件类型执行任何
AFTER ROW触发器。 -
对于指定的操作,无论它们是否实际发生,都执行任何
AFTER STATEMENT触发器。这类似于修改零行的UPDATE语句的行为。
总之,事件类型的语句触发器(例如INSERT)将在我们指定该类型的操作时触发。相比之下,行级触发器仅在执行的特定事件类型上触发。因此,MERGE命令可能会触发 UPDATE 和 INSERT 的语句触发器,即使只触发了 UPDATE 行触发器。
您应确保连接为每个目标行最多生成一个候选更改行。换句话说,目标行不应连接到多个数据源行。如果连接了多个数据源行,则只会使用其中一个候选更改行来修改目标行;后续尝试修改该行将导致错误。如果行触发器对目标表进行更改,并且随后也通过MERGE 进行修改,则也可能发生这种情况。如果重复的操作是 INSERT,则会导致唯一性冲突,而重复的 UPDATE 或DELETE 将导致基数冲突;后一种行为是 SQL 标准所要求的。这与历史上的 UXsinoDB 在 UPDATE 和DELETE 语句中连接的行为不同,后续尝试修改相同的行将被简单地忽略。
如果 WHEN 子句省略了一个 AND子句,则它将成为该类型(MATCHED 或 NOT MATCHED)的最终可达子句。如果稍后指定了该类型的后续 WHEN子句,则该子句将被证明是不可达的,并引发错误。如果没有指定任何一种最终可达的子句,可能不会对候选更改行执行任何操作。
默认情况下,从数据源生成行的顺序是不确定的。如果需要,可以使用source_query指定一致的排序方式,这可能需要避免并发事务之间的死锁。
MERGE没有RETURNING子句。INSERT、UPDATE和DELETE的操作不能包含RETURNING或WITH子句。
当MERGE与修改目标表的其他命令同时运行时,通常的事务隔离规则适用。您还可以考虑使用INSERT... ON CONFLICT作为替代语句,它提供了在并发INSERT发生时运行UPDATE的能力。这两种语句类型之间存在各种差异和限制,它们不能互换使用。
示例
基于新的recent_transactions对customer_accounts执行维护。
MERGE INTO customer_account ca
USING recent_transactions t
ON t.customer_id = ca.customer_id
WHEN MATCHED THEN
UPDATE SET balance = balance + transaction_value
WHEN NOT MATCHED THEN
INSERT (customer_id, balance)
VALUES (t.customer_id, t.transaction_value);
请注意,这与以下语句完全相同,因为MATCHED结果在执行期间不会改变。
MERGE INTO customer_account ca
USING (SELECT customer_id, transaction_value FROM recent_transactions) AS t
ON t.customer_id = ca.customer_id
WHEN MATCHED THEN
UPDATE SET balance = balance + transaction_value
WHEN NOT MATCHED THEN
INSERT (customer_id, balance)
VALUES (t.customer_id, t.transaction_value);
尝试插入新的库存项以及库存数量。如果该项已经存在,则更新现有项的库存计数。不允许具有零库存的条目。
MERGE INTO wines w
USING wine_stock_changes s
ON s.winename = w.winename
WHEN NOT MATCHED AND s.stock_delta > 0 THEN
INSERT VALUES(s.winename, s.stock_delta)
WHEN MATCHED AND w.stock + s.stock_delta > 0 THEN
UPDATE SET stock = w.stock + s.stock_delta
WHEN MATCHED THEN
DELETE;
wine_stock_changes表可能是最近加载到数据库中的临时表。
兼容性
此命令符合SQL标准。
WITH子句和DO NOTHING操作是SQL标准的扩展。
MERGE INTO
MERGE INTO — 对需要更新的表同时进行更新、插入操作
概要
[ WITH ]MERGE INTO { table_name } [ alias ]
USING {{ table_name | view} | subquery } [ alias ]
ON condition
{ [ merge_update_clause ]
[ merge_insert_clause ]
[...]}
其中merge_update_clause是:
WHEN MATCHED
[ AND condition ] THEN UPDATE SET column = { expr | DEFAULT }
[, column = { expr | DEFAULT } ] [...]
[ DELETE ]
其中merge_insert_clause是:
WHEN NOT MATCHED
[ AND condition ] THEN INSERT [(column [, column ]...)]
{ VALUES ({ expr } [, { expr } ]...) | DEFAULT VALUES | DO NOTHING }
描述
merge into通过两表相互关联,对需要更新的表同时进行更新、插入操作。
使用MERGE语句从一个或多个源中选择行以进行更新或插入到表或视图中。可以指定条件以确定是要更新还是插入到目标表或视图中。
该语句是组合多个操作的便捷方法,可以避免使用多个INSERT,UPDATE和DELETE DML语句。MERGE是确定性声明。也就是说,不能在同一MERGE语句中多次更新目标表的同一行。
参数
这个小节介绍了可以使用的参数。
-
table_name
表名称,表必须已经存在。 -
alias
别名,对源表、目标表操作。 -
view
视图。 -
subquery
select子句。 -
condition
条件语句。 -
column
表属性。 -
expr
获取表属性的值。
merge_update_clause
该merge_update_clause指定目标表的新列值。如果ON子句的条件为true,则执行此更新。如果执行update子句,则将激活目标表上定义的所有更新触发器。
如果仅在指定条件为true时才希望数据库执行更新操作,请指定where_clause。条件可以是数据源表或目标表。如果条件不成立,则在将行合并到表中时,数据库将跳过更新操作。
指定DELETE where_clause以在填充或更新表时清理表中的数据。受此子句影响的唯一行是目标表中由合并操作更新的行。也就是说,DELETE WHERE条件评估更新的值,而不是UPDATE SET ... WHERE条件评估的原始值。如果目标表的行满足DELETE条件,但未包含在ON子句定义的连接中,则不会删除该行。对于每行删除,将激活目标表上定义的所有删除触发器。
可以单独或通过merge_insert_clause指定此子句。如果两者都指定,则它们可以采用任何顺序。对merge_update_clause的 限制此子句受以下限制: 不能更新ON条件子句中引用的列,更新视图时,不能指定DEFAULT。
merge_insert_clause
如果ON子句的条件为false ,则merge_insert_clause指定要插入到目标表的列中的值。如果执行了insert子句,则将激活目标表上定义的所有插入触发器。如果在INSERT关键字之后省略列列表,则目标表中的列数必须与VALUES子句中的值数匹配。要将所有源行插入到表中,可以在ON子句条件中使用常量过滤谓词。常量过滤器谓词的一个示例为ON(0 = 1)。Oracle数据库会识别这样的谓词,并将所有源行无条件地插入到表中。此方法不同于省略merge_update_clause。在这种情况下,数据库仍必须执行。一个连接。使用常量过滤器谓词时,不执行连接。
仅当指定条件为真时,才希望Oracle数据库执行插入操作时,请指定where_clause。该条件只能引用数据源表。Oracle Database对条件不成立的所有行都跳过插入操作。
可以单独或通过merge_update_clause指定此子句。如果两者都指定,则它们可以采用任何顺序。合并到视图的限制更新视图时,不能指定DEFAULT。
示例
update和insert同时使用
insert into A_MERGE values(1,'liuwei',20);
insert into A_MERGE values(2,'zhangbin',21);
insert into A_MERGE values(3,'fuguo',20);
insert into B_MERGE values(1,2,'zhangbin',30,'吉林');
insert into B_MERGE values(2,4,'yihe',33,'黑龙江');
insert into B_MERGE values(3,3,'fuguo',44,'山东')
使用merge into用B_MERGE来更新A_MERGE中的数据,如下所示。
MERGE INTO A_MERGE A USING (select AID,NAME,YEAR from B_MERGE B) C ON (A.id=C.AID)
WHEN MATCHED THEN
UPDATE SET A.YEAR=C.YEAR
WHEN NOT MATCHED THEN
INSERT(ID,NAME,YEAR) VALUES(C.AID,C.NAME,C.YEAR);
- 仅
update
首先向B_MERGE中插入两个数据,来为了体现出只update没有insert,必须有一个数据--是A中已经存在的另一个数据是A中不存在的,插入数据语句如下,如下所示。
insert into B_MERGE values(4,1,'liuwei',80,'江西');
insert into B_MERGE values(5,5,'tiantian',23,'河南');
用B_MERGE来更新A_MERGE,如下所示。
merge into A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON(A.ID=C.AID)
WHEN MATCHED THEN
UPDATE SET A.YEAR=C.YEAR;
- 仅
insert
B表必须有一个数据--是A中已经存在的另一个数据是A中不存在的,更新B表数据,如下所示。
update B_MERGE set year=70 where AID=2;
用B_MERGE来更新A_MERGE中的数据,如下所示。
merge into A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON(A.ID=C.AID)
WHEN NOT MATCHED THEN
insert(ID,NAME,YEAR) VALUES(C.AID,C.NAME,C.YEAR);
- 带
where条件的update和insert
B表必须有一个数据--是A中已经存在的另一个数据是A中不存在的,如下所示。
update B_MERGE set year=100 where AID=2;
insert into B_MERGE values(6,6,'youxuan',23,'北京');
带where条件的update,如下所示。
merge into A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON(A.ID=C.AID)
WHEN MATCHED THEN
UPDATE SET A.YEAR=C.YEAR where AID=2;
带where条件的insert,如下所示。
merge into A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON(A.ID=C.AID)
WHEN NOT MATCHED THEN
insert(ID,NAME,YEAR) VALUES(C.AID,C.NAME,C.YEAR) where AID=6;
- 带
delete的update
merge into通过and可实现where条件判断。
MERGE INTO A_MERGE A USING (select B.AID,B.NAME,B.YEAR from B_MERGE B) C ON(A.ID=C.AID)
WHEN MATCHED AND (A.id = 1) THEN DELETE
WHEN NOT MATCHED THEN INSERT(ID,NAME,YEAR) VALUES(C.AID,C.NAME,C.YEAR);
全插入insert。
有时需要将一张表中所有的数据插入到另外一张表,此时就可以添加常量过滤谓词来实现,让其只满足匹配和不匹配,这样就只有update或者只有insert。这里要无条件全插入,则只需将on中条件设置为永假。
用B_MERGE来更新A_MERGE,如下所示。
MERGE INTO A_MERGE A USING (select AID,NAME,YEAR from B_MERGE B) C ON (1=0)
WHEN MATCHED THEN
UPDATE SET A.YEAR=C.YEAR
WHEN NOT MATCHED THEN
INSERT(ID,NAME,YEAR) VALUES(C.AID,C.NAME,C.YEAR);
MOVE
MOVE — 定位光标
概要
MOVE [ direction ] [ FROM | IN ] cursor_name
其中 direction 可以是以下之一:
NEXT
PRIOR
FIRST
LAST
ABSOLUTE count
RELATIVE count
count
ALL
FORWARD
FORWARD count
FORWARD ALL
BACKWARD
BACKWARD count
BACKWARD ALL
描述
MOVE 重新定位光标而不检索任何数据。MOVE 的工作方式与 FETCH 命令完全相同,只是它只定位光标而不返回行。
MOVE 命令的参数与 FETCH 命令的参数相同;有关语法和用法的详细信息,请参见FETCH。
输出
成功完成后,MOVE 命令返回一个命令标记,格式如下:
MOVE count
count 是与具有相同参数的 FETCH 命令将返回的行数相同的行数(可能为零)。
示例
BEGIN WORK;
DECLARE liahona CURSOR FOR SELECT * FROM films;
-- 跳过前5行:
MOVE FORWARD 5 IN liahona;
MOVE 5
-- 从光标 liahona 获取第6行:
FETCH 1 FROM liahona;
code | title | did | date_prod | kind | len
--+---++--+---+--
P_303 | 48 Hrs | 103 | 1982-10-22 | Action | 01:37
(1 行)
-- 关闭光标 liahona 并结束事务:
CLOSE liahona;
COMMIT WORK;
兼容性
SQL 标准中没有 MOVE语句。
另请参阅
NOTIFY
NOTIFY - 生成通知
概述
NOTIFY channel [ , payload ]
描述
NOTIFY 命令会向当前数据库中已经执行过 LISTEN channel指定的通道名称的每个客户端应用程序发送一个带有可选的“负载”字符串的通知事件。通知对所有用户可见。
NOTIFY 提供了一个简单的进程间通信机制, 用于访问同一 UXsinoDB 数据库的一组进程。可以在通知中发送负载字符串,并且可以使用数据库中的表来传递附加数据,从通知程序到监听器之间构建更高级别的结构化数据传递机制。
传递给客户端的通知事件信息包括通知通道名称、通知会话的服务器进程 PID,以及负载字符串(如果未指定,则为空字符串)。
由数据库设计人员定义将在给定数据库中使用的通道名称以及每个通道名称的含义。通常,通道名称与数据库中某个表的名称相同,通知事件基本上意味着“我更改了这个表,请查看它以查看新内容”。但是,NOTIFY 和 LISTEN 命令不强制执行这种关联。例如,数据库设计人员可以使用多个不同的通道名称来表示对单个表的不同类型的更改。或者,负载字符串可以用于区分各种情况。
当使用 NOTIFY 来表示对特定表的更改发生时, 一个有用的编程技术是将 NOTIFY 放在由表更新触发的语句触发器中。通过这种方式,当表更改时,通知会自动发生,应用程序员不会意外地忘记执行它。
NOTIFY 与 SQL 事务有一些重要的交互。有两种情况下,NOTIFY 信号不会立即传递。首先,如果在事务中执行NOTIFY,则通知事件直到事务提交之前都不会被传递。这是合适的,因为如果事务被中止,则其中的所有命令都没有产生任何效果,包括NOTIFY。但是,如果期望立即传递通知事件,则可能会感到不安。其次,如果监听会话在事务中接收到通知信号,则直到事务完成(提交或中止)后才将通知事件传递给其连接的客户端。同样,这样做的原因是,如果在稍后中止的事务中传递了通知,则希望以某种方式撤消通知,但是一旦将通知发送到客户端,服务器就无法“收回”通知。因此,通知事件仅在事务之间传递。这意味着使用NOTIFY 进行实时信令的应用程序应尽量保持其事务短暂。
如果在同一事务中使用相同的有效负载字符串多次发出相同的通知信号,则只向侦听器传递一个通知事件实例。另一方面,具有不同有效负载字符串的通知将始终作为不同的通知传递。同样,来自不同事务的通知永远不会折叠成一个通知。除了删除后面的重复通知实例外,NOTIFY保证来自同一事务的通知按照发送顺序传递。
还保证来自不同事务的消息按照事务提交的顺序传递。通常,执行 NOTIFY的客户端也会在同一通知通道上进行监听。在这种情况下,它将收到一个通知事件,就像所有其他侦听会话一样。根据应用程序逻辑,这可能会导致无用的工作,例如读取数据库表以查找该会话刚刚写出的相同更新。可以通过注意到通知会话的服务器进程PID(在通知事件消息中提供)是否与自己的会话的 PID(可从 libuxsql中获取)相同来避免这种额外的工作。当它们相同时,通知事件是自己的工作反弹回来,可以忽略它。参数:通知信号的名称(任何标识符)和要与通知一起传递的有效负载字符串。在默认配置中,有效负载字符串必须是简单字符串文字,并且长度必须小于8000 个字节。如果需要传输二进制数据或大量信息,则最好将其放在数据库表中并发送记录的键。
参数
-
channel
要发出信号的通知通道的名称(任何标识符)。 -
payload
要与通知一起通信的“ payload”字符串。这必须指定为一个简单的字符串文本。在默认配置中,它必须小于8000字节。(如果需要通信二进制数据或大量信息,最好将其放在数据库表中并发送记录的键。)
注意事项
有一个队列保存已发送但尚未被所有侦听会话处理的通知。如果此队列变满,则在提交时调用NOTIFY 的事务将失败。队列非常大(在标准安装中为 8GB),几乎适用于每种用例。但是,如果会话执行 LISTEN然后进入事务,则无法进行清理。长时间未清理的通知队列可能会影响性能。一旦队列占满一半,日志文件中会出现警告,指向阻止清理的会话。在这种情况下,您应该确保该会话结束其当前事务,以便清理可以继续进行。
函数 ux_notification_queue_usage返回当前占用待处理通知的队列的比例。
已执行 NOTIFY 的事务无法准备为两阶段提交。
ux_notify
要发送通知,您还可以使用函数ux_notify(text,text)。该函数将通道名称作为第一个参数,有效载荷作为第二个参数。如果需要使用非常量通道名称和有效载荷,则该函数比NOTIFY 命令更容易使用。
示例
从 uxsql 配置和执行监听/通知序列:
lISTEN virtual;
NOTIFY virtual;
Asynchronous notification "virtual" received from server process with PID 8448.
NOTIFY virtual, 'This is the payload';
Asynchronous notification "virtual" with payload "This is the payload" received from server process with PID 8448.
LISTEN foo;
SELECT ux_notify('fo' || 'o', 'pay' || 'load');
Asynchronous notification "foo" with payload "payload" received from server process with PID 14728.
兼容性
SQL 标准中没有 NOTIFY 语句。
另请参见
PREPARE
PREPARE - 准备执行语句
概要
PREPARE name [ ( data_type [, ...] ) ] AS statement
描述
PREPARE 创建一个准备执行语句。准备执行语句是一个服务器端对象,可用于优化性能。执行 PREPARE语句时,将解析、分析和重写指定的语句。随后发出 EXECUTE命令时,将计划并执行准备执行语句。这种分工避免了重复的解析分析工作,同时允许执行计划依赖于提供的特定参数值。
准备执行语句可以带有参数:在执行语句时替换到语句中的值。创建准备执行语句时,使用位置引用参数,使用 $1、$2等。还可以选择指定相应的参数数据类型列表。当未指定参数的数据类型或将其声明为unknown 时,类型将从首次引用参数的上下文中推断出来(如果可能)。在执行语句时,在 EXECUTE语句中指定这些参数的实际值。有关更多信息,请参见EXECUTE。
准备执行语句仅在当前数据库会话的持续时间内有效。会话结束时,准备执行语句将被遗忘,因此必须在再次使用之前重新创建。这也意味着单个准备执行语句不能被多个同时存在的数据库客户端使用;但是,每个客户端都可以创建自己的准备执行语句来使用。可以使用DEALLOCATE命令手动清理准备执行语句。
当单个会话用于执行大量相似语句时,准备执行语句可能具有最大的性能优势。性能差异将特别明显。
如果语句很复杂需要进行计划或重写,例如涉及多个表的连接或需要应用多个规则,则准备好的语句的性能优势就会更加明显。如果语句相对简单,但执行代价相对昂贵,则准备好的语句的性能优势就不太明显。
参数
-
name
给这个特定的准备好的语句一个任意名称。它必须在单个会话中是唯一的,并随后用于执行或取消准备好的语句。 -
data_type
准备好的语句的参数的数据类型。如果特定参数的数据类型未指定或指定为unknown,则它将从首次引用该参数的上下文中推断出来。要引用准备好的语句中的参数,请使用$1,$2等。 -
statement
任何SELECT,INSERT,UPDATE,DELETE或VALUES语句。
注释
准备好的语句可以使用通用计划或自定义计划执行。通用计划在所有执行中都相同,而自定义计划是使用该调用中给定的参数值为特定执行生成的。使用通用计划可以避免计划开销,但在某些情况下,自定义计划将更有效,因为规划器可以利用参数值的知识。(当然,如果准备好的语句没有参数,则这是无用的,并且始终使用通用计划。)
默认情况下(即当plan_cache_mode设置为auto时),服务器将自动选择是使用通用计划还是自定义计划来执行具有参数的准备好的语句。当前的规则是前五个执行使用自定义计划,并计算这些计划的平均估计成本。然后创建一个通用计划,并将其估计成本与平均自定义计划成本进行比较。如果通用计划的成本不比平均自定义计划成本高得太多,以至于重复重新规划似乎更可取,则后续执行将使用通用计划。
可以通过将plan_cache_mode设置为force_generic_plan或force_custom_plan来覆盖此启发式方法,强制服务器使用通用计划或自定义计划。如果通用计划的成本估计由于某种原因严重偏差,则此设置主要有用,允许选择它,即使其实际成本远高于自定义计划的成本。
要检查UXsinoDB正在使用的查询计划,可以使用EXPLAIN,例如
EXPLAIN EXECUTE name(parameter_values);
如果使用通用计划,则其中将包含参数符号$n,而自定义计划将将提供的参数值替换为其中的参数。
有关查询规划和收集的统计信息的详细信息,请参见ANALYZE。
通过 UXsinoDB创建预处理语句,可以避免重复解析和规划语句。但是,每当语句中使用的数据库对象经历定义(DDL)更改或其规划器统计信息自上次使用预处理语句以来已更新时,UXsinoDB将强制重新分析和重新规划语句。此外,如果从一次使用到下一次使用的search_path 的值发生更改,则将使用新的search_path重新解析语句。这些规则使得预处理语句在语义上几乎等同于反复提交相同的查询文本,但如果没有对象定义更改,特别是如果最佳计划在使用过程中保持不变,则具有性能优势。一个语义等价不完美的例子是,如果语句通过未限定的名称引用表,然后在search_path中出现在更早的模式中创建了一个同名的新表,则不会自动重新解析,因为语句中使用的对象没有更改。但是,如果某些其他更改强制重新解析,则新表将在后续使用中被引用。
您可以通过查询ux_prepared_statements系统视图来查看会话中所有可用的预处理语句。
示例
创建一个 INSERT 语句的预处理语句,然后执行它:
PREPARE fooplan (int, text, bool, numeric) AS
INSERT INTO foo VALUES($1, $2, $3, $4);
EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);
创建一个 SELECT语句的预处理语句,然后执行它:
PREPARE usrrptplan (int) AS
SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid
AND l.date = $2;
EXECUTE usrrptplan(1, current_date);
在这个例子中,第二个参数的数据类型没有指定,因此它是从使用$2的上下文中推断出来的。
兼容性
SQL 标准包括一个PREPARE语句,但它仅用于嵌入式SQL。这个版本的PREPARE语句也使用了稍微不同的语法。
参见
PREPARE TRANSACTION
PREPARE TRANSACTION — 准备当前事务以进行两阶段提交
概要
PREPARE TRANSACTION transaction_id
描述
PREPARE TRANSACTION准备当前事务以进行两阶段提交。执行此命令后,事务不再与当前会话关联;相反,它的状态完全存储在磁盘上,并且即使在请求提交之前发生数据库崩溃,它也有很高的概率可以成功提交。
一旦准备好,事务可以稍后使用COMMIT PREPARED或ROLLBACK PREPARED进行提交或回滚,这些命令可以从任何会话中发出,而不仅仅是执行原始事务的会话。
从发出会话的角度来看,PREPARE TRANSACTION 与 ROLLBACK 命令类似:执行后,没有活动的当前事务,并且准备事务的影响不再可见。(如果提交事务,则影响将再次可见。)
如果 PREPARE TRANSACTION 命令由于任何原因失败,则变为 ROLLBACK:当前事务被取消。
参数
transaction_id
一个任意标识符,稍后用于COMMIT PREPARED或ROLLBACK PREPARED标识此事务。标识符必须写为字符串文字,并且长度必须小于200个字节。它不能与当前已准备的任何事务使用相同的标识符。
注意事项
PREPARE TRANSACTION不适用于应用程序或交互式会话。它的目的是允许外部事务管理器(如分布式事务管理器)控制UXsinoDB事务的提交。
事务管理器可在多个数据库或其他事务资源之间执行原子全局事务。除非您正在编写事务管理器,否则您可能不应该使用PREPARE TRANSACTION。
此命令必须在事务块内使用。使用BEGIN开始一个事务块。
目前不允许PREPARE涉及临时表或会话临时命名空间的任何操作,创建任何带有WITH HOLD的游标,或执行LISTEN、UNLISTEN或NOTIFY。这些功能与当前会话紧密相关,无法在准备的事务中使用。
如果事务使用SET(没有LOCAL选项)修改了任何运行时参数,则这些效果在PREPARE TRANSACTION之后仍然存在,并且不会受到任何后续COMMIT PREPARED或ROLLBACK PREPARED的影响。因此,在这一方面,PREPARE TRANSACTION的行为更像COMMIT而不是ROLLBACK。
所有当前可用的准备事务都列在ux_prepared_xacts系统视图中。
注意
长时间保留事务处于准备状态是不明智的。这将干扰VACUUM回收存储的能力,并在极端情况下可能导致数据库关闭以防止事务ID环绕。请记住,事务仍然保持其持有的任何锁定。该功能的预期用法是,一旦外部事务管理器已验证其他数据库也已准备好提交,准备的事务通常将立即提交或回滚。
如果您尚未设置外部事务管理器以跟踪准备的事务并确保它们及时关闭,最好通过将max_prepared_transactions设置为零来禁用准备的事务功能。这将防止意外创建可能被遗忘并最终导致问题的准备事务。
示例
使用foobar作为事务标识符,为当前事务准备两阶段提交:
PREPARE TRANSACTION 'foobar';
兼容性
PREPARE TRANSACTION是UXsinoDB的扩展。它旨在供外部事务管理系统使用,其中一些受到标准(如X/Open XA)的覆盖,但这些系统的SQL部分未经标准化。
另请参阅
COMMIT PREPARED,ROLLBACK PREPARED
REASSIGN OWNED
REASSIGN OWNED - 更改由数据库角色拥有的数据库对象的所有权
概要
REASSIGN OWNED BY { old_role | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...]
TO { new_role | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
描述
REASSIGN OWNED 指示系统更改任何 old_roles 拥有的数据库对象的所有权 为 new_role。
参数
-
old_role
角色的名称。当前数据库中的所有对象以及所有共享对象(数据库,表空间) 由此角色拥有的所有权将被重新分配给new_role。 -
new_role
将成为受影响对象的新所有者的角色名称。
注意事项
REASSIGN OWNED 经常用于准备删除一个或多个角色。因为 REASSIGN OWNED 不影响其他数据库中的对象,通常需要在包含由要删除的角色拥有的对象的每个数据库中执行此命令。
REASSIGN OWNED 需要源角色和目标角色的成员身份。
DROP OWNED 命令是一个替代方案,它只是删除一个或多个角色拥有的所有数据库对象。
REASSIGN OWNED 命令不影响授予 old_roles 对不属于它们的对象的任何权限。同样,它不影响使用 ALTER DEFAULT PRIVILEGES 创建的默认权限。
使用 DROP OWNED 命令来撤销这些权限。
兼容性
REASSIGN OWNED 命令是UXsinoDB的扩展。
另请参阅
DROP OWNED、DROP ROLE、ALTER DATABASE
REFRESH MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW — 替换材料化视图的内容
概要
REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] name
[ WITH [ NO ] DATA ]
描述
REFRESH MATERIALIZED VIEW完全替换材料化视图的内容。要执行此命令,您必须是材料化视图的所有者。旧内容将被丢弃。如果指定(或默认)WITH DATA,则执行后备查询以提供新数据,并使材料化视图处于可扫描状态。如果指定了WITH NO DATA,则不会生成新数据,并且材料化视图将处于不可扫描状态。
CONCURRENTLY 和 WITH NO DATA不能同时指定。
参数
CONCURRENTLY
在不锁定材料化视图上的并发选择的情况下刷新材料化视图。如果没有此选项,刷新会影响大量行的情况下,将倾向于使用更少的资源并更快地完成,但可能会阻止其他正在尝试从材料化视图读取的连接。在受影响的行数较少的情况下,此选项可能更快。
仅当材料化视图上至少有一个仅使用列名并包括所有行的UNIQUE索引时,才允许使用此选项;也就是说,它不能是表达式索引或包括WHERE子句。
当材料化视图尚未填充时,不能使用此选项。
即使使用此选项,任何一个材料化视图一次只能运行一个REFRESH。
name
要刷新的材料化视图的名称(可选架构限定符)。
注释
该命令将刷新物化视图的内容,使其与物化视图定义中的查询结果一致。默认情况下,物化视图的行将按照定义查询的顺序排序,但是REFRESH MATERIALIZED VIEW不能保证保留该排序方式。
示例
该命令将使用物化视图定义中的查询结果替换名为order_summary的物化视图的内容,并使其处于可扫描状态:
REFRESH MATERIALIZED VIEW order_summary;
该命令将释放与物化视图annual_statistics_basis相关联的存储空间,并使其处于不可扫描状态:
REFRESH MATERIALIZED VIEW annual_statistics_basis WITH NO DATA;
兼容性
REFRESH MATERIALIZED VIEW是UXsinoDB的扩展命令。
另请参阅
CREATE MATERIALIZED VIEW、ALTER MATERIALIZED VIEW、DROP MATERIALIZED VIEW
REINDEX
REINDEX —重建索引
概要
REINDEX [ ( option [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } [ CONCURRENTLY ] name
其中 选项 可以是以下之一:
CONCURRENTLY [ boolean ]
TABLESPACE new_tablespace
VERBOSE [ boolean ]
描述
REINDEX 使用索引表中存储的数据重建索引,替换旧索引副本。有几种情况需要使用 REINDEX:
-
索引已损坏,不再包含有效数据。虽然理论上不应该发生这种情况,但在实践中,由于软件错误或硬件故障,索引可能会损坏。
REINDEX提供了一种恢复方法。 -
索引已变得“膨胀”,即包含许多空或几乎为空的页面。在某些不常见的访问模式下,这可能会发生在 B 树索引中。
REINDEX提供了一种通过编写新版本的索引来减少索引空间消耗的方法,而不包含死页面。 -
您已更改索引的存储参数(例如 fillfactor),并希望确保更改已完全生效。
-
如果索引构建失败并使用了
CONCURRENTLY选项,则此索引将保持为“无效”。这些索引是无用的,但使用REINDEX重建它们可能很方便。请注意,只有REINDEX INDEX能够在无效索引上执行并发构建。
参数
-
INDEX
重新创建指定的索引。当与分区索引一起使用时,此形式的REINDEX不能在事务块内执行。 -
TABLE
重新创建指定表的所有索引。如果表有一个辅助的“TOAST”表,也会重新索引。当与分区表一起使用时,此形式的REINDEX不能在事务块内执行。 -
SCHEMA
重新创建指定模式的所有索引。如果此模式的表有一个辅助的“TOAST”表,也会重新索引。共享系统目录上的索引也会被处理。当与分区表一起使用时,此形式的REINDEX不能在事务块内执行。 -
DATABASE
重新创建当前数据库中的所有索引。共享系统目录上的索引也会被处理。此形式的REINDEX不能在事务块内执行。 -
SYSTEM
重新创建当前数据库中系统目录上的所有索引。共享系统目录上的索引也会被处理。用户表上的索引不会被处理。此形式的REINDEX不能在事务块内执行。 -
name
要重新索引的特定索引、表或数据库的名称。索引和表名称可以带有模式限定符。目前,REINDEX DATABASE和REINDEX SYSTEM只能重新索引当前数据库,因此它们的参数必须与当前数据库的名称匹配。 -
CONCURRENTLY
使用此选项时,UXsinoDB将重建索引,而不会锁定阻止对表进行并发插入、更新或删除的任何锁定;而标准索引重建会锁定表上的写入(但不是读取),直到完成为止。使用此选项时需要注意几个注意事项,详见下面的同时重建索引。
对于临时表,REINDEX始终是非并发的,因为没有其他会话可以访问它们,而非并发重建索引更便宜。
-
TABLESPACE
指定索引将在新表空间上重建。 -
VERBOSE
在重新索引每个索引时打印进度报告。 -
boolean
指定是否应打开或关闭所选选项。您可以写TRUE、ON或1来启用选项,写FALSE、OFF或0来禁用选项。布尔值也可以省略,在这种情况下,假定为TRUE。 -
new_tablespace
将在其中重建索引的表空间。
注释
如果您怀疑用户表上的索引已经损坏,您可以使用REINDEX INDEX或REINDEX TABLE来重建该索引或表上的所有索引。
如果需要从系统表上的索引损坏中恢复,情况会更加困难。在这种情况下,重要的是系统没有使用任何可疑的索引。(实际上,在这种情况下,您可能会发现服务器进程在启动时立即崩溃,因为它们依赖于已损坏的索引。)为了安全地恢复,必须使用-P选项启动服务器,该选项可以防止它使用索引进行系统目录查找。
一种方法是关闭服务器并启动带有-P选项的单用户UXsinoDB服务器。然后,可以发出REINDEX DATABASE、REINDEX SYSTEM、REINDEX TABLE或REINDEX INDEX,具体取决于您想要重建多少内容。如果不确定,请使用REINDEX SYSTEM来选择重建数据库中的所有系统索引。然后退出单用户服务器会话并重新启动常规服务器。
或者,可以在其命令行选项中包含-P来启动常规服务器会话。这种方法因客户端而异,但在所有基于libuxsql的客户端中,可以在启动客户端之前将UXOPTIONS环境变量设置为-P。请注意,虽然此方法不需要锁定其他客户端,但在修复完成之前,仍然可能明智地防止其他用户连接到受损的数据库。
REINDEX类似于删除并重新创建索引,因为索引内容是从头开始重建的。但是,锁定考虑因素有所不同。REINDEX锁定写入,但不锁定索引的父表的读取。它还在正在处理的特定索引上获ACCESS EXCLUSIVE锁,这将阻止尝试使用该索引的读取。特别是,查询规划器尝试在表的每个索引上获取ACCESS SHARE锁,而不管查询如何,因此REINDEX阻止几乎所有查询,除了一些已缓存其计划且不使用此索引的准备查询。相比之下,DROP INDEX瞬间在父表上获取ACCESS EXCLUSIVE锁,阻止写入和读取。随后的CREATE INDEX锁定写入,但不锁定读取;由于索引不存在,因此不会有读取尝试使用它,这意味着不会有阻塞,但读取可能被迫进入昂贵的顺序扫描。
重新索引单个索引或表需要成为该索引或表的所有者。重新索引模式或数据库需要成为该模式或数据库的所有者。特别注意,因此非超级用户可以重建其他用户拥有的表的索引。但是,作为特殊例外,当非超级用户发出REINDEX DATABASE、REINDEX SCHEMA或REINDEX SYSTEM时,将跳过共享目录上的索引,除非用户拥有该目录。目录(通常不会出现这种情况)。当然,超级用户始终可以重新索引任何内容。
使用REINDEX INDEX或REINDEX TABLE支持重新索引分区索引或分区表。指定分区关系的每个分区都在单独的事务中重新索引。在处理分区表或索引时,这些命令不能在事务块内使用。
当在分区索引或表上使用REINDEX和TABLESPACE子句时,仅更新叶分区的表空间引用。由于分区索引不会更新,因此建议单独使用ALTER TABLE ONLY对它们进行操作,以便任何新附加的分区都继承新的表空间。如果失败,则可能未将所有索引移动到新表空间。重新运行命令将重建所有叶分区并将以前未处理的索引移动到新表空间。
如果使用SCHEMA、DATABASE或SYSTEM与TABLESPACE,则会跳过系统关系,并生成单个WARNING。TOAST表上的索引将被重建,但不会移动到新表空间。
并发重建索引
重建索引可能会干扰数据库的常规操作。通常,UXsinoDB会锁定要重建索引的表,防止写入,并使用单个扫描表执行整个索引构建。其他事务仍然可以读取表,但如果它们尝试在表中插入、更新或删除行,则会阻塞,直到索引重建完成。如果系统是实时生产数据库,则可能会产生严重影响。非常大的表可能需要数小时才能被索引,即使对于较小的表,索引重建也可能会锁定写入者,时间对于生产系统来说是不可接受的。
UXsinoDB支持使用最小锁定写入重建索引。通过指定REINDEX的CONCURRENTLY选项来调用此方法。使用此选项时,UXsinoDB必须对每个需要重建的索引执行两次表扫描,并等待可能使用索引的所有现有事务的终止。此方法需要比标准索引重建更多的总工作量,并且需要更长的时间才能完成,因为它需要等待可能修改索引的未完成事务。但是,由于它允许在重建索引时继续正常操作,因此此方法对于在生产环境中重建索引非常有用。当然,索引重建所带来的额外CPU、内存和I/O负载可能会减慢其他操作。
并发重新索引中发生以下步骤。每个步骤在单独的事务中运行。如果有多个索引需要重建,则每个步骤在移动到下一个步骤之前循环遍历所有索引。
-
将新的瞬态索引定义添加到目录
ux_index中。此定义将用于替换旧索引。在处理时,对正在重新索引的索引及其关联表采取SHARE UPDATE EXCLUSIVE锁,以防止任何模式修改。 -
对每个新索引进行第一次构建索引的尝试。构建索引后,其标志
ux_index.indisready将被设置为进行了以下步骤来重建索引:首先,对于每个索引,使用一个单独的事务将其切换为“true”,以便为插入做好准备,并在执行构建的事务完成后对其他会话可见。 -
然后进行第二遍遍历,以添加在第一遍遍历运行时添加的元组。这一步也是针对每个索引单独执行的事务。
-
所有引用该索引的约束都将更改为引用新的索引定义,并更改索引的名称。此时,对于新索引,将ux_index.indisvalid切换为“true”,对于旧索引,将其切换为“false”,并进行缓存失效,导致所有引用旧索引的会话无效。旧索引的ux_index.indisready被切换为“false”,以防止任何新的元组插入
-
在等待可能引用旧索引的运行中查询完成后。
-
旧索引被删除。索引和表的
SHARE UPDATE EXCLUSIVE会话锁被释放。
如果重建索引时出现问题,例如在唯一索引中出现唯一性冲突,则REINDEX命令将失败,但会留下一个“invalid”的新索引,除了现有的索引外。由于它可能不完整,因此将忽略此索引进行查询,但仍将消耗更新开销。uxsql \d命令将报告此类索引为INVALID。
uxdb=# \d tab
Table "public.tab"
Column | Type | Modifiers
---+----+-
col | integer |
Indexes:
"idx" btree (col)
"idx_ccnew" btree (col) INVALID
如果标记为INVALID的索引后缀为ccnew,则它对应于并发操作期间创建的短暂索引,建议的恢复方法是使用DROP INDEX将其删除,然后再尝试REINDEX CONCURRENTLY。如果无效的索引后缀为ccold,则它对应于无法删除的原始索引;建议的恢复方法是仅删除该索引,因为重建已成功。
常规索引构建允许同时在同一表上进行其他常规索引构建,但是一次只能在表上进行一个并发索引构建。在这两种情况下,同时不允许对表进行任何其他类型的模式修改。另一个区别是,可以在事务块内执行常规REINDEX TABLE或REINDEX INDEX命令,但不能执行REINDEX CONCURRENTLY。
像任何长时间运行的事务一样,对表进行REINDEX可能会影响可以通过并发VACUUM从任何其他表中删除的元组。
REINDEX SYSTEM不支持CONCURRENTLY,因为系统目录不能同时重新索引。
此外,排除约束的索引无法同时重新索引。如果在此命令中直接命名此类索引,则会引发错误。如果对具有排除约束索引的表或数据库进行并发重新索引,则将跳过这些索引。(可以使用ALTER INDEX ... SET (ux15docs/fastupdate =off)命令将排除约束的索引转换为常规索引,然后再进行并发重新索引。)重新构建索引时,如果没有使用CONCURRENTLY选项,则需要排除使用该索引的所有查询。
每个运行REINDEX的后端都会在ux_stat_progress_create_index视图中报告其进度。
示例
重建单个索引:
REINDEX INDEX my_index;
重建表my_table上的所有索引:
REINDEX TABLE my_table;
重建特定数据库中的所有索引,而不信任系统索引已经有效:
$ **`export UXOPTIONS="-P"`**
$ **`uxsql broken_db`**
...
broken_db=> REINDEX DATABASE broken_db;
broken_db=> \q
重建表的索引,同时在重新索引过程中不阻止涉及的关系的读写操作:
REINDEX TABLE CONCURRENTLYmy_broken_table;
兼容性
SQL标准中没有REINDEX命令。
另请参阅
RELEASE SAVEPOINT
RELEASE SAVEPOINT — 销毁先前定义的保存点
概要
RELEASE [ SAVEPOINT ] savepoint_name
描述
RELEASE SAVEPOINT 销毁当前事务中先前定义的保存点。
销毁保存点使其不再作为回滚点可用,但它没有其他用户可见的行为。它不会撤消在保存点建立后执行的命令的影响。(要做到这一点,请参见ROLLBACK TO SAVEPOINT。)在不再需要保存点时销毁它允许系统在事务结束之前回收一些资源。
RELEASE SAVEPOINT 还会销毁在命名保存点建立后建立的所有保存点。
参数
savepoint_name
要销毁的保存点的名称。
注意事项
指定先前未定义的保存点名称是错误的。
在事务处于中止状态时,无法释放保存点。
如果多个保存点具有相同的名称,则只释放最近定义的未释放保存点。重复的命令将逐步释放较旧的保存点。
示例
建立并稍后销毁保存点:
BEGIN;
INSERT INTO table1 VALUES (3);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (4);
RELEASE SAVEPOINT my_savepoint;
COMMIT;
上述事务将插入3和4。
兼容性
该命令符合 SQL 标准。标准指定关键字 SAVEPOINT 是必需的,但 UXsinoDB允许省略它。
另请参阅
BEGIN、COMMIT、ROLLBACK、ROLLBACK TO SAVEPOINT、SAVEPOINT
REPLACE INTO
REPLACE INTO — 在表中插入并替换数据
概要
REPLACE [INTO] tbl_name
[(col_name [, col_name] ...)]
{VALUES | VALUE} (value_list) [, (value_list)] ...
REPLACE [INTO] tbl_name
SET assignment_list
REPLACE [INTO] tbl_name
[(col_name [, col_name] ...)]
SELECT ...
value:
{expr | DEFAULT}
value_list:
value [, value] ...
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
描述
Replace into的语法,作用类似insert插入操作。主要的区别是replace会根据主键或者唯一键检查数据是否存在,如果存在就先删除再更新。
示例
建表:
CREATE TABLE cities(
Id serial PRIMARY KEY,
Name VARCHAR(50),
Population INT NOT NULL
);
写入数据:
INSERT INTO cities(name,population)
VALUES('NewYork',8008278),
('LosAngeles',3694825),
('SanDiego',1223405);
使用replace写入数据:
uxdb=# REPLACE INTO cities(name,population) VALUES('Phoenix',1321523);
INSERT 0 1
uxdb=# SELECT * FROM cities;
id | name | population
----+--+--
1 | NewYork | 8008278
2 | LosAngeles | 3694825
3 | SanDiego | 1223405
4 | Phoenix | 1321523
(4 rows)
使用replace更新数据:
REPLACE INTO cities SET id=4,name='Phoenix',population=1768980;
INSERT 0 2
使用replace语句拷贝数据:
REPLACE INTO cities(name,population) SELECT name,population FROM cities WHERE id=1;
INSERT 0 1
RESET
RESET — 将运行时参数的值恢复为默认值
概要
RESET configuration_parameter
RESET ALL
描述
RESET 将运行时参数恢复为它们的默认值。RESET 是SET configuration_parameter TO DEFAULT的另一种拼写方式。有关详细信息,请参见SET。
默认值被定义为参数在当前会话中从未发出过 SET命令时的值。实际的值来源可能是编译时默认值、配置文件、命令行选项或每个数据库或每个用户的默认设置。这与将其定义为“参数在会话开始时的值”略有不同,因为如果该值来自配置文件,则它将被重置为配置文件现在指定的任何值。
RESET 的事务行为与 SET 相同:它的效果将被事务回滚撤消。
参数
-
configuration_parameter
可设置的运行时参数的名称。SET 参考页面中有文档记录。 -
ALL
将所有可设置的运行时参数重置为默认值。
示例
将 timezone 配置变量设置为其默认值:
RESET time
zone;
兼容性
RESET 是 UXsinoDB 的扩展。
另请参阅
REVOKE
REVOKE — 撤销访问权限
概要
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
[, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON { SEQUENCE sequence_name [, ...]
| ALL SEQUENCES IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON DOMAIN domain_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER fdw_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER server_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ EXECUTE | ALL [ PRIVILEGES ] }
ON { { FUNCTION | PROCEDURE | ROUTINE } function_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
| ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON LANGUAGE lang_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
ON LARGE OBJECT loid [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SET | ALTER SYSTEM } [, ...] | ALL [ PRIVILEGES ] }
ON PARAMETER configuration_parameter [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
ON SCHEMA schema_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ CREATE | ALL [ PRIVILEGES ] }
ON TABLESPACE tablespace_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON TYPE type_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ ADMIN OPTION FOR ]
role_name [, ...] FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ] ALTER ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ CASCADE | RESTRICT ]
其中role_specification取值如下:
[ GROUP ] role_name
| PUBLIC
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
描述
REVOKE命令从一个或多个角色中撤销先前授予的特权。关键字PUBLIC指的是所有角色的隐式定义组。
有关特权类型的含义,请参见GRANT命令的描述。
请注意,任何特定角色将具有直接授予它的特权总和,授予给它当前是成员的任何角色的特权以及授予给PUBLIC的特权。因此,例如,从PUBLIC中撤销SELECT特权并不一定意味着所有角色都将失去该特权。已经失去了对对象的SELECT 权限:那些直接或通过其他角色授予该权限的用户仍将拥有该权限。同样,从用户中撤销 SELECT 权限可能无法阻止该用户使用SELECT,如果 PUBLIC 或其他成员角色仍具有 SELECT 权限的话。
如果指定了 GRANT OPTION FOR,则仅撤销授予权限,而不是权限本身。否则,权限和授予权限都将被撤销。
如果用户持有具有授予权限的权限并将其授予其他用户,则这些其他用户持有的权限称为依赖权限。如果第一个用户持有的权限或授予权限正在被撤销并且存在依赖权限,则如果指定了CASCADE,这些依赖权限也将被撤销;如果没有,则撤销操作将失败。这种递归撤销仅影响通过可追溯到此 REVOKE命令的主题用户的用户链授予的权限。因此,如果该权限也通过其他用户授予,则受影响的用户可能会有效地保留该权限。
在撤销表上的权限时,相应的列权限(如果有)也将自动撤销表的每个列上的权限。另一方面,如果角色已被授予表上的权限,则从单个列中撤销相同的权限将不会产生任何影响。
在撤销角色的成员身份时,GRANT OPTION 被称为 ADMIN OPTION,但行为类似。该命令的这种形式还允许 GRANTED BY 选项,但该选项目前被忽略(除了检查命名角色的存在)。
还要注意,该命令的这种形式不允许在 role_specification中使用噪声词 GROUP。
注意事项
用户只能撤销由该用户直接授予的权限。例如,如果用户 A 授予了具有授予权限的权限给用户 B,而用户 B又将其授予给用户 C,则用户 A 无法直接从 C 撤销权限。相反,用户 A 可以从用户 B 撤销授予权限,并使用 CASCADE选项,以便从用户 C 中撤销权限。另一个例子,如果 A 和 B 都向 C 授予了相同的权限,则 A可以撤销自己的授予,但无法撤销 B 的授予,因此 C 仍然有效地拥有该权限。
当非对象所有者尝试在对象上撤销权限时,如果用户在对象上没有任何权限,则该命令将直接失败。只要有一些权限可用,该命令就会继续进行,但它只会撤销用户具有授予权限的那些权限。如果未持有任何授予权限,则REVOKE ALL PRIVILEGES形式将发出警告消息,而其他形式将发出警告,如果未持有命令中明确命名的任何权限的授予权限。(原则上,这些语句也适用于对象所有者,但由于所有者始终被视为持有所有授予权限,因此永远不会出现这种情况。)
如果超级用户选择发出 GRANT 或 REVOKE命令,则该命令将被执行,就好像受影响的对象的所有者发出了该命令一样。由于所有权限最终都来自对象所有者(可能是通过授予权限链间接传递的),因此超级用户可以撤销所有权限,但这可能需要使用如上所述的CASCADE。
REVOKE也可以由不是受影响对象的所有者的角色执行,但是该角色是拥有该对象的角色的成员,或者是拥有特权的角色的成员WITH GRANT OPTION。在这种情况下,该命令的执行就像是由实际拥有对象或拥有特权WITH GRANT OPTION的包含角色发出的一样。例如,如果表t1由角色g1拥有,而角色u1是其成员,则u1可以撤销在t1上记录为由g1授予的权限。这将包括由u1以及角色g1的其他成员授予的授权。
如果执行REVOKE的角色通过多个角色成员路径间接持有特权,则未指定将使用哪个包含角色来执行该命令。在这种情况下,最好使用SET ROLE成为要执行REVOKE的特定角色。否则可能会导致撤销除您想要的权限之外的权限,或者根本不撤销任何权限。
示例
撤销公共表films上的插入权限:
REVOKE INSERT ON films FROM PUBLIC;
撤销用户manuel在视图kinds上的所有权限:
REVOKE ALL PRIVILEGES ON kinds FROM manuel;
请注意,这实际上意味着“撤销我授予的所有权限”。
从用户joe中撤销角色admins的成员身份:
REVOKE admins FROM joe;
兼容性
与GRANT命令的兼容性说明类似适用于REVOKE。标准要求使用关键字RESTRICT或CASCADE,但是UXsinoDB默认使用RESTRICT。
另请参见
GRANT,ALTER DEFAULT PRIVILEGES
ROLLBACK
ROLLBACK - 中止当前事务
概要
ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
描述
ROLLBACK 中止当前事务并导致事务所做的所有更新被丢弃。
参数
-
WORK
TRANSACTION
可选关键字。它们没有任何影响。 -
AND CHAIN
如果指定了AND CHAIN,则会立即启动一个新事务,其事务特性(参见SET TRANSACTION)与刚刚完成的事务相同。否则,不会启动新事务。
注意事项
使用 COMMIT成功终止事务。
在事务块之外发出 ROLLBACK 会发出警告,否则没有任何影响。在事务块之外发出 ROLLBACK AND CHAIN 是错误的。
示例
要中止所有更改:
ROLLBACK;
兼容性
命令 ROLLBACK 符合 SQL 标准。形式 ROLLBACK TRANSACTION 是 UXsinoDB的扩展。
另请参阅
BEGIN、COMMIT、ROLLBACK TO SAVEPOINT
ROLLBACK PREPARED
ROLLBACK PREPARED — 取消之前准备好的两阶段提交事务
概要
ROLLBACK PREPARED transaction_id
描述
ROLLBACK PREPARED 回滚处于准备状态的事务。
参数
transaction_id
要回滚的事务标识符。
注意事项
要回滚准备好的事务,必须是执行该事务的相同用户或超级用户。但是,您不必在执行事务的同一会话中。
此命令不能在事务块内执行。准备好的事务会立即回滚。
所有当前可用的准备好的事务都列在ux_prepared_xacts系统视图中。
示例
回滚由事务标识符 foobar 标识的事务:
ROLLBACK PREPARED 'foobar';
兼容性
ROLLBACK PREPARED 是 UXsinoDB 的扩展。它旨在供外部事务管理系统使用,其中一些系统受标准(如 X/Open XA)的覆盖,但这些系统的 SQL 方面未经标准化。
另请参阅
PREPARE TRANSACTION,COMMIT PREPARED
ROLLBACK TO SAVEPOINT
ROLLBACK TO SAVEPOINT — 回滚到保存点
概述
ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] savepoint_name
描述
回滚到建立保存点之后执行的所有命令。保存点仍然有效,如果需要,可以再次回滚到保存点。
ROLLBACK TO SAVEPOINT 隐式销毁了在指定保存点之后建立的所有保存点。
参数
savepoint_name
要回滚到的保存点。
注意事项
使用RELEASE SAVEPOINT销毁保存点,而不丢弃建立保存点之后执行的命令的影响。
指定未建立的保存点名称是错误的。
游标在保存点方面具有某些非事务性行为。在保存点内打开的任何游标都将在回滚保存点时关闭。如果先前打开的游标受到稍后回滚的保存点内的 FETCH或 MOVE 命令的影响,则游标仍然停留在 FETCH 指向的位置(即,FETCH引起的游标移动不会回滚)。回滚不会撤消关闭游标的操作。但是,游标查询引起的其他副作用(例如查询调用的易失性函数的副作用)会在稍后回滚的保存点期间回滚。执行事务导致事务中止的游标被置于无法执行状态,因此虽然可以使用ROLLBACK TO SAVEPOINT 恢复事务,但不能再使用游标。
示例
撤销在 my_savepoint 建立之后执行的命令:
ROLLBACK TO SAVEPOINT my_savepoint;
光标位置不受保存点回滚的影响:
BEGIN;
DECLARE foo CURSOR FOR SELECT 1 UNION SELECT 2;
SAVEPOINT foo;
FETCH 1 FROM foo;
?column?
1
ROLLBACK TO SAVEPOINT foo;
FETCH 1 FROM foo;
?column?
2
COMMIT;
兼容性
SQL 标准指定关键字 SAVEPOINT 是强制性的,但是 UXsinoDB 和 Oracle 允许省略它。SQL 仅允许在ROLLBACK 之后使用 WORK,而不是 TRANSACTION。此外,SQL 还有一个可选的子句 AND [ NO ]CHAIN,目前 UXsinoDB 不支持。否则,此命令符合 SQL标准。
另请参阅
BEGIN、COMMIT、RELEASE SAVEPOINT、ROLLBACK、SAVEPOINT
SAVEPOINT
SAVEPOINT — 在当前事务中定义一个新的保存点
概要
SAVEPOINT savepoint_name
描述
SAVEPOINT 在当前事务中定义一个新的保存点。
保存点是事务中的一个特殊标记,允许在它建立之后执行的所有命令都可以回滚,将事务状态恢复到保存点建立时的状态。
参数
savepoint_name
新保存点的名称。如果已经存在具有相同名称的保存点,则它们将无法访问,直到新的同名保存点被释放。
注意事项
使用ROLLBACK TO SAVEPOINT回滚到保存点。使用RELEASE SAVEPOINT销毁保存点,保留建立之后执行的命令的效果。
只有在事务块内部才能建立保存点。一个事务中可以定义多个保存点。
示例
建立一个保存点,稍后撤消建立之后执行的所有命令的效果:
BEGIN;
INSERT INTO table1 VALUES (1);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (2);
ROLLBACK TO SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (3);
COMMIT;
上述事务将插入值1和3,但不会插入2。
建立并稍后销毁一个保存点:
BEGIN;
INSERT INTO table1 VALUES (3);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (4);
RELEASE SAVEPOINT my_savepoint;
COMMIT;
上述事务将插入值3和4。
使用单个保存点名称:
BEGIN;
INSERT INTO table1 VALUES (1);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (2);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (3);
-- 回滚到第二个保存点
ROLLBACK TO SAVEPOINT my_savepoint;
SELECT * FROM table1; -- 显示行1和行2
-- 释放第二个保存点
RELEASE SAVEPOINT my_savepoint;
-- 回滚到第一个保存点
ROLLBACK TO SAVEPOINT my_savepoint;
SELECT * FROM table1; -- 仅显示行1
COMMIT;
上述事务首先回滚第3行,然后回滚第2行。
兼容性
SQL要求在建立具有相同名称的另一个保存点时自动销毁保存点。在UXsinoDB中,旧的保存点被保留,但只有最近的保存点在回滚或释放时才会使用。(使用RELEASE SAVEPOINT释放较新的保存点将使旧的保存点再次可用于ROLLBACK TO SAVEPOINT和RELEASE SAVEPOINT。)否则,SAVEPOINT完全符合SQL。
另请参阅
BEGIN、COMMIT、RELEASE SAVEPOINT、ROLLBACK、ROLLBACK TO SAVEPOINT
SECURITY LABEL
SECURITY LABEL - 定义或更改应用于对象的安全标签
概要
SECURITY LABEL [ FOR provider ] ON
{
TABLE object_name |
COLUMN table_name.column_name |
AGGREGATE aggregate_name ( aggregate_signature ) |
DATABASE object_name |
DOMAIN object_name |
EVENT TRIGGER object_name |
FOREIGN TABLE object_name
FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
LARGE OBJECT large_object_oid |
MATERIALIZED VIEW object_name |
[ PROCEDURAL ] LANGUAGE object_name |
PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
PUBLICATION object_name |
ROLE object_name |
ROUTINE routine_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] |
SCHEMA object_name |
SEQUENCE object_name |
SUBSCRIPTION object_name |
TABLESPACE object_name |
TYPE object_name |
VIEW object_name
} IS 'label'
其中 aggregate_signature 是:
* |
[ argmode ] [ argname ] argtype [ , ... ] |
[ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ]
描述
SECURITY LABEL将安全标签应用于数据库对象。可以将任意数量的安全标签(每个标签提供程序一个)与给定的数据库对象关联起来。标签提供程序是可加载的模块,它们通过使用函数register_label_provider进行注册。
注意
register_label_provider不是SQL函数;它只能从加载到后端的C代码中调用。
标签提供程序确定给定标签是否有效,以及是否允许将该标签分配给给定对象。同样,给定标签的含义也由标签提供程序决定。UXsinoDB不对标签提供程序必须如何解释安全标签施加任何限制;它只提供了一种存储它们的机制。实际上,此功能旨在允许与基于标签的强制访问控制(MAC)系统(如SELinux)集成。这些系统基于对象标签而不是传统的自主访问控制(DAC)概念(如用户和组)做出所有访问控制决策。
参数
-
object_name
table_name.column_name
aggregate_name
function_name
procedure_name
routine_name
要标记的对象的名称。驻留在模式(表、函数等)中的对象名称可以带有模式限定符。 -
provider
要将此标签与之关联的提供程序的名称。命名的提供程序必须已加载并且必须同意所提议的标记操作。如果只加载了一个提供程序,则可以省略提供程序名称以缩短长度。 -
argmode
函数、过程或聚合参数的模式:IN、OUT、INOUT或VARIADIC。如果省略,则默认为IN。请注意,SECURITY LABEL实际上不会关注OUT参数,因为只需要输入参数来确定函数的身份。因此,列出IN、INOUT和VARIADIC参数就足够了。 -
argname
函数、过程或聚合参数的名称。请注意,SECURITY LABEL实际上不会关注参数名称,因为只需要参数数据类型来确定函数的身份。argtype函数、过程或聚合参数的数据类型。 -
large_object_oid
大对象的 OID。 -
PROCEDURAL
这是一个噪声词。 -
label
新的安全标签,写成字符串字面量;或者NULL以删除安全标签。
示例
以下示例显示如何更改表的安全标签。
SECURITY LABEL FOR selinux ON TABLE mytable IS 'system_u:object_r:seuxsql_table_t:s0';
兼容性
SQL 标准中没有 SECURITY LABEL命令。
SELECT
SELECT, TABLE, WITH — 从表或视图中检索行
概要
[ WITH [ RECURSIVE ] with_query [, ...] ]
| [ WITH [ { PROCEDURE | FUNCTION } with_func_query [, ...] ] ]
SELECT [ ALL | DISTINCT | UNIQUE [ ON ( expression [, ...] ) ] ]
[ TOP n [, m | ( m ) ] ]
| [ TOP ( n ) [, m | ( m ) ] ]
[ * | expression [ [ AS ] output_name ] [, ...] ]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ START WITH condition CONNECT BY [ NOCYCLE ] condition ]
| [ CONNECT BY [ NOCYCLE ] condition [ START WITH condition ] ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition ]
[ WINDOW window_name AS ( window_definition ) [, ...] ]
[ { UNION | INTERSECT | EXCEPT | MINUS } [ ALL | DISTINCT ] select ]
[ ORDER [ SIBLINGS ] BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ]
[ OFFSET start [ ROW | ROWS ] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES } ]
[ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED | WAIT wait_time] [...] ]
其中 from_item 是以下之一:
[ ONLY ] table_name [ PARTITION ( partition_table_name ) | SUBPARTITION ( subpartition_table_name ) ] [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ ONLY ] table_name [ [ AS ] alias ] [ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] | SAMPLE [ BLOCK ] ( sample_percent ) [ SEED ( seed_value ) ] ]
[ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ LATERAL ] function_name ( [ argument [, ...] ] )
[ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias ( column_definition [, ...] )
[ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
[ LATERAL ] ROWS FROM( function_name ( [ argument [, ...] ] ) [ AS ( column_definition [, ...] ) ] [, ...] )
[ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ from_item PIVOT ( pivot_clause pivot_for_clause pivot_in_clause ) [ alias ] ]
[ from_item UNPIVOT [ { INCLUDE | EXCLUDE } NULLS ] ( unpivot_value_clause unpivot_for_clause unpivot_in_clause) [ [ AS ] alias [ ( column_alias [, ...] ) ] ] ]
from_item join_type from_item { ON join_condition | USING ( join_column [, ...] ) [ AS join_using_alias ] }
from_item NATURAL join_type from_item
from_item CROSS JOIN from_item
其中 pivot_clause 是:
agg_func_expression ( expr ) [ [ AS ] output_name ] [, ...]
其中 pivot_for_clause 是:
FOR { pivot_column | ( pivot_column [, ...] ) }
其中 pivot_in_clause 是:
IN ( [ const_expression [ [ AS ] output_name ] [, ...] ] )
其中 unpivot_value_clause 是:
{ column_name | ( column_name [, ...] ) }
其中 unpivot_for_clause 是:
FOR { output_column | ( output_column [, ...] ) }
其中 unpivot_in_clause 是:
IN ( input_data_column [ AS constant ] [, ...] )
其中 grouping_element是以下之一:
( )
expression
( expression [, ...] )
ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
CUBE ( { expression | ( expression [, ...] ) } [, ...] )
GROUPING SETS ( grouping_element [, ...] )
其中 with_func_query 是:
func_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
[ RETURNS rettype
| RETURNS TABLE ( column_name column_type [, ...] ) ]
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| WINDOW
| IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
| CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| PARALLEL { UNSAFE | RESTRICTED | SAFE }
| COST execution_cost
| ROWS result_rows
| SUPPORT support_function
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| { AS | IS } 'definition'
| { AS | IS } 'obj_file', 'link_symbol'
}
其中 with_query 是:
with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( select | values | insert | update | delete )
[ SEARCH { BREADTH | DEPTH } FIRST BY column_name [, ...] SET search_seq_col_name ]
[ CYCLE column_name [, ...] SET cycle_mark_col_name [ TO cycle_mark_value DEFAULT cycle_mark_default ] USING cycle_path_col_name ]
TABLE [ ONLY ] table_name [ * ]
描述
SELECT 从零个或多个表中检索行。SELECT 的一般处理如下:
-
计算
WITH列表中的所有查询。这些实际上充当可以在FROM列表中引用的临时表。在FROM中多次引用的WITH查询将只计算一次。(除非使用NOT MATERIALIZED进行指定,否则只计算一次。(请参见下面的WITH子句 。) -
计算
FROM列表中的所有元素。(FROM列表中的每个元素都是实际或虚拟表。) 如果在FROM列表中指定了多个元素,则它们会交叉连接在一起。(请参见下面的FROM子句 。) -
如果指定了
WHERE子句,则会从输出中消除不满足条件的所有行。(请参见下面的 WHERE子句。) -
如果指定了
GROUP BY子句,或者存在聚合函数调用, 则将输出组合成匹配一个或多个值的行组,并计算聚合函数的结果。如果存在HAVING子句,则会消除不满足给定条件的组。(请参见下面的 GROUP BY子句和 HAVING子句。) -
使用
SELECT输出表达式计算每个选定行或行组的实际输出行。(请参见下面的 SELECT列表。) -
SELECT DISTINCT从结果中消除重复行。SELECT DISTINCT ON消除匹配所有指定表达式的行。SELECT ALL(默认)将返回所有候选行,包括重复项。(请参见下面的 DISTINCT 子句。) -
使用运算符
UNION、INTERSECT和EXCEPT, 可以将多个SELECT语句的输出组合成单个结果集。UNION运算符返回在一个或两个结果集中的所有行。INTERSECT运算符返回严格在两个结果集中的所有行。EXCEPT运算符返回在第一个结果集中但不在第二个结果集中的行。在这三种情况下,除非指定了ALL,否则会消除重复行。可以添加噪声词DISTINCT来明确指定消除重复行。请注意,即使SELECT本身的默认值是ALL, 但在这里默认行为是DISTINCT。(请参见下面的 UNION子句,INTERSECT子句 和 EXCEPT子句。) -
如果指定了
ORDER BY子句,则返回的行按指定顺序排序。如果未给出ORDER BY,则系统将以最快的方式返回行。(请参见下面的 ORDER BY子句。) -
如果指定了
LIMIT(或FETCH FIRST)或OFFSET子句,则SELECT语句仅返回结果行的子集。(请参见下面的LIMIT子句。) -
如果指定了
FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE或FOR KEY SHARE,则SELECT语句会针对所选行进行锁定,以防止并发更新。(请参见下面的锁定子句。) -
在oracle兼容模式下,子查询支持查询rowid。
SELECT查询隐藏列时需要显式指定隐藏列名称,rowid属于隐藏列,当前可以在子查询中不显式指定rowid,但在主查询中显式指定时返回rowid的值。
您必须对SELECT命令中使用的每个列具有SELECT权限。使用FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE或FOR KEY SHARE还需要UPDATE权限(对于所选每个表的至少一个列)。
参数
WITH子句
WITH子句允许您指定一个或多个子查询,这些子查询可以在主查询中按名称引用。这些子查询实际上充当主查询的临时表或视图。每个子查询可以是SELECT、TABLE、VALUES、INSERT、UPDATE或DELETE语句。在WITH中编写数据修改语句(INSERT、UPDATE或DELETE)时,通常会包括一个RETURNING子句。是RETURNING的输出,而不是语句修改的底层表,形成了主查询读取的临时表。如果省略RETURNING,则仍会执行该语句,但它不会产生输出,因此无法由主查询引用为表。
必须为每个WITH查询指定名称(不带模式限定符)。可以选择指定列名列表;如果省略,则从子查询中推断列名。
如果指定了RECURSIVE,则允许SELECT子查询按名称引用自身。这样的子查询必须具有以下形式:
non_recursive_term UNION [ ALL | DISTINCT ] recursive_term
[SEARCH {BREADTH |DEPTH } FIRST BY c_alias [,c_alias] … SET ordering_column]
[CYCLE c_alias [,c_alias] SET cycle_mark_c_alias [TO cycle_value DEFAULT no_cycle_value] USING cycle_path_col_name]
SELECT … FROM with_query_name;
其中递归自引用必须出现在UNION的右侧。每个查询只允许一个递归自引用。不支持递归数据修改语句,但可以在数据修改语句中使用递归SELECT查询的结果。
RECURSIVE的另一个效果是WITH查询不需要排序:查询可以引用列表中后面的另一个查询。(但是,不实现循环引用或相互递归。)没有RECURSIVE,WITH查询只能引用兄弟WITH查询。在WITH 列表中较早的查询将优先执行。
WITH RECURSIVE AS语句带SEARCH和CYCLE时,可以指定递归查询的顺序控制和循环检测,两个语句都要在递归查询下才能使用。search语句可以指定按照深度优先或者广度优先的方式来进行递归查询;cycle语句可以检测递归查询中的环,并终止对形成环的元组的递归查询。其中,c_alias用于更改查询顺序和检测环的列;ordering_column用于记录查询顺序的列;cycle_mark_c_alias用于记录是否有环的列;cycle_value表示有环时列cycle_mark_c_alias中的值;no_cycle_value表示无环时列cycle_mark_c_alias中的值;cycle_path_col_name用于记录查询顺序的列。
uxdb的对于访问顺序的表现为以访问过的元组以访问顺序组成的数组。
当 WITH 子句中有多个查询时,RECURSIVE 只需在 WITH后立即编写一次。它适用于 WITH 子句中的所有查询,但对不使用递归或前向引用的查询没有影响。
可选的 SEARCH子句计算一个搜索序列列,可用于按广度优先或深度优先顺序排序递归查询的结果。提供的列名列表指定要用于跟踪已访问行的行键。名为search_seq_col_name 的列将添加到 WITH查询的结果列列表中。可以在外部查询中按此列排序以实现相应的排序。
可选的 CYCLE 子句用于检测递归查询中的循环。提供的列名列表指定要用于跟踪已访问行的行键。名为cycle_mark_col_name的列将添加到 WITH 查询的结果列列表中。当检测到循环时,此列将设置为cycle_mark_value,否则设置为cycle_mark_default。此外,在检测到循环时,递归联合的处理将停止。cycle_mark_value和 cycle_mark_default 必须是常量,并且它们必须可强制转换为公共数据类型,数据类型必须具有不等运算符。(SQL标准要求它们是布尔常量或字符字符串,但 UXsinoDB 不要求如此。)默认情况下,使用 TRUE 和FALSE(类型为 boolean)。此外,名为 cycle_path_col_name的列将添加到 WITH查询的结果列列表中。此列用于内部跟踪已访问的行。
SEARCH 和 CYCLE 子句仅适用于递归 WITH 查询。with_query必须是两个SELECT(或等效命令)的 UNION(或 UNION ALL)(没有嵌套的UNION)。如果同时使用两个子句,则由 SEARCH 子句添加的列出现在由 CYCLE子句添加的列之前。
主查询和 WITH 查询都(概念上)在同一时间执行。这意味着从 WITH中的数据修改语句中看不到其他查询部分的效果,除非读取其RETURNING 输出。如果两个这样的数据修改语句尝试修改同一行,则结果是未指定的。
WITH查询的一个关键属性是,它们通常仅在主查询的每次执行中评估一次,即使主查询多次引用它们。特别地,保证执行数据修改语句一次且仅一次,无论主查询是否引用它们。读取其所有或任何输出。
然而,可以将WITH查询标记为NOTMATERIALIZED以删除此保证。在这种情况下,WITH查询可以像主查询中的简单子SELECT一样折叠到主查询中的FROM子句中。如果主查询多次引用该WITH查询,则会导致重复计算;但是,如果每个这样的使用仅需要WITH查询的少数行总输出,则NOTMATERIALIZED可以通过允许联合优化查询来提供净节省。如果将NOT MATERIALIZED附加到递归或不是无副作用的(即不是包含任何易失性函数的普通SELECT)WITH查询,则将忽略它。
默认情况下,如果在主查询的FROM子句中恰好使用一次无副作用的WITH查询,则将其折叠到主查询中。这允许在那些在语义上应该是不可见的情况下对两个查询级别进行联合优化。但是,可以通过将WITH查询标记为MATERIALIZED来防止这种折叠。例如,如果WITH查询用作优化障碍以防止规划器选择错误的计划,则可能会有用。
UXsinoDB之前的版本从未进行过这样的折叠,因此为旧版本编写的查询可能依赖于WITH作为优化障碍的作用。
TOP子句
在使用select语句时,可以使用top子句来进行筛选结果。
top_item的语法如下所示。
([ ( ] n [ ) ] ) [ , [ ( ] m [ ) ]]
n和m的类型是int,仅支持正整数。
-
TOP n表示选择结果集的前n条记录。 -
TOP n,m表示选择第n条记录之后的m条记录。
注意
TOP子句不能与LIMIT同时出现在查询语句中。
FROM子句
FROM 子句指定一个或多个用于SELECT的源表。如果指定了多个源,则结果是所有源的笛卡尔积(交叉连接)。但通常会添加限定条件(通过WHERE)以将返回的行限制为笛卡尔积的一个小子集。
FROM子句可以包含以下元素:
-
table_name
现有表或视图的名称(可选模式限定)。如果在表名之前指定了ONLY,则仅扫描该表。如果未指定ONLY,则扫描该表及其所有后代表(如果有)。可以在表名后指定*,以明确表示包括后代表。也兼容oracle中table的用法(表名作为table函数的参数传递进去)。 -
PARTITION(partition_table_name)|SUBPARTITION(subpartition_table_name)
在查询时使用partition/subpartition关键字时,可以查询出指定分区名的分区表(指定子分区名的子分区表)的内容,括号内查询的表为from 中查询表的分区表,若两张表无关联则报错。
由于兼容模式的分区表名会自动被修改(保证唯一性),此处括号中,即可查询自动修改后的分区表名,也可查询创建时指定的分区表名。
-
alias
包含别名的FROM项的替代名称。别名用于简洁或消除自连接的歧义(其中同一表多次扫描)。提供别名时,它完全隐藏表或函数的实际名称;例如,给定FROM foo AS f,SELECT的其余部分必须引用此FROM项作为f而不是foo。如果编写了别名,则还可以编写列别名列表,以提供表的一个或多个列的替代名称。 -
[ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] | SAMPLE [ BLOCK ] ( sample_percent ) [ SEED ( seed_value ) ]
table_name之后的TABLESAMPLE子句或SAMPLE子句分别表示应该用指定的sampling_method来检索表中行的子集或者表示允许您从数据库的表中的随机数据样本中进行选择,而不是从整个表中进行选择。这个抽样在应用任何其他过滤器之前进行,例如WHERE子句。标准的UXsinoDB 发行版包括两种抽样方法:BERNOULLI和SYSTEM,其他抽样方法可以通过扩展安装到数据库中。
BERNOULLI 和 SYSTEM 抽样方法都接受一个单独的argument或者sample_percent,它是要抽样的表的比例,表示为 0 到 100之间的百分比。这个参数可以是任何实值表达式。(其他抽样方法可能接受更多或不同的参数。)这两种方法都返回一个随机选择的表样本,其中包含大约指定百分比的表行。BERNOULLI 方法扫描整个表,并以指定的概率独立选择或忽略单个行。SYSTEM方法使用块级抽样,每个块都有指定的被选择的机会;返回每个选定块中的所有行。当指定小的抽样百分比时,SYSTEM方法比 BERNOULLI 方法快得多,但由于聚类效应,它可能会返回一个不太随机的表样本。SAMPLE子句如果有BLOCK,那么使用的抽样方法为SYSTEM,否则为BERNOULLI。
可选的 REPEATABLE 子句或 SEED 子句指定用于在抽样方法中生成随机数的 seed 或者 seed_value 数字或表达式。种子值可以是任何非空浮点值。如果两个查询指定相同的种子和 argument 或者 sample_percent 值,则在表没有同时更改的情况下,它们将选择相同的表样本。但是不同的种子值通常会产生不同的样本。如果未给出REPEATABLE或 SEED,则每个查询都会基于系统生成的种子选择一个新的随机样本。请注意,一些附加的抽样方法不接受REPEATABLE,并且每次使用时都会产生新的样本。
-
select
子查询可以出现在FROM子句中。这就像它的输出在此单个SELECT命令的持续时间内被创建为临时表一样。请注意,子查询必须用括号括起来,并且必须为其提供别名。也可以在这里使用VALUES 命令。 -
with_query_name
通过编写查询的名称来引用WITH查询,就像查询的名称是表名一样。(实际上,WITH查询在主查询的目的上隐藏了同名的任何真实表。如果必要,可以通过模式限定表的名称来引用同名的真实表。)可以像为表提供别名一样提供别名。 -
function_name
函数调用可以出现在FROM子句中。(这对于返回结果集的函数特别有用,但任何函数都可以使用。)这就像函数的输出在单个SELECT命令的持续时间内被创建为临时表一样。如果函数的结果类型是组合类型(包括具有多个OUT参数的情况),则每个属性都成为隐式表中的单独列。
当在函数调用中添加可选的 WITH ORDINALITY 子句时,将附加一个类型为 bigint的附加列到函数的结果列中。该列对函数的结果集进行编号,从 1开始。默认情况下,此列的名称为 ordinality。
可以像为表一样提供别名。如果写入别名,则还可以编写列别名列表,以为函数的复合返回类型的一个或多个属性提供替代名称,包括序号列(如果存在)。
多个函数调用可以通过将它们用 ROWS FROM( ... ) 包围来组合成单个 FROM子句项。这样一个项的输出是每个函数的第一行的连接,然后是每个函数的第二行等等。如果某些函数产生的行数少于其他函数,则用空值替换缺失的数据,以使返回的行数总数始终与产生最多行的函数相同。
如果函数被定义为返回 record 数据类型,则必须存在别名或关键字 AS,后跟形式为 ( column_namedata_type [, ... ]) 的列定义列表。列定义列表必须与函数返回的实际列数和类型匹配。
在使用 ROWS FROM( ... ) 语法时,如果其中一个函数需要列定义列表,则最好将列定义列表放在函数调用后面的 ROWS FROM( ... ) 中。只有一个函数且没有 WITH ORDINALITY 子句时,才能在 ROWS FROM( ... )结构后放置列定义列表。
要将 ORDINALITY 与列定义列表一起使用,必须使用 ROWS FROM( ... ) 语法,并将列定义列表放在 ROWS FROM( ... ) 中。
-
join_type
其中之一 -
[ INNER ] JOIN -
LEFT [ OUTER ] JOIN -
RIGHT [ OUTER ] JOIN -
FULL [ OUTER ] JOIN
对于 INNER 和 OUTER 连接类型,必须指定连接条件,即恰好一个 ON join_condition、USING (join_column [, ...]) 或 NATURAL。请参见下面的含义。
JOIN 子句将两个 FROM子句中的表组合在一起。项目,为方便起见,我们将其称为“表”,但实际上它们可以是任何类型的FROM项目。如有必要,请使用括号确定嵌套顺序。在没有括号的情况下,JOIN从左到右嵌套。无论如何,JOIN比分隔FROM列表项的逗号更紧密地绑定。所有JOIN选项都只是符号上的便利,因为它们不能做任何你不能用纯FROM和WHERE做的事情。
LEFT OUTER JOIN返回合格笛卡尔积中的所有行(即通过其连接条件的所有组合行),以及左侧表中没有通过连接条件的右侧行的每个副本。通过插入右侧列的空值,将左侧行扩展到连接表的完整宽度。请注意,只有JOIN子句自己的条件在决定哪些行具有匹配项时才会被考虑。外部条件是之后应用的。除了LEFT OUTER JOIN语法,左连接还可以在连接条件右侧应用外连接操作符(+)作为where条件。
相反,RIGHT OUTER JOIN返回所有连接的行,以及每个未匹配的右侧行的一行(在左侧扩展为null)。除了RIGHT OUTER JOIN语法,右连接还可以在连接条件左侧应用外连接操作符(+)作为where条件。这只是一个符号上的便利,因为你可以通过交换左右表将其转换为LEFT OUTER JOIN。
左连接示例如下:
select * from t_A a,t_B b where a.id=b.id(+);
where子句:
Oracle更推荐使用outer join语法代替join操作符(+),outer join语句使用Oracle join操作符(+)的时候有下列的限制,这些条件不在from子句的outer join语法上生效:
-
Join操作符(+)不能和from子句中的左右连接语法、内连接语法同时使用,同时使用会报错。 -
有多个连接条件的两个表在连接的时候如果没有都写上(+),那么Oracle认为是等值内连接。
-
操作符(+)不能在单表上使用。
-
不允许操作符(+)和or操作符同时使用。
-
(+)操作符只能应用在列上,不能应用在表达式上。但是,表达式上可以包含一个或多个(+)操作符。
FULL OUTER JOIN返回所有连接的行,加上每个未匹配的左侧行的一行(在右侧扩展为null),加上每个未匹配的右侧行的一行(在左侧扩展为null)。
-
ON join_condition
join_condition是一个表达式,其结果为布尔类型的值(类似于WHERE子句),指定哪些连接中的行被认为是匹配的。 -
USING ( join_column [, ...] ) [ AS join_using_alias ]
形式为USING(a,b,...)的子句是ON left_table.a = right_table.a AND left_table.b = right_table.b...的简写。此外,USING意味着只有每对等效列中的一个将包含在连接输出中,而不是两个都包含。
如果指定了join_using_alias名称,则为连接列提供表别名。只有在USING子句中列出的连接列才可通过此名称寻址。与常规别名不同,这不会将连接表的名称从查询的其余部分隐藏。与常规别名不同,您不能编写列别名列表。连接列的输出名称与它们在USING列表中出现的名称相同。
-
NATURAL
NATURAL是一个简写,用于列出具有匹配名称的两个表中的所有列的USING列表。如果没有共同的列名,则NATURAL等效于ON TRUE。 -
CROSS JOIN
CROSS JOIN等效于INNER JOIN ON(TRUE),即没有行被资格要求删除。它们生成一个简单的笛卡尔积,与在FROM的顶层列出两个表时得到的结果相同,但受到连接条件(如果有)的限制。 -
LATERAL
LATERAL关键字可以在子SELECTFROM项之前。这允许子SELECT引用在FROM列表中出现在它之前的FROM项的列。(没有LATERAL,每个子SELECT都是独立评估的,因此不能交叉引用任何其他FROM项。)
LATERAL也可以在函数调用FROM项之前,但在这种情况下,它是一个噪声词,因为函数表达式可以引用任何情况下早期的FROM项。
LATERAL项可以出现在FROM列表的顶层,或者在JOIN树中。在后一种情况下,它也可以引用在其右侧的左侧的任何项。
当FROM项包含LATERAL交叉引用时,评估过程如下:对于提供交叉引用列或多个FROM项的行集的每一行,使用该行或行集的列值来评估LATERAL项。生成的行与它们计算出的行通常连接。对于来自列源表的每一行或行集重复此过程。
列源表必须是INNER或LEFT连接到LATERAL项,否则将没有明确定义的行集来计算LATERAL项的每个行集。因此,虽然像X RIGHT JOIN LATERAL Y这样的结构在语法上是有效的,但实际上不允许Y引用X。
WHERE子句
可选的WHERE子句的一般形式为
WHERE condition
其中condition是任何计算为boolean类型结果的表达式。不满足此条件的任何行都将从输出中删除。如果将实际行值替换为任何变量引用,则行满足条件并返回true。
condition支持数字类型表达式,计算规则如下所示。
表 计算规则
| 数字表达式结果范围 | 表达式返回 |
|---|---|
| (-0.5, +0.5) | FALSE |
| (-∞, -0.5]、[+0.5,+∞) | TRUE |
| 数字类型特殊值(参见 “数字类型”) | TRUE |
condition新增了“+”语法。“+”语法和left join,right join在执行计划和执行效率上并没有差异,在UXDB数据库中“+”语法就是对left join,right join的一个简写。
在查询分析过程中,将“+”重新转化为left join,right join的表达式去处理。
注意
“+”语法不支持全连接。“+”在左边表示右连接,“+”在右边表示左连接。
“+”语法左连接查询,如下所示。
select * from t_A a,t_B b where a.id=b.id(+);
“+”语法右连接查询,如下所示。
select * from t_A a,t_B b where a.id(+)=b.id;
“+”语法带子句的查询,如下所示。
select * from t_A a where exists (select 1 from t_B b where a.id(+) = b.id);
select * from t_A a where exists (select 1 from t_B b where a.id = b.id(+));
START WITH子句
层次查询(Hierarchical Query)是一种具有特殊功能的查询语句,通过它能够将分层数据按照层次关系展示出来。分层数据是指关系表中的数据之间具有层次关系。
表 层次查询参数说明
| 参数 | 描述 |
|---|---|
START WITH condition | condition 确定了首层数据。 |
CONNECT BY condition [ NOCYCLE ] | condition 确定了上下层次数据之间的关系。其中 PRIOR 作为 CONNECT BY 短语专用的表达式修饰符,语义为规定表达式范围内的列引用指向父层的列,未被 PRIOR 修饰的列引用指向待查询的关系对象的列;NOCYCLE 关键词存在时查询将舍弃层次关系死循环行,NOCYCLE 不存在时查询遇到死循环行时将报告异常,导致查询失败。 |
ORDER SIBLINGS BY expression ... | 确定每一层数据的排序条件。 |
层次查询的目标表达式中可以包含如下的伪列和函数。
表 层次查询的伪列和函数
| 参数 | 描述 |
|---|---|
| prior expr | 表示父行的 expr 表达式的值。 |
| level | 表示本行的层次顺序数,顶层行的level为整数1,其余层行的level为父行level+1。 |
| connect_by_root c_expr | 表示本行的顶层祖先行对应的 c_expr 表达式的值。 |
| connect_by_iscycle | 本行存在循环的子行时为整数1,否则为0。 |
| connect_by_isleaf | 本行不存在非循环的子行时为整数1,否则为0。 |
| sys_connect_by_path(a_expr_l,a_expr_r) | 顶层行表达为字符串并 ( a_expr_r ||a_expr_l ),其余行表达为字符串并 ( 父行本表达式 ||a_expr_r ||a_expr_l) |
注意
order by短语会破坏数据的层次关系,不建议和层次查询搭配使用,应使用order siblings by短语。
GROUP BY子句
可选的GROUP BY子句的一般形式为
GROUP BY [ ALL | DISTINCT ] grouping_element [, ...]
GROUP BY将所有选择的行压缩为具有相同分组表达式值的单个行。在grouping_element内使用的expression可以是输入列名,输出列(SELECT列表项)的名称或序号,或任意的表达式。如果存在歧义,则将GROUP BY名称解释为输入列名称而不是输出列名称。
如果任何GROUPING SETS、ROLLUP或CUBE作为分组元素存在,则整个GROUP BY子句定义了一些独立的分组集。这的效果相当于在子查询之间构建一个UNION ALL,其中每个子查询都有各自的分组集作为其GROUP BY子句。可选的DISTINCT子句在处理之前删除重复集;它不会将UNION ALL转换为UNION DISTINCT。
如果使用了聚合函数,则对构成每个组的所有行进行计算,为每个组产生一个单独的值。(如果有聚合函数但没有GROUP BY子句,则将查询视为具有包含所有选定行的单个组。)每个聚合函数所提供的行集可以通过将FILTER子句附加到聚合函数调用来进一步过滤。当存在FILTER子句时,只有与之匹配的行才包括在该聚合函数的输入中。
当存在GROUP BY或任何聚合函数时,SELECT列表表达式不能引用未分组的列,除非在聚合函数内部或未分组的列在功能上依赖于分组列,否则将会有多个可能的值返回给未分组的列。如果分组列(或其子集)是包含未分组列的表的主键,则存在功能依赖关系。
请记住,在评估HAVING子句或SELECT列表中的任何“标量”表达式之前,将评估所有聚合函数。这意味着,例如,CASE表达式不能用于跳过聚合函数的评估。
目前,不能将FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE和FOR KEY SHARE与GROUP BY一起使用。
grouping sets和having有限制,group by grouping sets(())不能和having子句一起使用。
在distinct子句和order by子句一起使用时,支持order by子句中的字段,可以不在distinct target list中出现。
若需要出现语义不明确的列时,设置sql_mode值为'';需要语义明确的列时,设置sql_mode值为ONLY_FULL_GROUP_BY。标准模式和兼容模式配置sql_mode参数有两种方法,如下所示。
-
修改配置文件
uxsinodb.conf中sql_mode的值,默认值为ONLY_FULL_GROUP_BY。 -
在客户端uxsql中,设置
sql_mode参数。
GROUP BY示例,如下所示。
--同时使用group by和order by子句进行查询
select a, b from tab group by a, b order by c;
--同时使用group by和having子句进行查询
select a, b from tab group by a, b having d < 5;
--同时使用group by、order by和having子句进行查询
select a, e from tab group by a, e having e > 5 order by a;
--使用distinct子句进行查询
select distinct a, b from tab having c > 4;
select distinct a, e from tab group by a having d > 5 order by c;
select distinct a, e from tab group by a, b, e, d having d > 5 order by e;
--在group by子句中使用grouping sets函数
select a, b, avg(c) from tab group by grouping sets (a, b, ());
select a, b, avg(c) from tab group by grouping sets (a, b, ()) having a < 2;
--使用grouping sets(()) having进行查询
select 1 from tab group by grouping sets (a,()) having a < 2;
HAVING子句
可选的HAVING子句的一般形式为
HAVING condition
其中condition与WHERE子句指定的条件相同。
HAVING消除不满足条件的分组行。HAVING与WHERE不同:WHERE在GROUP BY应用之前过滤单个行,而HAVING过滤分组行。由GROUP BY创建。在condition中引用的每列必须明确引用分组列,除非引用出现在聚合函数内或未分组列在功能上依赖于分组列。
即使没有GROUP BY子句,HAVING的存在也会将查询转换为分组查询。这与查询包含聚合函数但没有GROUP BY子句时发生的情况相同。所有选择的行被认为形成一个单独的组,SELECT列表和HAVING子句只能引用聚合函数内的表列。如果HAVING条件为真,则此类查询将发出一行,如果条件不为真,则发出零行。
目前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE和FOR KEY SHARE不能与HAVING一起使用。
WINDOW子句
可选的WINDOW子句的一般形式为
WINDOW window_name AS ( window_definition ) [, ...]
其中window_name是可以从OVER子句或后续窗口定义中引用的名称,window_definition是
[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]
如果指定了existing_window_name,则它必须引用WINDOW列表中的先前条目;新窗口从该条目复制其分区子句,以及其排序子句(如果有)。在这种情况下,新窗口不能指定自己的PARTITION BY子句,只有在复制的窗口没有排序子句时才能指定ORDER BY。新窗口始终使用自己的框架子句;复制的窗口不得指定框架子句。
PARTITION BY列表的元素的解释方式与GROUP BY子句的元素类似,只是它们始终是简单表达式,而不是输出列的名称或编号。另一个区别是这些表达式可以包含聚合函数调用,在常规GROUP BY子句中不允许这样做。它们在此处被允许,因为窗口化发生在分组和聚合之后。
类似地,ORDER BY列表的元素的解释方式与语句级别的ORDER BY子句的元素类似,只是表达式始终被视为简单表达式,而不是输出列的名称或编号。
可选的frame_clause定义依赖于框架的窗口函数的窗口框架(并非所有窗口函数都依赖于框架)。窗口框架是一组相关行,用于查询的每一行(称为当前行)都有一个frame_clause,可以是以下之一:
{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]
其中frame_start和frame_end可以是以下之一:
UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING
frame_exclusion可以是以下之一:
EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS
如果省略frame_end,则默认为CURRENT ROW。限制是frame_start不能是UNBOUNDED FOLLOWING,frame_end不能是UNBOUNDED PRECEDING,并且frame_end选项不能出现在上述frame_start和frame_end选项列表中的frame_start选项之前,例如RANGE BETWEEN CURRENT ROW AND offset PRECEDING是不允许的。
默认的框架选项是RANGE UNBOUNDED PRECEDING,它与RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同;它将框架设置为从分区开始到当前行的最后一个对等行(窗口的ORDER BY子句认为与当前行等效的行;如果没有ORDER BY,则所有行都是对等行)。一般来说,UNBOUNDED PRECEDING表示框架从分区的第一行开始,类似地,UNBOUNDED FOLLOWING表示框架以分区的最后一行结束,而不管RANGE,ROWS或GROUPS模式如何。在ROWS模式下,CURRENT ROW表示框架以当前行开始或结束;但在RANGE或GROUPS模式下,它表示框架以当前行的第一个或最后一个对等行开始或结束,按照ORDER BY排序。offset PRECEDING和offset FOLLOWING选项的含义因框架模式而异。在ROWS模式下,offset是一个整数,表示框架在当前行之前或之后开始或结束那么多行。在GROUPS模式下,offset是一个整数,表示框架在当前行的对等行组之前或之后开始或结束那么多对等行组,其中对等行组是根据窗口的ORDER BY子句相等的一组行。在RANGE模式下,使用offset选项需要有窗口定义中只能有一个ORDER BY列。然后,窗口包含那些排序列值不超过当前行排序列值减去offset(对于PRECEDING)或超过当前行排序列值加上offset(对于FOLLOWING)的行。在这些情况下,offset表达式的数据类型取决于排序列的数据类型。对于数字排序列,它通常与排序列具有相同的类型,但对于日期时间排序列,它是一个interval。在所有这些情况下,offset的值必须是非空且非负的。此外,offset虽然不必是一个简单的常量,但它不能包含变量、聚合函数或窗口函数。
frame_exclusion选项允许从窗口中排除当前行周围的行,即使根据窗口开始和窗口结束选项,它们将被包括在内。EXCLUDE CURRENT ROW将当前行从窗口中排除。EXCLUDE GROUP将当前行及其排序对等项从窗口中排除。EXCLUDE TIES将当前行的任何对等项从窗口中排除,但不包括当前行本身。EXCLUDE NO OTHERS只是明确指定不排除当前行或其对等项的默认行为。
请注意,如果ORDER BY排序未对行进行唯一排序,则ROWS模式可能会产生不可预测的结果。RANGE和GROUPS模式旨在确保按ORDER BY排序的对等行得到相同的处理:给定对等组的所有行都将在窗口中或从中排除。
WINDOW子句的目的是指定出现在查询的SELECT列表或ORDER BY子句中的窗口函数的行为。这些函数可以在其OVER子句中按名称引用WINDOW子句条目。然而,WINDOW子句条目不必在任何地方引用;如果在查询中未使用它,则会被简单地忽略。可以在没有任何WINDOW子句的情况下使用窗口函数,因为窗口函数调用可以在其OVER子句中直接指定其窗口定义。但是,当需要多个窗口函数使用相同的窗口定义时,WINDOW子句可以节省输入。
目前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE和FOR KEY SHARE不能与WINDOW一起使用。
SELECT列表
SELECT列表(在关键字之间)SELECT 和 FROM 子句指定了构成 SELECT语句输出行的表达式。这些表达式可以(并且通常)引用在FROM 子句中计算的列。
就像在表中一样,每个 SELECT 的输出列都有一个名称。在简单的 SELECT 中,这个名称只是用于标记列以供显示,但是当SELECT 是一个更大查询的子查询时,这个名称被看作是子查询产生的虚拟表的列名。要指定用于输出列的名称,请在列的表达式后面写上 AS output_name(你可以省略 AS,但是只有当所需的输出名称不匹配任何 UXsinoDB 关键字时才能省略。为了防止可能的未来关键字添加,建议你始终写上AS 或用双引号括起输出名称。如果你没有指定列名,UXsinoDB会自动选择一个名称。如果列的表达式是一个简单的列引用,那么选择的名称与该列的名称相同。在更复杂的情况下,可能会使用函数或类型名称,或者系统可能会回退到生成的名称,例如?column?。
输出列的名称可用于在 ORDER BY 和 GROUP BY 子句中引用该列的值,但不能在 WHERE 或 HAVING子句中使用;在那里,你必须写出表达式。
在输出列表中,可以用 * 作为选定行的所有列的简写。此外,你可以写成table_name.*,作为来自该表的列的简写。在这些情况下,不可能使用AS 指定新名称;输出列名称将与表列名称相同。
根据 SQL 标准,输出列表中的表达式应在应用 DISTINCT、ORDER BY 或 LIMIT 之前计算。当使用DISTINCT 时,这显然是必要的,否则不清楚正在使哪些值不同。然而,在许多情况下,如果输出列表包含任何易失性或昂贵的函数,则在ORDER BY 和 LIMIT之后计算输出表达式更方便;特别是如果输出表达式包含任何易失性或昂贵的函数。在这种行为下,函数评估的顺序更加直观,而且不会有与不出现在输出中的行对应的评估。只要这些表达式没有被引用在DISTINCT、ORDER BY 或 GROUP BY 中,UXsinoDB 将在排序和限制之后有效地评估输出表达式。(作为反例,SELECT f(x) FROM tab ORDER BY 1 显然必须在排序之前评估f(x)。)包含集合返回函数的输出表达式在排序之后和限制之前有效地评估,因此 LIMIT将用于截断来自集合返回函数的输出。
注意
之前的UXsinoDB没有提供任何关于输出表达式的评估时间与排序和限制的保证;这取决于所选择的查询计划的形式。
DISTINCT子句
如果指定了SELECT DISTINCT,则从结果集中删除所有重复行(保留每组重复行中的一行)。SELECT ALL指定相反的操作:保留所有行;这是默认设置。
SELECT DISTINCT ON ( expression [, ...] )仅保留给定表达式求值相等的每组行的第一行。DISTINCT ON表达式使用与ORDER BY相同的规则进行解释(见上文)。请注意,每组的“第一行”是不可预测的,除非使用ORDER BY确保所需行首先出现。例如:
SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
ORDER BY location, time DESC;
检索每个位置的最新天气报告。但是,如果我们没有使用ORDER BY来强制每个位置的时间值按降序排列,我们将从每个位置的不可预测时间得到报告。
DISTINCT ON表达式必须与最左边的ORDER BY表达式匹配。ORDER BY子句通常包含确定每个DISTINCT ON组内行的所需优先级的其他表达式。
目前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE和FOR KEY SHARE不能与DISTINCT一起使用。
兼容模式下支持distinct与order by子查询排序。在UXDB标准模式,仅支持distinct与order by子查询顺序排序,不支持逆序排序。
使用该功能需要初始化兼容模式的数据库,即初始化阶段增加参数--running-mode compatible。
表 子查询排序的处理区别表
| 功能 | UXDB标准模式 | UXDB兼容模式 | 备注 |
|---|---|---|---|
| 子查询正序 | 正序排列,null为最大值 | 正序排列,null为最大值 | select distinct on(id) id from (select id from t_distinct order by id asc); |
| 子查询逆序 | 乱序 | 逆序排列,null为最大值 | select distinct on(id) id from (select id from t_distinct order by id desc); |
| 是否null值去重 | 是 | 是 |
UNIQUE子句
SELECT UNIQUE子句是SELECT DISTINCT的同义替换,它们之间等效,详细请参见DISTINCT子句。
UNION子句
UNION子句的一般形式如下:
select_statement UNION [ ALL | DISTINCT ] select_statement
select_statement是没有ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE或FOR KEY SHARE子句的任何SELECT语句。(如果将子表达式括在括号中,则ORDER BY和LIMIT可以附加到子表达式。如果没有括号,则这些子句将被视为适用于UNION的结果,而不是其右侧输入表达式。)
UNION运算符计算所涉及的SELECT语句返回的行的集合并。如果一行出现在至少一个结果集中,则该行在两个结果集的集合并中。表示UNION的两个SELECT语句必须生成相同数量的列,并且相应的列必须具有兼容的数据类型。
UNION的结果不包含任何重复行,除非指定了ALL选项。ALL防止消除重复项。(因此,UNION ALL通常比UNION快得多;尽可能使用ALL。)DISTINCT可以被显式地写出来,以指定消除重复行的默认行为。
同一 SELECT 语句中的多个 UNION 运算符从左到右进行评估,除非括号另有说明。
当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能被指定为UNION 结果或任何输入的一部分。
INTERSECT 子句
INTERSECT 子句的一般形式如下:
select_statement INTERSECT [ ALL | DISTINCT ] select_statement
select_statement 是任何没有 ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 或 FOR KEY SHARE 子句的 SELECT 语句。
INTERSECT 运算符计算所涉及的 SELECT 语句返回的行的交集。如果一行同时出现在两个结果集中,则它在交集中。
INTERSECT 的结果不包含任何重复行,除非指定了 ALL 选项。使用 ALL在左表中有m个重复项,在右表中有n个重复项的行将在结果集中出现min(m,n) 次。可以显式地写出DISTINCT,以指定消除重复行的默认行为。
同一 SELECT 语句中的多个 INTERSECT 运算符从左到右进行评估,除非括号另有说明。INTERSECT 的绑定比UNION 更紧密。也就是说,A UNION B INTERSECT C 将被解读为 A UNION (B INTERSECT C)。
当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能被指定为INTERSECT 结果或任何输入的一部分。
EXCEPT 子句
EXCEPT 子句的一般形式如下:
select_statement EXCEPT [ ALL | DISTINCT ] select_statement
select_statement 是任何没有 ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 或 FOR KEY SHARE 子句的 SELECT 语句。
EXCEPT 运算符计算左侧 SELECT 语句的结果中存在但右侧结果中不存在的行的集合。
EXCEPT 的结果不包含任何重复行,除非指定了 ALL 选项。使用 ALL,在左表中有m个重复项,在右表中有n个重复项的行将在结果集中出现m-n次。可以显式地写出 DISTINCT,以指定消除重复行的默认行为。
除非指定了ALL选项,否则会重复行。使用ALL,左表中有m个重复项,右表中有n个重复项的行将在结果集中出现 max(m-n,0)次。DISTINCT可以明确指定消除重复行的默认行为。
同一SELECT语句中的多个EXCEPT运算符从左到右进行评估,除非括号另有规定。EXCEPT与UNION的绑定级别相同。
目前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE和FOR KEY SHARE不能为EXCEPT结果或任何输入指定。
MINUS子句
可选的ORDER BY子句的形式如下所示。
select_statement1 MINUS [ ALL | DISTINCT ]select_statement2
MINUS关键字使两个同类型结果集之间做差运算,返回位于第一个结果集但不在第二个结果集中的行。
MINUS返回所有在select_statement1的结果中但是不在select_statement2的结果中的行(也叫做两个查询的差)。为了计算两个查询的差,这两个查询必须是“操作兼容的”,意味着它们都返回同样数量的列,并且对应的列有兼容的数据类型。
ORDER BY子句
可选的ORDER BY子句的一般形式如下:
ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]
ORDER BY子句导致结果行按指定的表达式排序。如果两行根据最左边的表达式相等,则根据下一个表达式进行比较,以此类推。如果根据所有指定的表达式相等,则以实现相关的顺序返回它们。
每个expression可以是输出列的名称或序号(SELECT列表项),也可以是由输入列值形成的任意表达式。
序号是指输出列的序号(从左到右)。此功能使得可以基于不具有唯一名称的列定义排序。这从来不是绝对必要的,因为始终可以使用AS子句为输出列分配名称。
还可以在ORDER BY子句中使用任意表达式,包括不出现在SELECT输出列表中的列。因此,以下语句是有效的:
SELECT name FROM distributors ORDER BY code;
此功能的限制是,应用于UNION、INTERSECT或EXCEPT子句的结果的ORDER BY子句只能指定输出列名称或编号,而不能指定表达式。
如果ORDER BY表达式是一个简单名称,既匹配输出列名称又匹配输入列名称,ORDER BY将其解释为输出列名称。这与GROUP BY在相同情况下所做的选择相反。这种不一致性是为了与SQL标准兼容而做出的选择。
可以在ORDER BY子句中选择添加关键字ASC(升序)或DESC(降序)。如果未指定,默认情况下假定为ASC。或者,可以在USING子句中指定特定的排序运算符名称。排序运算符必须是某个B树运算符族的小于或大于成员。ASC 通常等同于 USING <,而 DESC 通常等同于 USING >。(但是,用户定义的数据类型的创建者可以定义默认的排序顺序,它可能对应于具有其他名称的运算符。)如果指定了 NULLS LAST,则空值在所有非空值之后排序;如果指定了 NULLS FIRST,则空值在所有非空值之前排序。如果没有指定,则默认行为是在指定或隐含ASC 时为 NULLS LAST,在指定或隐含 DESC 时为 NULLS FIRST(因此,默认情况下,空值被视为大于非空值)。
当指定 USING 时,默认的空值排序取决于运算符是小于还是大于运算符。请注意,排序选项仅适用于它们后面的表达式;例如,ORDER BY x, y DESC 的含义与 ORDER BY x DESC, y DESC 不同。
字符串数据根据应用于排序列的排序规则进行排序。可以通过在expression 中包含 COLLATE 子句来在需要时覆盖它,例如 ORDER BY mycolumn COLLATE "en_US"。
LIMIT 子句
LIMIT 子句由两个独立的子句组成:
LIMIT { count | ALL }
OFFSET start
参数 count 指定要返回的最大行数,而 start 指定要在开始返回行之前跳过的行数。当两者都指定时,在开始计算要返回的count 行之前,将跳过 start 行。
如果 count 表达式计算为 NULL,则将其视为 LIMIT ALL,即没有限制。如果 start 计算为NULL,则将其视为与 OFFSET 0 相同。
SQL:2008 引入了一种不同的语法来实现相同的结果,UXsinoDB 也支持该语法。它是:
OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }
在此语法中,标准要求 start 或 count 值为文字常量、参数或变量名;作为 UXsinoDB的扩展,允许使用其他表达式,但通常需要将其括在括号中以避免歧义。如果在 FETCH子句中省略了 count,则默认为 1。WITH TIES 选项用于返回与 ORDER BY子句相符的结果集中最后一位并列的任何其他行;在这种情况下,ORDER BY 是强制性的,而 SKIP LOCKED 是不允许。ROW和ROWS以及FIRST和NEXT是噪声词,不影响这些子句的效果。根据标准,如果两者都存在,则OFFSET子句必须在FETCH子句之前;但是UXsinoDB更宽松,允许任何顺序。
使用LIMIT时,最好使用ORDER BY子句将结果行约束为唯一顺序。否则,您将获得查询行的不可预测子集 -您可能要求第十到第二十行,但第十到第二十行按什么顺序排列?除非指定ORDER BY,否则您不知道排序方式。
查询规划器在生成查询计划时考虑LIMIT,因此根据您用于LIMIT和OFFSET的不同值,很可能会获得不同的计划(产生不同的行顺序)。因此,使用不同的LIMIT/OFFSET值选择查询结果的不同子集将给出不一致的结果,除非您使用ORDER BY强制执行可预测的结果排序。这不是错误;这是SQL不保证以任何特定顺序传递查询结果的固有后果,除非使用ORDER BY约束顺序。
即使是相同的LIMIT查询的重复执行,如果没有ORDER BY来强制选择确定性子集,则可能返回表的行的不同子集。同样,这不是错误;在这种情况下,结果的确定性不被保证。
锁定子句
FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE和FOR KEY SHARE是锁定子句;它们影响SELECT从表中获取行时如何锁定行。
锁定子句的一般形式为
FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ]
其中lock_strength可以是以下之一
UPDATE
NO KEY UPDATE
SHARE
KEY SHARE
为了防止操作等待其他事务提交,请使用NOWAIT或SKIP LOCKED选项。使用NOWAIT时,如果无法立即锁定所选行,则该语句会报告错误,而不是等待。使用SKIP LOCKED时,任何无法立即锁定的选定行都将被跳过。跳过锁定的行提供了数据的不一致视图,因此不适用于通用目的的工作,但可用于避免具有访问类似队列的表的多个使用者的锁争用。请注意,NOWAIT和SKIP LOCKED仅适用于行级锁定 - 必需的ROW SHARE表级锁定仍以普通方式进行。您可以使用如果需要在不等待的情况下获取表级锁,请首先使用NOWAIT选项LOCK 。
防止FOR UPDATE语句长时间等待其他事务提交。SELECT FOR UPDATE的锁定子句中增加语法WAIT N(N表示秒数),如果选中的行在N秒不能被立即锁定,则该语句会在N秒后结束事务并报告错误。
WAIT N说明:N表示等待获取对应表或者行锁的时间,单位:秒,类型:integer,范围:between 0 and 2147483。当超过Ns未获取到对应的锁时,报错。在表加上排它锁的时候(lock table),那么返回结果直到表被解锁。当在Ns内获取对应表或者行锁的时候,则正常返回结果。
select * from test for update wait 10;
如果在锁定子句中指定了特定的表,则仅锁定来自这些表的行;在SELECT中使用的任何其他表都将像通常一样被读取。没有表列表的锁定子句会影响语句中使用的所有表。如果将锁定子句应用于视图或子查询,则会影响视图或子查询中使用的所有表。但是,这些子句不适用于主查询引用的WITH查询。如果要在WITH查询中发生行锁定,请在WITH查询中指定锁定子句。
如果需要为不同的表指定不同的锁定行为,则可以编写多个锁定子句。如果同一个表被多个锁定子句提到(或隐含影响),则它将被处理为只被最强的一个指定。同样,如果在影响它的任何子句中指定了NOWAIT,则该表将被处理为NOWAIT。否则,如果在影响它的任何子句中指定了SKIP LOCKED,则它将被处理为SKIPLOCKED。
锁定子句不能用于返回的行无法明确地与单个表行相关联的上下文中;例如,它们不能与聚合一起使用。
当锁定子句出现在SELECT查询的顶层时,被锁定的行恰好是查询返回的行;在连接查询的情况下,被锁定的行是为返回的连接行做出贡献的行。此外,满足查询快照条件的行将被锁定,尽管如果它们在快照之后被更新并且不再满足查询条件,则不会返回它们。如果使用了LIMIT,则锁定会在返回足够的行以满足限制后停止(但请注意,被OFFSET跳过的行将被锁定)。同样,如果在游标的查询中使用锁定子句,则只有实际获取或跨越游标的行将被锁定。当锁定子句出现在子SELECT中时,被锁定的行是由子查询返回到外部查询的行。这可能涉及比仅检查子查询所示更少的行,因为可能使用来自外部查询的条件来优化执行子查询。例如,
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;
将仅锁定具有col1= 5的行,即使该条件不在子查询中。之前的版本未能保留稍后由保存点升级的锁定。例如,这段代码:
BEGIN;
SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE mytable SET ... WHERE key = 1;
ROLLBACK TO s;
在ROLLBACK TO之后未能保留FOR UPDATE锁定。
注意
在使用ORDER BY和锁定子句的SELECT命令运行在READ COMMITTED事务隔离级别并可能返回无序行。这是因为ORDER BY首先被应用。该命令对结果进行排序,但可能会在尝试获取一个或多个行的锁时阻塞。一行看起来可能是无序的(尽管它们在原始列值方面是有序的)。这可以通过在子查询中放置FOR UPDATE/SHARE子句来解决,例如:
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;
请注意,这将导致锁定mytable的所有行,而在顶层使用FOR UPDATE仅锁定实际返回的行。这可能会导致显着的性能差异,特别是如果ORDER BY与LIMIT或其他限制结合使用。因此,仅当预期对排序列进行并发更新并且需要严格排序的结果时,才建议使用此技术。在REPEATABLE READ或SERIALIZABLE事务隔离级别下,这将导致序列化失败(带有'40001'的SQLSTATE),因此在这些隔离级别下不可能接收到无序的行。
TABLE命令
命令
TABLE name
等同于
SELECT * FROM name
它可以用作顶级命令或作为复杂查询的部分中节省空间的语法变体。只能使用TABLE与WITH、UNION、INTERSECT、EXCEPT、ORDER BY、LIMIT、OFFSET、FETCH和FOR锁定子句;不能使用WHERE子句和任何形式的聚合。
示例
把表films与表distributors连接:
SELECT f.title, f.did, d.name, f.date_prod, f.kind
FROM distributors d JOIN films f USING (did);
title | did | name | date_prod | kind
----++----+--+
The Third Man | 101 | British Lion | 1949-12-23 | Drama
The African Queen | 101 | British Lion | 1951-08-11 | Romantic
...
将所有电影的len相加并将结果按kind分组:
SELECT kind, sum(len) AS total FROM films GROUP BY kind;
kind | total
+--
Action | 07:34
Comedy | 02:58
Drama | 14:28
Musical | 06:42
Romantic | 04:38
将所有影片的len相加,将结果按kind分组,并显示小于5小时的组合总数:
SELECT kind, sum(len) AS total
FROM films
GROUP BY kind
HAVING sum(len) < interval '5 hours';
kind | total
+--
Comedy | 02:58
Romantic | 04:38
以下两个例子是根据第二列(名称)的内容对各个结果进行排序的相同方法:
SELECT * FROM distributors ORDER BY name;
SELECT * FROM distributors ORDER BY 2;
did | name
+---
109 | 20th Century Fox
110 | Bavaria Atelier
101 | British Lion
107 | Columbia
102 | Jean Luc Godard
113 | Luso films
104 | Mosfilm
103 | Paramount
106 | Toho
105 | United Artists
111 | Walt Disney
112 | Warner Bros.
108 | Westward
下一个示例展示了如何获取表distributors和actors的并集,将结果限制为每个表中以字母W开头的行。只想要不同的行,因此省略了关键字ALL。
distributors: actors:
did | name id | name
+---- ----+-
108 | Westward 1 | Woody Allen
111 | Walt Disney 2 | Warren Beatty
112 | Warner Bros. 3 | Walter Matthau
... ...
SELECT distributors.name
FROM distributors
WHERE distributors.name LIKE 'W%'
UNION
SELECT actors.name
FROM actors
WHERE actors.name LIKE 'W%';
name
-
Walt Disney
Walter Matthau
Warner Bros.
Warren Beatty
Westward
Woody Allen
这个示例展示了如何在FROM子句中使用函数,包括带有和不带有列定义列表的情况:
CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS $$
SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;
SELECT * FROM distributors(111);
did | name
+---
111 | Walt Disney
CREATE FUNCTION distributors_2(int) RETURNS SETOF record AS $$
SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;
SELECT * FROM distributors_2(111) AS (f1 int, f2 text);
f1 | f2
+---
111 | Walt Disney
这是一个带有序号列的函数示例:
SELECT * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY;
unnest | ordinality
---+
a | 1
b | 2
c | 3
d | 4
e | 5
f | 6
(6 rows)
这个示例展示了如何使用简单的WITH子句:
WITH t AS (
SELECT random() as x FROM generate_series(1, 3)
)
SELECT * FROM t
UNION ALL
SELECT * FROM t
x
0.534150459803641
0.520092216785997
0.0735620250925422
0.534150459803641
0.520092216785997
0.0735620250925422
请注意,WITH查询仅被评估一次,因此我们得到了两组相同的三个随机值。这个示例使用WITH RECURSIVE查找员工Mary的所有下属(直接或间接),以及他们的间接程度,从仅显示直接下属的表中:
WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS (
SELECT 1, employee_name, manager_name
FROM employee
WHERE manager_name = 'Mary'
UNION ALL
SELECT er.distance + 1, e.employee_name, e.manager_name
FROM employee_recursive er, employee e
WHERE er.employee_name = e.manager_name
)
SELECT distance, employee_name FROM employee_recursive;
请注意递归查询的典型形式:一个初始条件,后跟UNION,后跟查询的递归部分。确保查询的递归部分最终不会返回任何元组,否则查询将无限循环。这个示例使用LATERAL为manufacturers表的每一行应用一个返回集的函数get_product_names():
SELECT m.name AS mname, pname
FROM manufacturers m, LATERAL get_product_names(m.id) pname;
当前没有任何产品的制造商不会出现在结果中,因为它是一个内部连接。如果我们希望在结果中包括这些制造商的名称,我们可以执行以下操作:
SELECT m.name AS mname, pname
FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true;
q'转义字符示例如下所示。
select q'!name LIKE '%DBMS_%%'!';
select q'*!名称类似'%DBMS_%%'!*';
select q'"name like '['"';
select q'<'So,' she said, 'It's finished.'>';
select q'{SELECT * FROM employees WHERE last_name = 'Smith';}';
select q'[SELECT * FROM employees WHERE last_name = 'Smith';]';
select q'(SELECT * FROM employees WHERE last_name = 'Smith';)';
TOP子句示例如下所示。
select top 1,3 * from test;
select top 3 id,name from test;
select top (1) (id) from test01;
select top (1),(4) * from test01;
MINUS子句示例如下所示。
select * from tbtest_101 minus select * from tbtest_102;
层次查询示例如下所示。
--创建测试表
create table player(keyid int,parent_keyid int,name varchar(16),salary int,sex varchar(4));
insert into player values(1,0,'zhangsan','1000000','f');
insert into player values(2,1,'lisi','50500','m');
insert into player values(3,1,'wangwu','60000','m');
insert into player values(4,1,'houzi','65000','m');
insert into player values(5,2,'maliu','30000','f');
insert into player values(6,2,'liuqi','25000','m');
insert into player values(7,4,'gouba','23000','m');
insert into player values(8,4,'dujiu','21000','f');
--自上而下遍历,查询以keyid为n开始的节点的所有子孙节点
select keyid,parent_keyid,name,prior name,salary
from player
start with keyid=1
connect by prior keyid = parent_keyid;
select keyid,parent_keyid,name,prior name,salary
from player
start with keyid=2
connect by prior keyid = parent_keyid;
--自下而上遍历,查询以keyid为6的所有祖先节点
select keyid,parent_keyid,name,salary
from player
start with keyid = 6
connect by prior parent_keyid = keyid;
子查询支持无别名示例,如下所示。
select * from (select id from test_a where id < 3);
select * from (select id from test_a where id < 3) as a;
select * from (select id from test_a where id < 3) a;
递归查询SEARCH指定深度优先遍历,如下所示。
create table graph0( f int, t int, label text );
insert into graph0 values
(1, 2, 'arc 1 -> 2'),
(1, 3, 'arc 1 -> 3'),
(2, 3, 'arc 2 -> 3'),
(1, 4, 'arc 1 -> 4'),
(4, 5, 'arc 4 -> 5');
with recursive search_graph(f, t, label) as (
select * from graph0 g
union all
select g.*
from graph0 g, search_graph sg
where g.f = sg.t
) search depth first by f, t set seq
select * from search_graph order by seq;
f | t | label | seq
---+---+--+----
1 | 2 | arc 1 -> 2 | {"(1,2)"}
2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}
1 | 3 | arc 1 -> 3 | {"(1,3)"}
1 | 4 | arc 1 -> 4 | {"(1,4)"}
4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}
2 | 3 | arc 2 -> 3 | {"(2,3)"}
4 | 5 | arc 4 -> 5 | {"(4,5)"}
(7 rows)
递归查询SEARCH指定广度优先遍历,如下所示。
create table graph0( f int, t int, label text );
insert into graph0 values
(1, 2, 'arc 1 -> 2'),
(1, 3, 'arc 1 -> 3'),
(2, 3, 'arc 2 -> 3'),
(1, 4, 'arc 1 -> 4'),
(4, 5, 'arc 4 -> 5');
with recursive search_graph(f, t, label) as (
select * from graph0 g
union all
select g.*
from graph0 g, search_graph sg
where g.f = sg.t
) search breadth first by f, t set seq
select * from search_graph order by seq;
uxdb=# with recursive search_graph(f, t, label) as (
select * from graph0 g
union all
select g.*
from graph0 g, search_graph sg
where g.f = sg.t
) search breadth first by f, t set seq
select * from search_graph order by seq;
f | t | label | seq
---+---+--+----
1 | 2 | arc 1 -> 2 | (0,1,2)
1 | 3 | arc 1 -> 3 | (0,1,3)
1 | 4 | arc 1 -> 4 | (0,1,4)
2 | 3 | arc 2 -> 3 | (0,2,3)
4 | 5 | arc 4 -> 5 | (0,4,5)
2 | 3 | arc 2 -> 3 | (1,2,3)
4 | 5 | arc 4 -> 5 | (1,4,5)
(7 rows)
递归查询CYCLE指定环检测,如下所示。
create table graph( f int, t int, label text );
insert into graph values
(1, 2, 'arc 1 -> 2'),
(1, 3, 'arc 1 -> 3'),
(2, 3, 'arc 2 -> 3'),
(1, 4, 'arc 1 -> 4'),
(4, 5, 'arc 4 -> 5'),
(5, 1, 'arc 5 -> 1');
with recursive search_graph(f, t, label) as (
select * from graph g
union all
select g.*
from graph g, search_graph sg
where g.f = sg.t
) cycle f, t set is_cycle using path
select * from search_graph;
f | t | label | is_cycle | path
---+---+--++---
1 | 2 | arc 1 -> 2 | f | {"(1,2)"}
1 | 3 | arc 1 -> 3 | f | {"(1,3)"}
2 | 3 | arc 2 -> 3 | f | {"(2,3)"}
1 | 4 | arc 1 -> 4 | f | {"(1,4)"}
4 | 5 | arc 4 -> 5 | f | {"(4,5)"}
5 | 1 | arc 5 -> 1 | f | {"(5,1)"}
1 | 2 | arc 1 -> 2 | f | {"(5,1)","(1,2)"}
1 | 3 | arc 1 -> 3 | f | {"(5,1)","(1,3)"}
1 | 4 | arc 1 -> 4 | f | {"(5,1)","(1,4)"}
2 | 3 | arc 2 -> 3 | f | {"(1,2)","(2,3)"}
4 | 5 | arc 4 -> 5 | f | {"(1,4)","(4,5)"}
5 | 1 | arc 5 -> 1 | f | {"(4,5)","(5,1)"}
1 | 2 | arc 1 -> 2 | f | {"(4,5)","(5,1)","(1,2)"}
1 | 3 | arc 1 -> 3 | f | {"(4,5)","(5,1)","(1,3)"}
1 | 4 | arc 1 -> 4 | f | {"(4,5)","(5,1)","(1,4)"}
2 | 3 | arc 2 -> 3 | f | {"(5,1)","(1,2)","(2,3)"}
4 | 5 | arc 4 -> 5 | f | {"(5,1)","(1,4)","(4,5)"}
5 | 1 | arc 5 -> 1 | f | {"(1,4)","(4,5)","(5,1)"}
1 | 2 | arc 1 -> 2 | f | {"(1,4)","(4,5)","(5,1)","(1,2)"}
1 | 3 | arc 1 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,3)"}
1 | 4 | arc 1 -> 4 | t | {"(1,4)","(4,5)","(5,1)","(1,4)"}
2 | 3 | arc 2 -> 3 | f | {"(4,5)","(5,1)","(1,2)","(2,3)"}
4 | 5 | arc 4 -> 5 | t | {"(4,5)","(5,1)","(1,4)","(4,5)"}
5 | 1 | arc 5 -> 1 | t | {"(5,1)","(1,4)","(4,5)","(5,1)"}
2 | 3 | arc 2 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
(25 rows)
兼容性
当然,SELECT语句与SQL标准兼容。但是有一些扩展和一些缺失的功能。
省略FROM子句
UXsinoDB允许省略FROM子句。它有一个简单的用途来计算简单表达式的结果:
SELECT 2+2;
?column?
4
一些其他的SQL数据库除了引入一个虚拟的一行表来执行SELECT之外,不能做到这一点。
空SELECT列表
在SELECT后的输出表达式列表可以为空,产生一个零列结果表。这不是SQL标准的有效语法。UXsinoDB允许它与允许零列表保持一致。但是,当使用DISTINCT时,不允许空列表。
省略AS关键字
在SQL标准中,如果新列名是有效的列名(即不同于任何保留关键字),则可以省略可选的关键字AS。UXsinoDB稍微更加严格:如果新列名匹配任何关键字,无论是保留的还是不保留的,都需要AS。建议使用AS或双引号输出列名,以防止任何可能的冲突未来关键字添加。
在FROM项中,标准和UXsinoDB都允许在别名之前省略AS,这是一个未保留的关键字。但是,由于语法歧义,这对于输出列名是不切实际的。
ONLY和继承
SQL标准要求在写ONLY时在表名周围加上括号,例如SELECT * FROM ONLY(tab1),ONLY(tab2)WHERE...。UXsinoDB认为这些括号是可选的。
UXsinoDB允许在末尾写入*,以显式指定包括子表的非ONLY行为。标准不允许这样做。
(这些点同样适用于支持ONLY选项的所有SQL命令。)
TABLESAMPLE子句限制
TABLESAMPLE子句目前仅接受常规表和材料化视图。根据SQL标准,它应该可以应用于任何FROM项。
FROM中的调用函数
UXsinoDB允许直接将函数调用写为FROM列表的成员。在SQL标准中,需要将这样的函数调用包装在子SELECT中;也就是说,语法FROM func(...) alias大致相当于FROM LATERAL (SELECT func(...)) alias。请注意,LATERAL 被认为是隐式的;这是因为标准要求在 FROM 中的 UNNEST() 项具有LATERAL 语义。UXsinoDB 将 UNNEST() 与其他返回集的函数视为相同。
GROUP BY 和 ORDER BY 可用的命名空间
在 SQL-92 标准中,ORDER BY 子句只能使用输出列名或数字,而 GROUP BY 子句只能使用基于输入列名的表达式。UXsinoDB 扩展了这些子句,以允许另一种选择(但如果存在歧义,则使用标准的解释)。UXsinoDB还允许两个子句指定任意表达式。请注意,出现在表达式中的名称始终将被视为输入列名,而不是输出列名。
SQL:1999 及更高版本使用略有不同的定义,与 SQL-92 不完全向上兼容。但在大多数情况下,UXsinoDB 将以与SQL:1999 相同的方式解释 ORDER BY 或 GROUP BY 表达式。
函数依赖
只有当表的主键包含在 GROUP BY 列表中时,UXsinoDB 才会识别函数依赖(允许从 GROUP BY 中省略列)。SQL标准指定了应该识别的其他条件。
LIMIT 和 OFFSET
子句 LIMIT 和 OFFSET 是 UXsinoDB 特定的语法,也被 MySQL 使用。SQL:2008 标准引入了子句OFFSET ... FETCH {FIRST|NEXT} ...,用于相同的功能,如上所示。这种语法也被 IBM DB2 使用。(为Oracle 编写的应用程序通常使用一种解决方法,涉及自动生成的 rownum 列,该列在 UXsinoDB中不可用,以实现这些子句的效果。)
UXDB数据库的rownum利用limit语法进行改造;如:rownum<3等价于limit 2。
SELECT ROWNUM,* FROM t1_rn WHERE ROWNUM = 1;
SELECT ROWNUM,* FROM t1_rn WHERE ROWNUM > 1;
SELECT ROWNUM,* FROM t1_rn WHERE ROWNUM = ID;
SELECT ROWNUM,* FROM t1_rn WHERE ROWNUM < 3 and ROWNUM < 4;
SELECT rm FROM (SELECT *,rownum rm FROM t1_rn) t;
SELECT rm FROM (SELECT rownum rm,* FROM t1_rn) t WHERE rm < 3;
SELECT rm FROM (SELECT rownum AS rm,Id FROM t1_rn ORDER BY Id DESC) t;
SELECT ROWNUM,* from t1_rn,t2_rn;
FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE、FOR KEY SHARE
虽然 FOR UPDATE 出现在 SQL 标准中,但标准仅允许将其作为 DECLARE CURSOR 的选项。UXsinoDB允许在任何 SELECT 查询以及子查询中使用它,但这是一种扩展。FOR NO KEY UPDATE、FOR SHARE 和FOR KEY SHARE 变体以及 NOWAIT 和 SKIP LOCKED 选项不出现在标准中。
WITH 中的数据修改语句
UXsinoDB 允许 INSERT、UPDATE和DELETE可以用作WITH查询。这不是SQL标准中的内容。
非标准子句
DISTINCT ON ( ... )是SQL标准的扩展。
ROWS FROM( ... )是SQL标准的扩展。
WITH的MATERIALIZED和NOT MATERIALIZED选项是SQL标准的扩展。
SELECT INTO
SELECT INTO — 从查询结果定义一个新表
概要
[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
* | expression [ [ AS ] output_name ] [, ...]
INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] new_table
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY expression [, ...] ]
[ HAVING condition ]
[ WINDOW window_name AS ( window_definition ) [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ LIMIT { count | ALL } ]
[ OFFSET start [ ROW | ROWS ] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
[ FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ]
描述
SELECT INTO 创建一个新表,并用查询计算出的数据填充它。与普通的 SELECT 不同的是,数据不会返回给客户端。新表的列具有与SELECT 的输出列相关联的名称和数据类型。
参数
-
TEMPORARY或TEMP
如果指定,表将被创建为临时表。有关详细信息,请参见CREATE TABLE。 -
UNLOGGED
如果指定,表将被创建为非日志记录表。请参见CREATE TABLE。 -
new_table
要创建的新表的名称。 -
from_item
要查询的表、视图、子查询或连接的列表。 -
condition
查询中的条件。只有满足条件的行才会被包含在结果中。 -
expression
要在查询中计算的表达式。 -
output_name
输出列的名称。 -
window_name
窗口的名称。 -
window_definition
定义窗口的查询。 -
operator
用于排序的操作符。 -
count
要返回的行数。 -
start
结果集的起始行。 -
table_name
要锁定的表的名称。
有关详细信息,请参见CREATE TABLE。
new_table
要创建的表的名称(可选模式限定符)。
所有其他参数在SELECT下详细描述。
注释
CREATE TABLE AS在功能上类似于SELECT INTO。建议使用 CREATE TABLE AS 语法,因为 SELECT INTO 的这种形式在ECUX或PL/uxSQL 中不可用,因为它们以不同的方式解释 INTO 子句。此外,CREATE TABLE AS 提供了 SELECT INTO 提供的功能的超集。
与 CREATE TABLE AS 相比,SELECT INTO 不允许指定诸如表的访问方法(请参见CREATE TABLE中的“USING method”和“表空间”)等属性。必要时请使用CREATE TABLE AS。因此,新表的默认表访问方法将被选择。有关更多信息,请参见default_table_access_method。
示例
创建一个名为 films_recent 的新表,该表仅包含来自表 films 的最新条目:
SELECT * INTO films_recent FROM films WHERE date_prod >= '2002-01-01';
兼容性
SQL 标准使用 SELECT INTO 来表示将值选择到主机程序的标量变量中,而不是创建新表。这确实是在ECUX和 PL/uxSQL中找到的用法。UXsinoDB 使用SELECT INTO 来表示表创建是历史性的。一些其他 SQL 实现也以这种方式使用 SELECT INTO(但大多数 SQL实现支持 CREATE TABLE AS)。除了这些兼容性考虑因素外,在新代码中最好使用 CREATE TABLE AS来实现此目的。
另请参阅
SET
SET —更改运行时参数
概述
SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value | 'value' | DEFAULT }
SET [ SESSION | LOCAL ] TIME ZONE { value | 'value' | LOCAL | DEFAULT }
描述
SET 命令更改运行时配置参数。在“服务器配置”中列出的许多运行时参数可以通过 SET 实时更改。(某些参数只能由超级用户和被授予该参数的 SET 权限的用户更改。还有一些参数在服务器或会话启动后无法更改。) SET 仅影响当前会话使用的值。
如果在稍后被中止的事务中发出 SET(或等效的 SET SESSION)命令,则当事务回滚时,SET命令的影响将消失。一旦周围的事务提交,影响将持续到会话结束,除非被另一个SET 覆盖。
SET LOCAL 的影响仅持续到当前事务的结束,无论是否提交。一个特殊情况是在单个事务中使用 SET 后跟 SET LOCAL:在事务结束之前,将看到 SET LOCAL 值,但之后(如果事务提交),将采用 SET 值。
SET 或 SET LOCAL 的影响也会被回滚到早于该命令的保存点所取消。
如果在具有相同变量的 SET 选项的函数中使用 SET LOCAL(请参见CREATE FUNCTION), 则该函数中的 SET LOCAL 将覆盖外部 SET 命令的值,直到函数返回。
SET LOCAL 命令的效果在函数退出时消失;也就是说,函数调用时的值会被恢复。这使得 SET LOCAL可以用于函数内参数的动态或重复更改,同时仍然可以使用 SET选项来保存和恢复调用者的值。但是,常规的 SET 命令会覆盖任何周围函数的 SET选项;其效果将持续存在,除非回滚。
参数
-
SESSION
指定命令对当前会话生效。(如果没有出现SESSION或LOCAL,则为默认值。) -
LOCAL
指定命令仅对当前事务生效。在COMMIT或ROLLBACK后,会话级别的设置再次生效。在事务块外部发出此命令会发出警告,否则不会产生任何效果。 -
configuration_parameter
可设置的运行时参数的名称。 -
value
参数的新值。值可以指定为字符串常量、标识符、数字或逗号分隔的这些列表,具体取决于特定参数。可以写入DEFAULT来指定将参数重置为其默认值(也就是,如果在当前会话中没有执行SET,它将具有的值)。
除了在记录的配置参数外,还有一些只能使用SET命令进行调整或具有特殊语法的参数:
-
SCHEMA
SET SCHEMA 'value'是SET search_path TO value的别名。只能使用这种语法指定一个模式。 -
NAMES
SET NAMES value是SET client_encoding TO value的别名。 -
SEED
设置随机数生成器(函数random)的内部种子。允许的值是介于 -1 和 1 之间的浮点数。
种子也可以通过调用函数setseed 来设置:
SELECT setseed(value);
-
TIME ZONE
SET TIME ZONE 'value' 是SET timezone TO 'value' 的别名。语法SET TIME ZONE允许特殊的时区规范。以下是有效值的示例: -
'PST8PDT'
加利福尼亚州伯克利的时区。 -
'Europe/Rome'
意大利的时区。 -
-7
比协调世界时早7小时的时区(等同于 PDT)。正值表示比协调世界时晚。 -
INTERVAL '-08:00' HOUR TO MINUTE
比协调世界时早8小时的时区(等同于 PST)。 -
LOCAL
DEFAULT
将时区设置为本地时区(即服务器的默认值timezone)。
以数字或间隔形式给出的时区设置会被内部转换为 POSIX 时区语法。例如,在执行 SET TIME ZONE -7 后,SHOW TIME ZONE 将报告 <-07>+07。
SET 不支持时区缩写。
注解
函数 set_config 提供了等效的功能。此外,可以更新ux_settings系统视图来执行等效的SET 操作。
示例
设置模式搜索路径:
SET search_path TO my_schema, public;
将日期样式设置为传统的 UXDB 样式,使用“日在月之前”的输入约定:
SET datestyle TO uxdb, dmy;
将时区设置为加利福尼亚州伯克利的时区:
SET TIME ZONE 'PST8PDT';
将时区设置为意大利的时区:
SET TIME ZONE 'Europe/Rome';
兼容性
SET TIME ZONE 扩展了 SQL 标准中定义的语法。标准仅允许数字时区偏移量,而 UXsinoDB允许更灵活的时区规范。所有其他 SET 功能都是 UXsinoDB 扩展。
另请参阅
SET CONSTRAINTS
SET CONSTRAINTS — 设置当前事务的约束检查时间
概要
SET CONSTRAINTS { ALL | name [, ...] } { DEFERRED | IMMEDIATE }
描述
SET CONSTRAINTS 设置当前事务中约束检查的行为。IMMEDIATE 约束在每个语句结束时进行检查。DEFERRED约束直到事务提交才进行检查。每个约束都有自己的 IMMEDIATE 或 DEFERRED 模式。
在创建时,约束被赋予三个特性之一:DEFERRABLE INITIALLY DEFERRED、DEFERRABLE INITIALLY IMMEDIATE 或 NOT DEFERRABLE。第三个类别始终是 IMMEDIATE,不受 SET CONSTRAINTS命令的影响。前两个类别以指定的模式开始每个事务,但它们的行为可以在事务内通过 SET CONSTRAINTS 进行更改。
带有约束名列表的 SET CONSTRAINTS更改了仅这些约束的模式(这些约束必须全部是可延迟的)。每个约束名称都可以带有模式。如果未指定模式名称,则使用当前模式搜索路径查找第一个匹配的名称。SET CONSTRAINTS ALL 更改所有可延迟约束的模式。
当 SET CONSTRAINTS 将约束的模式从 DEFERRED 更改为 IMMEDIATE时,新模式会反向生效:任何未完成的数据修改将在执行 SET CONSTRAINTS 命令期间进行检查,而不是在事务结束时进行检查。如果违反了任何此类约束,则 SET CONSTRAINTS失败(并且不更改约束模式)。因此,SET CONSTRAINTS 可用于强制在事务的特定点进行约束检查。
目前,仅 UNIQUE、PRIMARY KEY、EXCLUSION 和 FOREIGN KEY 约束可以是可延迟的。
此设置会影响到外键约束(REFERENCES)和排除约束(EXCLUDE)。非空约束(NOT NULL)和检查约束(CHECK)会在插入或修改行时立即检查(而不是在语句末尾)。未声明为可延迟的唯一性和排除约束也会立即进行检查。声明为“约束触发器”的触发器的触发时间也受此设置的控制,它们会在关联的约束应该被检查时触发。
注意事项
由于 UXsinoDB 不要求约束名称在模式内唯一(而只是在每个表内唯一),因此指定的约束名称可能有多个匹配项。在这种情况下,SET CONSTRAINTS 将作用于所有匹配项。对于非模式限定名称,一旦在搜索路径中的某个模式中找到了匹配项,后面出现的模式就不会再被搜索。
此命令仅会更改当前事务中约束的行为。在事务块外部发出此命令会发出警告,否则不会产生任何效果。
兼容性
此命令遵循 SQL标准定义的行为,但有一个限制,即在UXsinoDB中,它不适用于非空约束和检查约束。此外,UXsinoDB会立即检查不可延迟的唯一性约束,而不是在语句末尾进行检查,这与标准建议的行为不同。
SET ROLE
SET ROLE — 设置当前会话的当前用户标识符
概要
SET [ SESSION | LOCAL ] ROLE role_name
SET [ SESSION | LOCAL ] ROLE NONE
RESET ROLE
描述
此命令将当前 SQL 会话的当前用户标识符设置为 role_name。角色名称可以写成标识符或字符串文字。在 SET ROLE之后,对于 SQL 命令的权限检查将按照最初登录的命名角色进行。
指定的 role_name 必须是当前会话用户的成员角色。(如果会话用户是超级用户,则可以选择任何角色。)
SESSION 和 LOCAL 修饰符的作用与常规的 SET 命令相同。
SET ROLE NONE 将当前用户标识符设置为由 session_user 返回的当前会话用户标识符。RESET ROLE将当前用户标识符设置为由命令行选项、ALTER ROLE 或 ALTER DATABASE 指定的连接时设置,如果存在这样的设置。否则,RESET ROLE 将当前用户标识符设置为当前会话用户标识符。任何用户都可以执行这些形式。
注释
使用此命令,可以添加特权或限制特权。如果会话用户角色具有 INHERIT 属性,则它自动具有它可以 SET ROLE到的每个角色的所有特权;在这种情况下,SET ROLE实际上会删除直接分配给会话用户的所有特权。对于其它角色,它是一个成员,只留下命名角色可用的权限。另一方面,如果会话用户角色具有NOINHERIT属性,则 SET ROLE 将删除直接分配给会话用户的权限,并获取命名角色可用的权限。
特别是,当超级用户选择 SET ROLE 到非超级用户角色时,他们将失去超级用户权限。
SET ROLE 具有与 SET SESSION AUTHORIZATION相当的效果,但涉及的特权检查是完全不同的。此外,SET SESSION AUTHORIZATION确定哪些角色可用于后续 SET ROLE 命令,而使用SET ROLE更改角色不会更改允许后续SET ROLE的角色集。
SET ROLE 不会按照角色的 ALTER ROLE 设置处理会话变量;这只会在登录期间发生。
SET ROLE 不能在 SECURITY DEFINER 函数中使用。
示例
SELECT SESSION_USER, CURRENT_USER;
session_user | current_user
----+----
peter | peter
SET ROLE 'paul';
SELECT SESSION_USER, CURRENT_USER;
session_user | current_user
----+----
peter | paul
兼容性
UXsinoDB 允许标识符语法("rolename"),而 SQL 标准要求角色名称写为字符串字面值。SQL不允许在事务期间使用此命令;UXsinoDB不会限制此操作,因为没有理由这样做。SESSION和LOCAL修饰符是 UXsinoDB 的扩展,RESET 语法也是如此。
另请参阅
SET SESSION AUTHORIZATION
SET SESSION AUTHORIZATION — 设置当前会话的会话用户标识符和当前用户标识符
概要
SET [ SESSION | LOCAL ] SESSION AUTHORIZATION user_name
SET [ SESSION | LOCAL ] SESSION AUTHORIZATION DEFAULT
RESET SESSION AUTHORIZATION
描述
此命令将当前 SQL 会话的会话用户标识符和当前用户标识符设置为user_name。用户名称可以写成标识符或字符串文字。例如,使用此命令可以暂时成为非特权用户,稍后再切换回超级用户。
会话用户标识符最初设置为客户端提供的(可能经过身份验证的)用户名称。当前用户标识符通常等于会话用户标识符,但在 SECURITY DEFINER 函数和类似机制的上下文中可能会暂时更改;它也可以通过SET ROLE更改。当前用户标识符与权限检查相关。
只有初始会话用户(经过身份验证的用户)具有超级用户特权时,才能更改会话用户标识符。否则,仅当命令指定经过身份验证的用户名称时才接受该命令。
SESSION 和 LOCAL 修饰符与常规 SET命令的作用相同。
DEFAULT 和 RESET 表单将会话和当前用户标识符重置为最初经过身份验证的用户名称。任何用户都可以执行这些表单。
注意事项
SET SESSION AUTHORIZATION 不能在 SECURITY DEFINER 函数内使用。
示例
SELECT SESSION_USER, CURRENT_USER;
session_user | current_user
----+----
peter | peter
SET SESSION AUTHORIZATION 'paul';
SELECT SESSION_USER, CURRENT_USER;
session_user | current_user
----+----
paul | paul
兼容性
SQL标准允许一些其他表达式出现在字面量“user_name”的位置,但这些选项在实践中并不重要。UXsinoDB允许标识符语法(“username”),而SQL不允许。SQL不允许在事务期间执行此命令;UXsinoDB没有这个限制,因为没有理由这样做。SESSION和LOCAL修饰符是UXsinoDB的扩展,RESET语法也是如此。
执行此命令所需的权限由标准的实现定义。
另请参阅
SET TRANSACTION
SET TRANSACTION — 设置当前事务的特性
概要
SET TRANSACTION transaction_mode [, ...]
SET TRANSACTION SNAPSHOT snapshot_id
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
其中 transaction_mode 是以下之一:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
[ NOT ] DEFERRABLE
描述
SET TRANSACTION 命令设置当前事务的特性。它不会影响任何后续的事务。SET SESSION CHARACTERISTICS 设置会话后续事务的默认事务特性。这些默认值可以被单个事务的 SET TRANSACTION 覆盖。
可用的事务特性包括事务隔离级别、事务访问模式(读/写或只读)和可延迟模式。此外,可以选择快照,但仅适用于当前事务,而不是会话默认值。
事务的隔离级别确定了当其他事务同时运行时,该事务可以看到哪些数据:
-
READ COMMITTED
语句只能看到在它开始之前提交的行。这是默认值。 -
REPEATABLE READ
当前事务的所有语句只能看到在该事务中执行第一个查询或数据修改语句之前提交的行。 -
SERIALIZABLE
当前事务的所有语句只能看到在该事务中执行第一个查询或数据修改语句之前提交的行。如果可并发序列化事务之间的读和写模式会造成这些事务的任何串行(一次一个)执行都不可能发生的情况,那么其中一个事务将会回滚,出现序列化失败错误。 -
READ UNCOMMITTED
当前事务的所有语句可以看到其他事务未提交的行,可能会导致脏读、不可重复读和幻读。
SQL标准定义了一种额外的级别:READ UNCOMMITTED。在UXDB中READ UNCOMMITTED被视作READ COMMITTED。
一个事务执行了第一个查询或者数据修改语句(SELECT、INSERT、DELETE、UPDATE、FETCH或COPY)之后就无法更改事务隔离级别。
事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。当一个事务为只读时,如果 SQL 命令 INSERT、UPDATE、DELETE和COPY FROM要写的表不是一个临时表,则它们不被允许。不允许CREATE、ALTER以及DROP命令。不允许COMMENT、GRANT、REVOKE、TRUNCATE。如果EXPLAIN ANALYZE和EXECUTE要执行的命令是上述命令之一,则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对磁盘的写入。
只有事务也是SERIALIZABLE以及READ ONLY时,DEFERRABLE事务属性才会有效。当一个事务的所有这三个属性都被选择时,该事务在 第一次获取其快照时可能会阻塞,在那之后它运行时就不会有SERIALIZABLE事务的开销并且不会有任何牺牲或者 被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者备份。
SET TRANSACTION SNAPSHOT命令允许新的事务 使用与一个现有事务相同的快照运行。已经存在的事务 必须已经把它的快照用ux_export_snapshot函数导出。该函数会返回一个快照标识符,SET TRANSACTION SNAPSHOT需要被给定一个快照标识符来指定要导入的快照。在这个命令中该标识符必须被写成一个字符串,例如 '000003A1-1'。SET TRANSACTION SNAPSHOT只能在一个事务的开始执行,并且要在该事务的第一个查询或者数据修改语句(SELECT、INSERT、DELETE、UPDATE、FETCH或COPY)之前执行。此外,该事务必须已经被设置 为SERIALIZABLE或者REPEATABLE READ隔离级别(否则,该快照将被立刻抛弃, 因为READ COMMITTED模式会为每一个命令取一个新快照)。如果导入事务使用了SERIALIZABLE隔离级别,那么导入快照 的事务必须也使用该隔离级别。还有,一个非只读可序列化事务不能导入来自只读 事务的快照。
注意事项
如果执行SET TRANSACTION之前没有START TRANSACTION或者BEGIN,它会发出一个警告并且不会有任何效果。
可以通过在BEGIN或者START TRANSACTION中指定想要的transaction_modes来省掉SET TRANSACTION。但是在SET TRANSACTION SNAPSHOT中该选项不可用。
会话默认事务模式也可以通过配置参数default_transaction_isolation、default_transaction_read_only和default_transaction_deferrable来设置或检查。(实际上,SET SESSION CHARACTERISTICS只是使用SET设置这些变量的冗长等效形式。)这意味着可以在配置文件中、通过ALTER DATABASE等方式设置默认值。
当前事务的模式也可以通过配置参数transaction_isolation、transaction_read_only和transaction_deferrable来设置或检查。设置其中一个参数的效果与相应的SET TRANSACTION选项相同,并具有相同的限制条件。但是,这些参数不能在配置文件中设置,也不能从除了实时SQL之外的任何来源设置。
示例
要使用与已存在事务相同的快照开始一个新事务,首先从现有事务中导出快照。这将返回快照标识符,例如:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT ux_export_snapshot();
ux_export_snapshot
-
00000003-0000001B-1
(1 row)
然后在新打开的事务开始时,在SET TRANSACTION SNAPSHOT命令中给出快照标识符:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION SNAPSHOT '00000003-0000001B-1';
兼容性
这些命令在SQL标准中定义,除了DEFERRABLE事务模式和SET TRANSACTION SNAPSHOT形式是UXsinoDB扩展。
SERIALIZABLE是标准中的默认事务隔离级别。在UXsinoDB中,默认值通常为READ COMMITTED,但可以像上面提到的那样进行更改。
在SQL标准中,还可以使用这些命令设置另一个事务特性:诊断区域的大小。这个概念是特定于嵌入式SQL的,因此在其他数据库中不适用。
未在 UXsinoDB 服务器中实现。
SQL 标准要求在连续的 transaction_modes 之间使用逗号,但由于历史原因,UXsinoDB 允许省略逗号。
SHOW
SHOW - 显示运行时参数的值
概要
SHOW name
SHOW ALL
描述
SHOW 将显示运行时参数的当前设置。这些变量可以使用 SET 语句设置,通过编辑 uxsinodb.conf 配置文件,通过UXOPTIONS 环境变量(使用 libuxsql 或基于 libuxsql 的应用程序),或通过在启动 uxdb服务器时使用命令行标志进行设置。
参数
-
name
运行时参数的名称。可用参数在SET参考页面中有文档。此外,有一些参数可以显示但不能设置。 -
SERVER_VERSION
显示服务器的版本号。 -
SERVER_ENCODING
显示服务器端字符集编码。目前,此参数可以显示但不能设置,因为编码是在数据库创建时确定的。 -
LC_COLLATE
显示数据库的排序(文本排序)的区域设置。目前,此参数可以显示但不能设置,因为设置是在数据库创建时确定的。 -
LC_CTYPE
显示数据库的字符分类的区域设置。目前,此参数可以显示但不能设置,因为设置是在数据库创建时确定的。 -
IS_SUPERUSER
如果当前角色具有超级用户权限,则为True。 -
ALL
显示所有配置参数的值和描述。
注释
函数current_setting产生等效的输出。此外,ux_settings系统视图产生相同的信息。
示例
显示参数DateStyle的当前设置:
SHOW DateStyle;
DateStyle
-
ISO, MDY
(1 row)
显示参数geqo的当前设置:
SHOW geqo;
geqo
-
on
(1 row)
显示所有设置:
SHOW ALL;
name | setting | description
+----+----
allow_system_table_mods | off | Allows modifications of the structure of ...
.
.
.
xmloption | content | Sets whether XML data in implicit parsing ...
zero_damaged_pages | off | Continues processing past damaged page headers.
(196 rows)
兼容性
SHOW命令是UXsinoDB的扩展。
另请参阅
SHOW COLUMNS
SHOW COLUMNS — 显示给定表对应的列信息
概要
SHOW [FULL] {COLUMNS | FIELDS}
{FROM | IN} tbl_name
[{FROM | IN} schema_name]
[LIKE 'pattern' | WHERE expr]
描述
show columns显示给定表对应的列信息。其中,可选full关键字段可以控制列信息的输出,包括列的collation,comments和对应用户对列的权限信息。like从句,如果存在,则匹配对应列名。where从句可通过使用更通用的条件选择行。
show columns中,tbl_name from schema_name等价于schema_name.tbl_name,即如下语句等价。
show columns from mytable from myschema;
show columns from myschema.mytable;
参数
-
Field
列名。 -
Type
列的数据类型。 -
Collation
列(必须是一种可排序数据类型)赋予一个排序规则。是否显示受关键字full控制。 -
NULL
列是否为空。如果列可以存储NULL,则为YES,否则为NO。 -
KEY
是否列被编为索引信息,取值如下所示。- 如果键为空,则该列不进行索引,或仅作为多列非唯一索引中的辅助列进行索引。
- 如果
Key为PRI,则该列是PRIMARY KEY或是多列中PRIMARY KEY其中一个。 - 如果
Key为UNI,则该列是UNIQUE KEY的第一列。 -如果Key是MUL,则该列是非唯一索引的第一列,其中允许在该列中多次出现给定值。
如果有多个Key值适用于表的给定列,则Key将按PRI、UNI、MUL的顺序显示优先级最高的列。
如果一个UNIQUE索引不能包含NULL值,且表中没有PRIMARY KEY,则该索引可以显示为PRI。如果多个列形成复合唯一索引,则UNIQUE索引可以显示为MUL;尽管这些列的组合是唯一的,但每个列仍然可以保存给定值的多次出现。
-
Default
列的默认值。 -
Extra
列的额外信息。存在序列的列或者将列创建为标识列即GENERATED ALWAYS AS IDENTITY和GENERATED BY DEFAULT AS IDENTITY场景下,extra的是值为auto_increment;当存在类型为TIMESTAMP或TIMESTAMPTZ列的属性上有ON UPDATE CURRENT_TIMESTAMP功能,则显示on update URRENT_TIMESTAMP;将列创建为标识列GENERATED ALWAYS AS (generation_expr) STORED,extra字段显示STORED GENERATED。此字段的显示受full关键字控制。 -
Privileges标识所有授予给一个当前启用的角色或者被一个当前启用的角色授予的特权,包括SELECT、INSERT、UPDATE、REFERENCES。此字段的显示受full关键字控制。 -
Comment列的注释信息。
示例
-
安装模式为mysql的uxdb数据库,创建集群。
-
创建表demo,并改变表对应字段id的约束类型。
uxdb=# create table demo(id int primary key,idme varchar(20),pwd varchar(20)); CREATE TABLE uxdb=# alter table demo add unique (id); ALTER TABLE -
通过
show columns查看信息。uxdb=# show columns from demo; Field | Type | Null | Key | Default | Extra --+---+-++----+-- id | integer | NO | PRI | | idme | character varying(20) | YES | | | pwd | character varying(20) | YES | | | (3 rows) -
通过
show full columns查看信息。uxdb=# show full columns from demo; Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment --+---+-+-++----+--+-+---- id | integer | | NO | PRI | | | INSERT, REFERENCES, SELECT, UPDATE | idme | character varying(20) | | YES | | | | INSERT, REFERENCES, SELECT, UPDATE | pwd | character varying(20) | | YES | | | | INSERT, REFERENCES, SELECT, UPDATE | (3 rows) -
删除对应表。
uxdb=# drop table demo; DROP TABLE
注意
uxdb不支持extra字段显示VIRTUAL GENERATED和default GENERATED显示物化视图的列信息时,权限信息为空。
SHOW CREATE TABLE
SHOW CREATE TABLE — 查询表的建表语句
概要
SHOW { INDEX | INDEXES | KEYS }
{ FROM | IN } table_name
[ { FROM | IN } schema_name ]
[ WHERE expr ]
描述
通过show create table查询表的建表语句。
参数
tablename
表名称。
返回值
表名和其对应的建表语句。
示例
通过show create table查看表,如下所示。
show create table test;
TABLE | CREATE TABLE
---+---
PUBLIC.TEST | SET SEARCH_PATH = PUBLIC; +
| CREATE TABLE PUBLIC.TEST ( +
| TYPE1 CHARACTER VARYING(100)+
| );
(1 row)
SHOW INDEX
SHOW INDEX — 查看某个表中索引的相关信息
概要
SHOW {INDEX | INDEXES | KEYS}
{FROM | IN} tbl_name
[{FROM | IN} schema_name]
[WHERE expr]
描述
通过SHOW INDEX查看某个表中索引的相关信息。
参数
-
tbl_name
指定需要查看索引的数据表名。 -
schema_name
指定需要查看索引的数据表所在的模式名,可省略。如:SHOW INDEX FROM student FROM public;语句表示查看 public模式下student数据表的索引信息。 -
tablename
表名称。 -
[WHERE expr]
指定对执行结果的过滤条件,如where Collation = 'A'。
返回值
返回值结果如下所示。
表 SHOW INDEX返回值说明
| 参数 | 说明 |
|---|---|
| Table | 表的名称。 |
| Non_unique | 如果索引不能包含重复项,则为0;如果包含,则为1。 |
| Key_name | 索引名称,如果索引是主键,则名称总是PRIMARY。(联合索引,索引名称相同) |
| Seq_in_index | 索引Key_name中的列序列号,从1开始。 |
| Column_name | Key_name中对应Seq_in_index的列名,当索引引用属性为表达式时,该值为NULL。 |
| Collation | 列在索引中的排序方式。这可以具有值A(升序)或D(降序)。 |
| Cardinality | UXDB中该值表示索引键值数量的估计值。 |
| Sub_part | MYSQL中代表前缀索引:表示列中被编入索引的字符数量。若列只是部分被编入索引,则该列的值为被编入索引的字符数;若整列被编入索引,则该列的值为 NULL。UXDB兼容此功能时设置为默认值NULL。 |
| Packed | MYSQL中指示key如何被压缩。UXDB兼容此功能时设置为默认值NULL。 |
| Null | 用于显示索引列中是否包含NULL。若列含有NULL,该列的值为YES。否则为空。 |
| Index_type | 显示索引使用的类型和方法,UXDB值包括(BTREE|HASH|GIST|GIN|SPGIST|BRIN)。 |
| Comment | MYSQL中代表索引的DISABLE | ENABLE特性,没有则该列值为空。UXDB兼容时设置为空。 |
| Index_comment | 索引的注释。 |
| Expression | 索引键对应的表达式(扩展字段,对应mysql 8.0 以上版本),没有则为空。 |
示例
UXDB使用SHOW INDEX权限说明如下所示。
对索引所在表对应的模式有对应的USAGE权限即可(和\d+ 表名要求的权限一致)。
show index查询结果集中,部分字段属于关键字,在通过where条件访问时,需要该字段加双引号或反引号才可以正常执行出预期的结果(Collation和Null字段)。
-
表上创建唯一索引
CREATE TABLE tb_stu_info3 ( id INT NOT NULL, name CHAR(45) DEFAULT NULL, dept_id INT DEFAULT NULL, age INT DEFAULT NULL, height INT not NULL ); CREATE TABLE uxdb=# CREATE UNIQUE INDEX height_idx ON tb_stu_info3 (height); CREATE INDEX uxdb=# COMMENT ON INDEX height_idx IS 'is unique index'; COMMENT uxdb=# show index from tb_stu_info3 ; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression ----+--+--+----+---+-+---++---+-+--+----+--+-- tb_stu_info3 | 0 | height_idx | 1 | height | A | 0 | | | | BTREE | | is unique index | (1 row) uxdb=# show index from tb_stu_info3 where "Collation" = 'A'; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression ----+--+--+----+---+-+---++---+-+--+----+--+-- tb_stu_info3 | 0 | height_idx | 1 | height | A | 0 | | | | BTREE | | is unique index | (1 row) uxdb=# show index from tb_stu_info3 where "Collation" = 'D'; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- (0 rows) uxdb=# show index from tb_stu_info3 where Collation = 'A'; ERROR: syntax error at or near "=" LINE 1: show index from tb_stu_info3 where Collation = 'A'; ^ -
约束
CREATE TABLE test1 ( id serial PRIMARY KEY, code INTEGER, label text, CONSTRAINT test1_uq UNIQUE (code, label)); CREATE TABLE uxdb=# show index from test1; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- test1 | 0 | PRIMARY | 1 | id | A | 0 | | | | BTREE | | | test1 | 0 | test1_uq | 1 | code | A | 0 | | | YES | BTREE | | | test1 | 0 | test1_uq | 2 | label | A | 0 | | | YES | BTREE | | | (3 rows) uxdb=# show index from test1 where "Null" = 'yes'; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- (0 rows) uxdb=# show index from test1 where "Null" = 'YES'; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- test1 | 0 | test1_uq | 1 | code | A | 0 | | | YES | BTREE | | | test1 | 0 | test1_uq | 2 | label | A | 0 | | | YES | BTREE | | | (2 rows) uxdb=# show index from test1 where Comment IS NULL; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- (0 rows) uxdb=# show index from test1 where Comment IS NOT NULL; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--++----+---+-+---++---+-+--+----++-- test1 | 0 | PRIMARY | 1 | id | A | 0 | | | | BTREE | | | test1 | 0 | test1_uq | 1 | code | A | 0 | | | YES | BTREE | | | test1 | 0 | test1_uq | 2 | label | A | 0 | | | YES | BTREE | | | (3 rows) -
索引引用属性为表达式
uxdb=# CREATE TABLE t1 (col1 VARCHAR(10),col2 VARCHAR(20)); CREATE TABLE uxdb=# CREATE INDEX func_index on t1 ((ABS(col1))); CREATE INDEX uxdb=# CREATE TABLE t2(col1 text not NULL,col2 text); CREATE TABLE uxdb=# CREATE INDEX func_index2 on t2 (textcat(col1,col2)); CREATE INDEX uxdb=# CREATE TABLE t3(col1 VARCHAR(10) not NULL, col2 int); CREATE TABLE uxdb=# CREATE INDEX func_index3 on t3 ((col2 > 1)); CREATE INDEX uxdb=# CREATE TABLE func_index_test6 (f1 text, f2 text); CREATE TABLE uxdb=# CREATE UNIQUE INDEX func_index_t on func_index_test6 ((f1 || f2) text_ops); CREATE INDEX uxdb=# show index in t1; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--+--+----+---+-+---++---+-+--+----++---- t1 | 1 | func_index | 1 | | A | 0 | | | YES | BTREE | | | abs((col1)::text) (1 row) uxdb=# show index in t1 from public; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--+--+----+---+-+---++---+-+--+----++---- t1 | 1 | func_index | 1 | | A | 0 | | | YES | BTREE | | | abs((col1)::text) (1 row) uxdb=# show index from t2; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--+---+----+---+-+---++---+-+--+----++- t2 | 1 | func_index2 | 1 | | A | 0 | | | YES | BTREE | | | textcat(col1, col2) (1 row) uxdb=# show index from t3; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression --+--+---+----+---+-+---++---+-+--+----++-- t3 | 1 | func_index3 | 1 | | A | 0 | | | YES | BTREE | | | (col2 > 1) (1 row) uxdb=# show index from func_index_test6; Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Expression ---+--+----+----+---+-+---++---+-+--+----++-- func_index_test6 | 0 | func_index_t | 1 | | A | 0 | | | YES | BTREE | | | (f1 || f2) (1 row)
兼容性
UXDB数据库中外键约束不会自动创建索引,因此带外键约束的,通过show index查询相关索引信息为空。
创建表时指定serial类型,该列并未自动创建索引,show index执行结果为空。
如果建表时列指定唯一约束,UXDB中show index时则索引对应的Key_name命名规则为“表名_列名_key”。
SHOW VARIABLES
SHOW VARIABLES — 显示所有配置参数的值和描述
概要
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern' | WHERE expr]
描述
通过show variables查看数据库参数的值和描述。此语句不需要任何权限,它只需要能够连接到服务器就可以来查看服务器的全部或指定参数配置信息。其中可选字段global/session可以决定查看全局级变量或会话级系统变量。like/where从句,如果存在,则匹配对应变量名查询。
参数
global|session
系统变量分为全局级(global)和会话级(session),在客户端连接到服务端后,可以分别查看全局级的系统变量和当前连接会话的会话级系统变量。当不显式指定为session时,将优先显示会话级系统变量(如果不存在,将显示全局级系统变量)。
示例
show variables/show session variables查看会话级系统变量。
uxdb=# show variables;
name | setting | description
---++-
allow_in_place_tablespaces | off | Allows tablespaces directly inside ux_tblspc, for testing.
.
.
.
(415 rows)
show global variables like '%password_c%';查看使用like子句模糊匹配的会话级系统变量。
uxdb=# show global variables like '%password_c%';
name | setting | description
----+----+-
password_condition_digit | 1 | Minimum number of digits in a password.
password_condition_lower_case_character | 1 | Minimum number of lower case characters in a password.
password_condition_symbol | 1 | Minimum number of symbols in a password.
password_condition_upper_case_character | 1 | Minimum number of upper case characters in a password.
(4 rows)
START TRANSACTION
START TRANSACTION — 开始一个事务块
概要
START TRANSACTION [ transaction_mode [, ...] ]
其中 transaction_mode 是以下之一:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
[ NOT ] DEFERRABLE
描述
该命令开始一个新的事务块。如果指定了隔离级别、读/写模式或可延迟模式,则新事务具有这些特性,就像执行了 SET TRANSACTION 命令一样。这与BEGIN命令相同。
参数
有关此语句参数含义的信息,请参见 SET TRANSACTION。
兼容性
在标准中,不需要发出 START TRANSACTION 来开始一个事务块:任何 SQL 命令都会隐式开始一个块。UXsinoDB的行为可以看作是在不遵循START TRANSACTION(或 BEGIN)的每个命令之后隐式发出COMMIT,因此通常被称为“自动提交”。其他关系型数据库系统可能会提供自动提交功能作为一种便利。
DEFERRABLE transaction_mode 是 UXsinoDB 的语言扩展。
SQL 标准要求在连续的 transaction_modes 之间使用逗号,但由于历史原因,UXsinoDB 允许省略逗号。
请参见 SET TRANSACTION的兼容性部分。
另请参阅
BEGIN,COMMIT,ROLLBACK,SAVEPOINT,SET TRANSACTION
TRUNCATE
TRUNCATE — 清空一个表或一组表
概要
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
描述
TRUNCATE 快速地从一组表中删除所有行。它与未限定的 DELETE 在每个表上具有相同的效果,但由于它实际上不会扫描表,因此速度更快。此外,它立即回收磁盘空间, 而不需要后续的 VACUUM操作。这在大型表上最有用。
参数
-
name
要清空的表的名称(可选模式限定)。如果在表名之前指定了ONLY,则仅清空该表。如果未指定ONLY,则清空该表及其所有后代表(如果有)。可以在表名后明确指定*,以表示包括后代表。 -
RESTART IDENTITY
自动重新启动被截断表的列所拥有的序列。 -
CONTINUE IDENTITY
不更改序列的值。这是默认值。 -
CASCADE
自动清空所有具有外键引用的表,这些引用指向任何命名表或由于CASCADE添加到组中的任何表。 -
RESTRICT
拒绝清空任何具有外键引用的表,这些引用来自于未在命令中列出的表。这是默认值。
注意事项
您必须拥有表的 TRUNCATE 权限才能清空它。
TRUNCATE在要操作的表上要求一个ACCESS EXCLUSIVE锁,这会阻塞所有其他在该表上的 并发操作。当指定RESTART IDENTITY时,任何需要被 重新开始的序列也会被排他地锁住。如果要求表上的并发访问,那么应该使用DELETE命令。
TRUNCATE不能被用在被其他表外键引用的表上,除非那些表也在同一个命令中被阶段。这些情况中的可行性检查将会要求表扫描,并且重点不是为了做扫描。CASCADE选项可以被用来自动地包括所有依赖表 — 但使用它时要非常注意,否则可能丢失数据!特别注意的是,当要被截断的表是一个分区时,兄弟节点分区不会受到影响,但是所有的引用表都发生级联,他们的分区也没有区别。
TRUNCATE将不会引发表上可能存在的任何ON DELETE触发器。但是它将会引发ON TRUNCATE触发器。如果在这些表的任意一个上定义了ON TRUNCATE触发器,那么所有的BEFORE TRUNCATE触发器将在任何截断发生之前被引发,而所有AFTER TRUNCATE触发器将在最后 一次截断完成并且所有序列被重置之后引发。触发器将以表被处理的顺序被引发(首先是那些被列在命令中的,然后是由于级联被加入的)。
TRUNCATE不是MVCC安全的。截断之后, 如果并发事务使用的是一个在截断发生前取得的快照,表将对这些并发事务呈现为空。
从表中数据的角度来说,TRUNCATE是事务安全的:如果所在的事务没有提交,阶段将会被安全地回滚。
在指定了RESTART IDENTITY时,隐含的ALTER SEQUENCE RESTART操作也会被事务性地完成。也就是说,如果所在事务没有提交,它们也将被回滚。这和ALTER SEQUENCE RESTART的通常行为不同。注意如果事务回滚前在被重启序列上还做了额外的序列操作,这些操作在序列上的效果 也将被回滚,但是它们在currval()上的效果不会被回滚。也就 是说,在事务之后,currval()将继续反映在失败事务内得到的 最后一个序列值,即使序列本身可能已经不再与此一致。这和失败事务之后currval()的通常行为类似。
如果受到外部数据包装器的支持,TRUNCATE可用于外部表。
示例
清空表bigtable和fattable:
TRUNCATE bigtable, fattable;
同样,也重置任何相关的序列生成器:
TRUNCATE bigtable, fattable RESTART IDENTITY;
清空表othertable, 并通过外键约束级联到引用其他表的任何表::
TRUNCATE othertable CASCADE;
兼容性
SQL:2008 标准包括一个带有语法 TRUNCATE TABLE tablename 的 TRUNCATE 命令。该标准中还出现了 CONTINUE IDENTITY/RESTART IDENTITY子句,但它们具有略微不同但相关的含义。该命令的某些并发行为由标准定义,因此如果必要,应将上述注释与其他实现进行比较。
另请参阅
UNLISTEN
UNLISTEN — 停止监听通知
概要
UNLISTEN { channel | * }
描述
UNLISTEN 用于删除现有的 NOTIFY 事件注册。UNLISTEN 取消当前 UXsinoDB 会话作为通知通道channel 的侦听器的任何现有注册。特殊通配符 * 取消当前会话的所有侦听器注册。
NOTIFY包含更详细的 LISTEN 和 NOTIFY 的使用讨论。
参数
-
channel
通知通道的名称(任何标识符)。 -
*
清除此会话的所有当前侦听注册。
注意事项
您可以取消您没有侦听的内容;不会出现警告或错误。
在每个会话结束时,UNLISTEN * 会自动执行。
执行了 UNLISTEN 的事务不能准备为两阶段提交。
示例
进行注册:
LISTEN virtual;
NOTIFY virtual;
Asynchronous notification "virtual" received from server process with PID 8448.
执行 UNLISTEN 后,将忽略进一步的 NOTIFY 消息:
UNLISTEN virtual;
NOTIFY virtual;
-- no NOTIFY event is received
兼容性
SQL 标准中没有 UNLISTEN 命令。
另请参阅
UPDATE
UPDATE — 更新表中的行
概要
[ WITH [ RECURSIVE ] with_query [, ...] ]
UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
[ NATURAL join_type JOIN { table_name [ * ] [ [ AS ] alias ] | subquery }
join_type JOIN { table_name [ * ] [ [ AS ] alias ] | subquery } [ ON join_condition | USING ( join_column [,...] ) ] ]
SET { column_name = { expression | DEFAULT } |
( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
( column_name [, ...] ) = ( sub-SELECT )
} [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition | WHERE CURRENT OF cursor_name ]
[ ORDER BY column_name [ LIMIT limit_count ] ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
描述
UPDATE 改变满足条件的所有行中指定列的值。只需要在 SET 子句中提到要修改的列;未明确修改的列保留其先前的值。
使用数据库中其他表中包含的信息修改表的两种方法:使用子查询或在 FROM 子句中指定其他表。哪种技术更合适取决于具体情况。
可选的 RETURNING 子句使 UPDATE 根据实际更新的每行计算并返回值。可以计算使用表的列或在 FROM中提到的其他表的列的任何表达式。使用表的列的新(更新后)值。RETURNING 列表的语法与 SELECT的输出列表相同。
必须对表具有 UPDATE 权限,或者至少对要更新的列具有 UPDATE 权限。还必须对在 expressions 或WHERE 子句中读取其值的任何列具有 SELECT 权限。
UPDATE...JOIN...SET用包含在数据库其他表中的信息来修改一个表。
使用UPDATE...JOIN...SET语句时,不能出现FROM子句和WHERE CURRENT OF子句。
参数
-
with_query
WITH子句允许您指定一个或多个子查询,这些子查询可以在UPDATE查询中通过名称引用。详见SELECT。 -
table_name
要更新的表的名称(可选模式限定符)。如果在表名之前指定了ONLY,则仅在指定的表中更新匹配的行。如果没有指定ONLY,则匹配的行也会在从指定表继承的任何表中更新。可选地,在表名后面指定*,以明确表示包括后代表。 -
alias
目标表的替代名称。提供别名时,它完全隐藏了实际表名。例如,给定UPDATE foo AS f,则UPDATE语句的其余部分必须将此表称为f而不是foo。 -
subquery
子查询语句,该子查询对象不能作为更新对象。 -
column_name
要更新的表中的列的名称。如果需要,列名可以带有子字段名或数组下标。不要在目标列的规范中包括表的名称,例如,UPDATE table_name SET table_name.col = 1是无效的。 -
expression
要分配给该列的表达式。该表达式可以使用该表中此列和其他列的旧值。 -
DEFAULT
将列设置为其默认值(如果没有为其分配特定的默认表达式,则该值将为NULL)。标识列将设置为由关联序列生成的新值。对于生成的列,允许指定此选项,但仅指定从其生成表达式计算列的正常行为。 -
sub-SELECT
一个SELECT子查询,它产生与其前面括号中列列表中列数相同的输出列。当执行时,子查询必须不超过一行。如果它产生一行,则将其列值分配给目标列;如果它没有产生行,则将NULL 值分配给目标列。子查询可以引用正在更新的表的当前行的旧值。 -
from_item
一个表达式,允许其他表中的列出现在WHERE条件和更新表达式中。这使用与SELECT语句的FROM子句 子句相同的语法;例如,可以指定表名的别名。除非您打算进行自连接(在这种情况下,它必须在from_item中以别名出现),否则不要重复目标表。 -
condition
一个返回类型为boolean的表达式。只有当该表达式返回true时,才会更新该行。 -
cursor_name
在WHERE CURRENT OF条件中使用的游标名称。要更新的行是最近从该游标中获取的行。该游标必须是针对UPDATE目标表的非分组查询。请注意,WHERE CURRENTOF不能与布尔条件一起指定。有关使用带有WHERE CURRENT OF的游标的更多信息,请参见DECLARE。 -
output_expression
在每个行更新后由UPDATE命令计算并返回的表达式。该表达式可以使用table_name或FROM中列出的任何表的列名。写*以返回所有列。 -
output_name
用于返回列的名称。
输出
成功完成后,UPDATE命令返回一个形如
UPDATE count
的命令标记。count是更新的行数,包括值未更改的匹配行。请注意,当更新被BEFORE UPDATE触发器抑制时,数量可能少于满足condition的行数。如果count为0,则查询未更新任何行(这不被视为错误)。
如果UPDATE命令包含RETURNING子句,则结果将类似于包含在RETURNING列表中定义的列和值的SELECT语句,计算在命令更新的行上。
注意事项
当存在FROM子句时,实际上发生的是将目标表与from_item列表中提到的表连接,并且每个连接的输出行表示目标表的更新操作。使用FROM时,应确保连接为每个要修改的行最多产生一行输出。换句话说,目标行不应与其他表中的多个行连接。如果确实如此,则只会使用一个连接行来更新目标行,但是将使用哪个连接行不容易预测。
由于这种不确定性,仅在子选择中引用其他表比使用连接更安全,尽管通常比使用连接更难阅读和更慢。
在分区表的情况下,更新行可能会导致其不再满足包含分区的分区约束条件。在这种情况下,如果分区树中有其他分区满足此行的分区约束条件,则将该行移动到该分区。如果没有这样的分区,则会发生错误。在幕后,行移动实际上是一个DELETE和INSERT操作。
有可能在移动行时,正在进行的并发UPDATE或DELETE操作会出现序列化失败错误。假设会话1正在执行对分区键的UPDATE,同时对于此行可见的并发会话2执行对此行的UPDATE或DELETE操作。在这种情况下,会话2的UPDATE或DELETE将检测到行移动并引发序列化失败错误(始终返回SQLSTATE代码“40001”)。如果发生这种情况,应用程序可能希望重试事务。在表未分区或不存在行移动的情况下,会话2将识别新更新的行并执行对此新行版本的UPDATE/DELETE。
请注意,虽然可以将行从本地分区移动到外部表分区(如果外部数据包装器支持元组路由),但不能将行从外部表分区移动到另一个分区。如果发现外键直接引用源分区的祖先与在UPDATE查询中提到的祖先不同,则尝试将行从一个分区移动到另一个分区将失败。
由于数据库update更新机制原因,limit查出来的数据会发生变化,建议在update中使用limit时同时使用order by排序子句。
示例
将表films的kind列中的单词Drama更改为Dramatic:
UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';
调整表weather中一行的温度条目并将降水量重置为其默认值:
UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
WHERE city = 'San Francisco' AND date = '2003-07-03';
执行相同的操作并返回更新的条目:
UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
WHERE city = 'San Francisco' AND date = '2003-07-03'
RETURNING temp_lo, temp_hi, prcp;
使用替代的列列表语法执行相同的更新:
UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
WHERE city = 'San Francisco' AND date = '2003-07-03';
使用FROM子句语法将销售人员的销售计数增加,该销售人员管理Acme Corporation的帐户:
UPDATE employees SET sales_count = sales_count + 1 FROM accounts
WHERE accounts.name = 'Acme Corporation'
AND employees.id = accounts.sales_person;
执行相同的操作,使用WHERE子句中的子查询:
UPDATE employees SET sales_count = sales_count + 1 WHERE id =
(SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');
将帐户表中的联系人名称更新为与当前分配的销售人员匹配:
UPDATE accounts SET (contact_first_name, contact_last_name) =
(SELECT first_name, last_name FROM employees
WHERE employees.id = accounts.sales_person);
可以使用连接实现类似的结果:
UPDATE accounts SET contact_first_name = first_name,
contact_last_name = last_name
FROM employees WHERE employees.id = accounts.sales_person;
但是,如果employees.id不是唯一键,则第二个查询可能会产生意外结果,而第一个查询保证在存在多个匹配时会引发错误。id匹配。此外,如果特定的 accounts.sales_person 条目没有匹配,第一个查询将把相应的名称字段设置为NULL,而第二个查询将不会更新该行。
更新摘要表中的统计数据以匹配当前数据:
UPDATE summary s SET (sum_x, sum_y, avg_x, avg_y) =
(SELECT sum(x), sum(y), avg(x), avg(y) FROM data d
WHERE d.group_id = s.group_id);
尝试插入新的库存项目以及库存数量。如果该项目已经存在,则更新现有项目的库存计数。为了在不使整个事务失败的情况下执行此操作,请使用保存点:
BEGIN;
-- other operations
SAVEPOINT sp1;
INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
-- Assume the above fails because of a unique key violation,
-- so now we issue these commands:
ROLLBACK TO sp1;
UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
-- continue with other operations, and eventually
COMMIT;
更改游标 c_films 当前所在行的表 films 的 kind 列:
UPDATE films SET kind = 'Dramatic' WHERE CURRENT OF c_films;
UPDATE语句可以使用别名来设置表中数据。
在提供了一个别名时,它会完全隐藏表的真实名称,如下所示。
update table_name as alias_name set table_name.column_name1 = 3, alias_name.column_name2 = 'wangwu' where column_name1 = 3; -- ok
update table_name as alias_name set table_name.column_name1 = 3, alias_name.column_name2 = 'wangwu' where alias_name.column_name1 = 3; -- ok
update table_name as alias_name set table_name.column_name1 = 3, alias_name.column_name2 = 'wangwu' where table_name.column_name1 = 3; -- failed
在提供别名或没提供别名,剩余的语句都可以直接使用列名方式来引用。
UPDATE...JOIN...SET语句示例,如下所示。
--使用左连接更新目标表
UPDATE t1 LEFT JOIN t2 ON t1.ID = t2.ID SET t1.ID = 4;
--使用交叉连接更新目标表
UPDATE t1 CROSS JOIN t2 SET t2.ID = 6;
--根据子查询更新目标表
UPDATE t1 CROSS JOIN (SELECT * FROM t2) a SET t1.ID = 8;
--多重连接更新表
UPDATE t1 CROSS JOIN (t2 RIGHT JOIN t3 USING(ID)) SET t2.ID = 4;
按照id排序后更新满足条件的前三条记录,如下所示。
update test set name = 'aaa' where id<10 order by id limit 3
兼容性
此命令符合 SQL 标准,但是 FROM 和 RETURNING 子句是 UXsinoDB 扩展,使用 UPDATE 时可以使用WITH。
其他一些数据库系统提供了一个 FROM 选项,其中目标表应再次列在 FROM 中。这不是 UXsinoDB 解释 FROM的方式。在移植使用此扩展的应用程序时要小心。
根据标准,目标列名称的括号子列表的源值可以是任何产生正确列数的行值表达式。UXsinoDB 仅允许源值为行构造函数或子SELECT。在行构造函数的情况下,可以将单个列的更新值指定为 DEFAULT,但在子 SELECT 中不行。
VACUUM
VACUUM — 垃圾回收并可选地分析数据库
概要
VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
where option can be one of:
FULL [ boolean ]
FREEZE [ boolean ]
VERBOSE [ boolean ]
ANALYZE [ boolean ]
DISABLE_PAGE_SKIPPING [ boolean ]
SKIP_LOCKED [ boolean ]
INDEX_CLEANUP { AUTO | ON | OFF }
PROCESS_TOAST [ boolean ]
TRUNCATE [ boolean ]
PARALLEL integer
其中table_and_columns是:
table_name [ ( column_name [, ...] ) ]
描述
VACUUM 会回收被死元组占用的存储空间。在正常的 UXsinoDB操作中,被删除或被更新所淘汰的元组并不会从它们所在的表中物理删除;它们会一直存在,直到执行VACUUM。因此,需要定期执行 VACUUM,特别是对于频繁更新的表。
如果没有 table_and_columns 列表,VACUUM 会处理当前用户有权限清理的当前数据库中的每个表和物化视图。如果有列表,VACUUM只会处理那些表。
VACUUM ANALYZE 会为每个选定的表执行 VACUUM,然后执行ANALYZE。这是常规维护脚本的一个方便的组合形式。有关其处理的更多详细信息,请参见ANALYZE。
VACUUM(不带FULL)仅回收空间并使其可供重用。该命令形式可以与表的正常读写并行操作,因为不会获取独占锁。但是,在大多数情况下,不会将额外的空间返回给操作系统;它只是在同一表中保持可供重用。它还允许我们利用多个CPU 来处理索引。此功能称为并行VACUUM。要禁用此功能,可以使用PARALLEL选项并将并行工作程序指定为零。VACUUM FULL将整个表的内容重写为一个新的磁盘文件,没有额外的空间,从而可以将未使用的空间返回给操作系统。这种形式要慢得多,并且在处理过程中需要对每个表进行ACCESS EXCLUSIVE锁定。
当选项列表被括在括号中时,选项可以以任何顺序编写。没有括号,选项必须按上面显示的顺序指定。括号语法在UXsinoDB中添加;不带括号的语法已被弃用。
参数
-
FULL
选择“full” vacuum,可以回收更多的空间,但需要更长的时间并独占锁定表。这种方法还需要额外的磁盘空间,因为它会写入表的新副本,并且在操作完成之前不会释放旧副本。通常,只有在需要从表内回收大量空间时才应使用此方法。 -
FREEZE
选择元组的积极“冻结”。指定FREEZE等效于使用设置为零的vacuum_freeze_min_age和vacuum_freeze_table_age参数执行VACUUM。当重写表时,总是执行积极的冻结,因此在指定FULL时,此选项是多余的。 -
VERBOSE
为每个表打印详细的 vacuum 活动报告。 -
ANALYZE
更新规划器用于确定执行查询的最有效方式的统计信息。 -
DISABLE_PAGE_SKIPPING
通常,VACUUM将基于可见性映射跳过页面。已知所有元组都被冻结的页面总是会被跳过,而那些所有元组对所有事务都可见的页面则可能会被跳过(除非执行的是激进的清理)。此外,除非在执行激进的清理时,一些页面也可能会被跳过,这样可避免等待其他页面完成对其使用。这个选项禁用所有的跳过页面的行为,其意图是只在可见性映射内容被怀疑时使用,这种情况只有在硬件或者软件问题导致数据库损坏时才会发生。 -
SKIP_LOCKED
指定VACUUM在开始处理关系时不等待任何冲突锁定的释放:
如果一个关系不能立即锁定而需要等待,那么该关系将被跳过。需要注意的是,即使使用了这个选项,VACUUM在打开关系的索引时仍可能会被阻塞。此外,VACUUM ANALYZE在从分区、表继承子和某些类型的外部表中获取样本行时仍可能会被阻塞。另外,虽然VACUUM通常会处理指定分区表的所有分区,但如果分区表存在冲突锁,则该选项将导致VACUUM跳过所有分区。
INDEX_CLEANUP
通常情况下,当表中死元组很少时,VACUUM会跳过索引清理。在这种情况下,处理表的所有索引的成本预计将大大超过删除死索引元组的好处。可以使用此选项强制VACUUM在有多个死元组时处理索引。默认值为AUTO,允许VACUUM在适当时跳过索引清理。如果将INDEX_CLEANUP设置为ON,VACUUM将谨慎地从索引中删除所有死元组。这可能对与早期版本的UXsinoDB向后兼容性有用,因为这是标准行为。
将INDEX_CLEANUP设置为OFF可以强制VACUUM始终跳过索引清理,即使表中有许多死元组。当需要尽快运行VACUUM以避免即将发生的事务ID环绕时,这可能很有用。然而,由vacuum_failsafe_age控制的环绕故障保护机制通常会自动触发,以避免事务ID环绕故障,并且应该优先考虑。如果不定期执行索引清理,则性能可能会受到影响,因为随着表的修改,索引将累积死元组,而表本身将累积无法删除的死行指针,直到完成索引清理为止。
此选项对于没有索引的表没有影响,如果使用了FULL选项,则会被忽略。它也不会影响事务ID环绕故障保护机制。当触发时,它将跳过索引清理,即使INDEX_CLEANUP设置为ON。
-
PROCESS_TOAST
指定VACUUM应尝试处理每个关系的相应TOAST表(如果存在)。这通常是期望的行为,也是默认行为。将此选项设置为false可能在只需要清理主关系时有用。使用FULL选项时需要此选项。 -
TRUNCATE
指定VACUUM应尝试截断表末尾的任何空页面,并允许将截断页面的磁盘空间返回给操作系统。这通常是期望的行为,并且是默认行为,除非已为要清理的表设置了vacuum_truncate选项。将此选项设置为false可能有用,以避免截断页面。ACCESS EXCLUSIVE锁定表以执行截断所需的操作。如果使用了FULL选项,则忽略此选项。 -
PARALLEL
使用integer个后台工作进程并行执行VACUUM的索引清理和索引清理阶段。执行操作的工作进程数等于支持并行清理的关系上的索引数,这受到使用PARALLEL选项指定的工作进程数的限制,如果有的话,这进一步受到max_parallel_maintenance_workers的限制。只有当索引的大小大于min_parallel_index_scan_size时,索引才能参与并行清理。请注意,并不保证在执行过程中使用integer指定的并行工作进程数。可能会使用比指定的工作进程数更少的工作进程,甚至根本不使用工作进程。每个索引只能使用一个工作进程。因此,只有在表中至少有2个索引时才启动并行工作进程。在每个阶段开始之前启动清理工作进程,并在阶段结束时退出。这些行为可能会在未来的版本中发生变化。此选项不能与FULL选项一起使用。 -
boolean
指定所选选项是否应打开或关闭。您可以编写TRUE、ON或1来启用选项,FALSE、OFF或0来禁用选项。也可以省略boolean值,在这种情况下,假定为TRUE。 -
integer
指定传递给所选选项的非负整数值。 -
table_name
指定要清理的特定表或材料化视图的名称(可选模式限定)。如果指定的表是分区表,则清理其所有叶分区。 -
column_name
分析特定列的名称。默认为所有列。如果指定了列列表,则必须同时指定ANALYZE。
输出
当指定VERBOSE时,VACUUM会发出进度消息,指示当前正在处理哪个表。还会打印有关表的各种统计信息。
注意事项
要清理表,必须是表的所有者或超级用户。但是,允许数据库所有者清理其数据库中的所有表,除了共享目录。(共享目录的限制意味着只有超级用户才能执行真正的数据库范围的VACUUM。)VACUUM将跳过调用用户没有清理权限的任何表。
VACUUM不能在事务块内执行。
对于具有 GIN 索引的表,VACUUM(以任何形式)还会通过将挂起的索引条目移动到主 GIN 索引结构的适当位置来完成任何挂起的索引插入。
我们建议定期对所有数据库进行清理,以删除死行。UXsinoDB 包括一个“autovacuum”工具,可以自动执行例行清理维护。
FULL选项不建议常规使用,但在特殊情况下可能有用。例如,当您已删除或更新表中的大多数行,并希望表在物理上缩小以占用更少的磁盘空间并允许更快的表扫描时,VACUUM FULL通常会比普通的VACUUM更缩小表。
PARALLEL选项仅用于清理目的。如果此选项与ANALYZE选项一起指定,则不会影响ANALYZE。
VACUUM会导致I/O流量显著增加,这可能会导致其他活动会话的性能不佳。因此,有时建议使用基于成本的清理延迟功能。对于并行清理,每个工作进程的休眠时间与该工作进程完成的工作成比例。
每个运行VACUUM而不带FULL选项的后端将在ux_stat_progress_vacuum视图中报告其进度。运行VACUUM FULL的后端将在ux_stat_progress_cluster视图中报告其进度。
示例
要清理单个表onek,为优化器进行分析并打印详细的清理活动报告:
VACUUM (VERBOSE, ANALYZE) onek;
兼容性
SQL标准中没有VACUUM语句。
VALUES
VALUES — 计算一组行
概要
VALUES ( expression [, ...] ) [, ...]
[ ORDER BY sort_expression [ ASC | DESC | USING operator ] [, ...] ]
[ LIMIT { count | ALL } ]
[ OFFSET start [ ROW | ROWS ] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
描述
VALUES 计算由值表达式指定的行值或一组行值。它最常用于在更大的命令中生成一个“常量表”,但它也可以单独使用。
当指定多行时,所有行必须具有相同数量的元素。生成的表的列的数据类型由该列中出现的表达式的显式或推断类型组合确定,使用与 UNION相同的规则。
在更大的命令中,VALUES 在语法上允许出现在任何 SELECT 出现的地方。因为它被语法视为 SELECT,所以可以使用ORDER BY、LIMIT(或等效的 FETCH FIRST)和 OFFSET 子句与 VALUES 命令。
参数
-
expression
要计算并插入到生成的表(一组行)中指定位置的常量或表达式。在INSERT的顶层出现的VALUES列表中,可以用DEFAULT替换expression,表示应插入目标列的默认值。DEFAULT不能用于其他情况。VALUES出现在其他上下文中时使用。 -
sort_expression
表示如何对结果行进行排序的表达式或整数常量。此表达式可以引用VALUES结果的列,如column1、column2等。有关详细信息,请参见 ORDER BY子句 。 -
operator
排序运算符。有关详细信息,请参见 ORDER BY子句。 -
count
要返回的最大行数。有关详细信息,请参见 LIMIT子句。 -
start
开始返回行之前要跳过的行数。有关详细信息,请参见LIMIT子句。
注意事项
应避免使用具有非常大行数的 VALUES 列表,因为可能会遇到内存不足或性能差的问题。出现在 INSERT 中的 VALUES是一种特殊情况(因为可以从 INSERT 的目标表中知道所需的列类型,而无需通过扫描 VALUES列表来推断),因此它可以处理比其他上下文中实际可行的更大的列表。
示例
一个简单的 VALUES 命令:
VALUES (1, 'one'), (2, 'two'), (3, 'three');
这将返回一个包含两列和三行的表。它实际上相当于:
SELECT 1 AS column1, 'one' AS column2
UNION ALL
SELECT 2, 'two'
UNION ALL
SELECT 3, 'three';
更通常地,VALUES 用于更大的 SQL 命令中。最常见的用法是在 INSERT 中:
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
在 INSERT 的上下文中,VALUES 列表的条目可以是 DEFAULT,表示应该使用列默认值而不是指定值:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'),
('T_601', 'Yojimbo', 106, DEFAULT, 'Drama', DEFAULT);
VALUES 还可以用于子 SELECT 可能会被编写的地方,例如在 FROM 子句中:
SELECT f.*
FROM films f, (VALUES('MGM', 'Horror'), ('UA', 'Sci-Fi')) AS t (studio, kind)
WHERE f.studio = t.studio AND f.kind = t.kind;
UPDATE employees SET salary = salary * v.increase
FROM (VALUES(1, 200000, 1.2), (2, 400000, 1.4)) AS v (depno, target, increase)
WHERE employees.depno = v.depno AND employees.sales >= v.target;
请注意,当在FROM子句中使用VALUES时,需要使用AS子句,就像SELECT一样。不需要AS子句为所有列指定名称,但最好这样做。(在UXsinoDB中,VALUES的默认列名为column1,column2等,但这些名称在其他数据库系统中可能不同。)
当在INSERT中使用VALUES时,所有值都会自动强制转换为相应目标列的数据类型。在其他上下文中使用时,可能需要指定正确的数据类型。如果所有条目都是带引号的文字常量,则强制转换第一个条目就足以确定所有条目的假定类型:
SELECT * FROM machines
WHERE ip_address IN (VALUES('192.168.0.1'::inet), ('192.168.0.10'), ('192.168.1.43'));
提示
对于简单的IN测试,最好依赖于IN的标量列表形式,而不是编写上面显示的VALUES查询。标量列表方法需要更少的编写,并且通常更有效。
兼容性
VALUES符合SQL标准。LIMIT和OFFSET是UXsinoDB扩展;另请参见SELECT下面的内容。
另请参见