14.SQL语句:COMMIT 到 CREATE LANGUAGE
本章包含以下内容SQL语句:
-
COMMIT
-
COMMIT PREPARED
-
COPY
-
CREATE ACCESS METHOD
-
CREATE AGGREGATE
-
CREATE CAST
-
CREATE COLLATION
-
CREATE CONTEXT
-
CREATE CONVERSION
-
CREATE DATABASE
-
CREATE DATABASE LINK
-
CREATE DIRECTORY
-
CREATE DOMAIN
-
CREATE EVENT TRIGGER
-
CREATE EXTENSION
-
CREATE FOREIGN DATA WRAPPER
-
CREATE FOREIGN TABLE
-
CREATE FUNCTION
-
CREATE GROUP
-
CREATE INDEX
-
CREATE LANGUAGE
14.1.COMMIT
COMMIT提交当前事务。该公司所做的所有变更都将显示给他人,并保证在崩溃时仍能发生 持久。
提交当前事务不需要任何权限。
COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
WORKTRANSACTION可选关键词。它们没有效果。
ANDCHAIN如果指定了
ANDCHAIN,立即启动具有相同事务特征的新事务(参见SET TRANSACTION)作为一个刚刚完成的。 否则, 不开始新事务。
提交当前事务,使所有变更持久:
COMMIT;
COMMIT命令符合SQL标准。COMMITTRANSACTION是KingbaseES的扩展。
14.2.COMMIT PREPARED
COMMITPREPARED提交准备好的事务。
要提交预备事务,您必须是同一用户或超级用户。 但不需要在执行事务的同一会话中。
该命令不能在一个事务块中执行。准备工作将立即提交。
sys_prepared_xacts所有当前可用的准备事务都列在系统视图中。
COMMIT PREPARED transaction_id
transaction_id提交事务的事务标识符。
提交事务标识符
foobar标识事务:COMMIT PREPARED 'foobar';
COMMITPREPARED是一种 KingbaseES扩展。其意图是用于外部事务管理系统,其中一些已被标准覆盖(例如 X/Open XA),但是那些系统 SQL 这方面没有标准化。
14.3.COPY
COPY在 KingbaseES标准文件系统文件之间的表和标准文件 移动数据。COPYTO复制一个表的内容 到一个文件,而COPYFROM将数据从文件复制到表(将数据添加到表中原始数据) 据)。COPYTO也可以复制一个SELECT查询结果。若指定列表,
COPY只有指定列 将数据复制到文件或从文件复制到指定列。如果列表中没有列出,COPYFROM将默认值插入这些列。带文件名
COPY指示 KingbaseES服务器直接读取文件 或者写文件。这个文件必须是 KingbaseES用户(运行服务器的用户) ID) 可访问的名称应从服务器的角度指定。当指定时PROGRAM服务器从程序标准执行给定的命令 输出读取或写入程序的标准输入。该程序必须从服务器的角度指定,并且 必须是KingbaseES用户可以执行。STDIN或者STDOUT数据将通过客户 户与服务器之间的连接传输。
COPYTO只能用于纯表,不能用于视图。 但是你可以写COPY(SELECT*FROMviewname) TO...复制视图的当前内容。
COPYFROM可用于普通表、外表、分区表或INSTEADOFINSERT触发器视图。
COPY只处理提到的表,不复制从子表 数据或者复制数据到子表中。例如COPYtableTO 会显示与SELECT*FROMONLYtable数据相同。还有COPY(SELECT*FROMtable) TO ... 可用于转储继承层次中的所有数据。你必须有被子
COPYTO读取表上的选择特权, 以及被COPYFROM插入表上的插入特权。 在命令中列出的特权就足够了。如果对表使用行级安全,则相关
SELECT应用策略COPYtableTO语句。目前,行级安全表不支持COPYFROM。但可以使用等效INSERT语句。
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 [, ...] ) ] where option can be one of: FORMAT format_name FREEZE [ boolean ] DELIITER 'delimiter_character'
TERMINATOR 'terminator_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'
SKIP_ERRORS [‘errors_num’ ]
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格式中默认是一个逗号。KingbaseES支持设置 不大于8个字节的分隔符。使用binary格式时不允许这个选项。
TERMINATOR指定文本中每行中换行的字符。默认换行符为
\r、\n、\r\n。 KingbaseES支持设置不大于8个字节的分隔符,使用binary格式时不允许这个选项。 KingbaseES兼容Oracle模式支持,而兼容PostgreSQL模式不支持。
NULL指定表示一个空值的字符串。文本格式中默认是
\N(反斜线-N),CSV格式中默认 是一个未加引用的空串。在你不想区分空值和空串的情况下,即使在文本 格式中你也可能更喜欢空串。使用binary格式时不允许这 个选项。注意
在使用
COPY FROM时,任何匹配 这个串的数据项将被存储为空值,因此你应该确定你使用的是和COPY TO时相同的串。
HEADER指定文件包含标题行,其中有每一列的名称。在输出时,第一行包含 来自表的列名。在输入时,第一行会被忽略。只有使用
CSV格式时才允许这个选项。
QUOTE指定一个数据值被引用时使用的引用字符。默认是双引号。 这必须是一个单一的单字节字符。只有使用
CSV格式时才允许这个选项。
ESCAPE指定应该出现在一个匹配
QUOTE值的数据字符之前 的字符。默认和QUOTE值一样(这样如果引用字符 出现在数据中,它会被双写)。这必须是一个单一的单字节字符。 只有使用CSV格式时才允许这个选项。
FORCE_QUOTE强制必须对每个指定列中的所有非
NULL值使用引用。NULL输出不会被引用。如果指定了*, 所有列的非NULL值都将被引用。只有在COPY TO中使用CSV格式时才允许 这个选项。
FORCE_NOT_NULL不要把指定列的值与空值串匹配。在空值串就是空串的默认情况下, 这意味着空串将被读作长度为零的字符串而不是空值(即使它们没有 被引用)。只有在
COPY FROM中使用CSV格式时才允许这个选项。
FORCE_NULL将指定列的值与空值串匹配(即使它已经被加上引号),并且在找到 匹配时将该值设置为
NULL。在空值串就是空串的默认 情况下,这会把一个被引用的空串转换为 NULL。 只有在COPY FROM中使用CSV格式时才允许这个选项。
ENCODING指定文件被以``encoding_name``编码。如果省略 这个选项,将使用当前的客户端编码。详见下文的注解。
SKIP_ERRORS指定copy from中允许跳过最大错误行数``errors_num``。 如果省略这个选项,不允许跳过,出错退出。 如果指定该选项,但不指定``errors_num``,表示一直允许跳过错误行。 如果指定该选项,且指定``errors_num``,超过最大错误行后退出。
WHERE可选的
WHERE子句具有一般形式WHERE condition其中``condition``是计算出类型
boolean的结果的任何表达式。任何不满足此条件的行都不会被插入到表中。当实际的行值被替换为任何变量引用时,如果行返回true,则满足该条件。目前,在
WHERE表达式中不允许使用子查询,并且计算时不会看到由COPY本身所做的任何更改(当表达式包含对VOLATILE函数的调用时,这一点很重要)。
下面的例子使用竖线(
|)作为域定界符把一个表复制到客户端: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语句。下列语法用于KingbaseES V8.2 之前的版本, 并且仍然被支持:
COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | STDIN } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] [ CSV [ HEADER ] [ QUOTE [ AS ] 'quote' ] [ ESCAPE [ AS ] 'escape' ] [ FORCE NOT NULL column_name [, ...] ] ] ] COPY { table_name [ ( column_name [, ...] ) ] | ( query ) } TO { 'filename' | STDOUT } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] [ CSV [ HEADER ] [ QUOTE [ AS ] 'quote' ] [ ESCAPE [ AS ] 'escape' ] [ FORCE QUOTE { column_name [, ...] | * } ] ] ]注意在这种语法中,
BINARY和CSV被视作独立的关键词,而不是FORMAT选项的参数。下列语法用于KingbaseES V7之前的版本, 并且仍然被支持:
COPY [ BINARY ] table_name FROM { 'filename' | STDIN } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ] COPY [ BINARY ] table_name TO { 'filename' | STDOUT } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ]
输出
在成功完成时,一个
COPY命令会返回一个形为COPY count的命令标签。 ``count``是被复制 的行数。
注意
如果命令不是
COPY ... TO STDOUT或者等效的 ksql元命令\copy ... to stdout, ksql将只打印这个命令标签。这是为了防止弄混 命令标签和刚刚打印的数据。注解
COPY命令中提到的文件会被服务器(而不是 客户端应用)直接读取或写入。因此它们必须位于数据库服务器(不是客户 端)的机器上或者是数据库服务器可以访问的。它们必须是 KingbaseES用户(运行服务器的用户 ID)可访问的并且是可读或者可写的。类似地,用PROGRAM指定的命令也会由服务器(不是客户端应用)直接执行,它也必须是 KingbaseES用户可以执行的。 只允许数据库超级用户或者授予了默认角色sys_read_server_files、sys_write_server_files及sys_execute_server_program之一的用户COPY一个文件或者命令, 因为它允许读取或者写入服务器有特权访问的任何文件或者运行服务器有特权访问的程序。不要把
COPY和 ksql指令\copy弄混。\copy会调用COPY FROM STDIN或者COPY TO STDOUT,然后读取/存储一个 ksql客户端可访问的文件中的数据。 因此,在使用\copy时,文件的可访 问性和访问权利取决于客户端而不是服务器。我们推荐在
COPY中使用的文件名总是 指定为一个绝对路径。在COPY TO的 情况下服务器会强制这一点,但是对于COPY FROM你可以选择从一个用相对 路径指定的文件中读取。该路径将根据服务器进程(而不是客户端) 的工作目录(通常是集簇的数据目录)解释。用
PROGRAM执行一个命令可能会受到操作系统 的访问控制机制(如 SELinux)的限制。
COPY FROM将调用目标表上的任何触发器 和检查约束。但是它不会调用规则。对于标识列,
COPY FROM命令将总是写上输入数据中提供的列值,这和INSERT的选项OVERRIDING SYSTEM VALUE的行为一样。
COPY输入和输出受到DateStyle的影响。为了确保到其他 可能使用非默认DateStyle设置的 KingbaseES安装的可移植性,在使用COPY TO前应该把DateStyle设置为ISO。避免转储把IntervalStyle设置为sql_standard的数据也是一个好主意,因为负的区间值可能会 被具有不同IntervalStyle设置的服务器解释错误。即使数据会被服务器直接从一个文件读取或者写入一个文件而不通过 客户端,输入数据也会被根据
ENCODING选项或者当前 客户端编码解释,并且输出数据会被根据ENCODING或 者当前客户端编码进行编码。
COPY会在第一个错误处停止操作。这在COPY TO的情况下不会导致问题,但是 在COPY FROM中目标表将已经收到了一 些行。这些行将不会变得可见或者可访问,但是它们仍然占据磁盘空间。 如果在一次大型的复制操作中出现错误,这可能浪费相当可观的磁盘空间。 你可能希望调用VACUUM来恢复被浪费的 空间。
FORCE_NULL和FORCE_NOT_NULL可以被同时 用在同一列上。这会导致把已被引用的空值串转换为空值并且把未引用的空值 串转换为空串。KingbaseES支持导入和导出数据中包含0x00字节的场景,受guc变量
ignore_char_null_check控制, 当变量打开时,将支持此特性,变量默认值为关闭状态。 在从文件等方式导入包含有0x00字节的数据时,需要使用二进制编辑工具保证输入的数据是二进制0x00字节, 而不是"0x00"字符串。 导出数据时,KingbaseES也会将数据中的0x00字节使用二进制方式导出到目标输出端。在显示0x00字节时, 不同的终端可能有不同的显示风格。在以文本格式导入数据时,KingbaseES总是尝试将"\0"开始的字符串,转换为八进制数据,转换时会尝试 读取"\0"后面的两个0-7的数字字符,比如当读到"\040"时,会转为空格(0x20字节)。 如果想在文本方式导入时,使用"\0"表示0x00字节,避免使用二进制工具编辑0x00字节, KingbaseES提供了guc变量
ignore_char_converter来控制, 当此变量设置为打开状态时,遇到"\0"将不会尝试八进制转换,而认为是0x00字节,此变量默认值为关闭状态。文件格式
文本格式
在使用
text格式时,读取或写入的是一个文本文件, 其中每一行就是表中的一行。一行中的列被定界字符分隔。列值 本身是由输出函数产生的或者是可被输入函数接受的属于每个属性 数据类型的字符串。在为空值的列的位置使用指定的空值串。如果 输入文件的任何行包含比预期更多或者更少的列,COPY FROM将会抛出一个错误。数据的结束可以表示为一个只包含反斜线-点号(
\.)的 单一行。从一个文件读取时,数据结束标记并不是必要的,因为文件 结束符就已经足够用了。只有使用 3.0 客户端协议之前的客户端应用 复制数据时才需要它。反斜线字符(
\)可以被用在COPY数据中来引用被用作行或者列定界符的 字符。特别地,如果下列字符作为一个列值的一部分出现,它们 必须被前置一个反斜线:反斜线本身、新行、回车以及 当前的定界符字符。
COPY TO会不加任何反斜线返回指定的空值串。 相反,COPY FROM会在移除反斜线之前把输入 与空值串相匹配。因此,一个空值串(例如\N)不会与实 际的数据值\N(它会被表示为\\N)搞混。
COPY FROM识别下列特殊的反斜线序列:
序列
表示
\b退格 (ASCII 8)
\f换页 (ASCII 12)
\n新行 (ASCII 10)
\r回车 (ASCII 13)
\t制表 (ASCII 9)
\v纵向制表 (ASCII 11)
\``digits``反斜线 后跟一到三个十进制位表示该数字代码对应的字符
\x``digits``反斜线加
x后 跟一到三个十六进制位表示该数字代码对应的字符当前,
COPY TO不会发出一个十进制或十六进制位 反斜线序列,但是它确实把上面列出的其他序列用于那些控制字符。任何上述表格中没有提到的其他反斜线字符将被当作表示其本身。不过,要注意 增加不必要的反斜线,因为那可能意外地产生一个匹配数据结束标记(
\.)或者空值串(默认是\N)的字符串。这些字符串 将在完成任何其他反斜线处理之前被识别。强烈建议产生
COPY数据的应用把数据新行和回车分别 转换为\n和\r序列。当前可以把一个数据回车表示为 一个反斜线和回车,把一个数据新行表示为一个反斜线和新行。不过,未来的发行 可能不会接受这些表示。如果在不同的机器之间(例如从 Unix 到 Windows) 传输COPY文件,它们也很容易受到破坏。
COPY TO将用一个 Unix 风格的新行( “\n”)终止每一行。运行在 Microsoft Windows 上的服务器则会输出回车/新行(“\r\n”),不过只对COPY到一个服务器文件这样做。为了做到跨平台一致,COPY TO STDOUT总是发送“\n”而 不管服务器平台是什么。COPY FROM能够处理以 新行、回车或者回车/新行结尾的行。为了减少由作为数据的未加反斜线的新行 或者回车带来的风险,如果输出中的行结束并不完全相似,COPY FROM将会抱怨。CSV 格式
这种格式选项被用于导入和导出很多其他程序(例如电子表格)使用的逗号 分隔值(
CSV)文件格式。不同于 KingbaseES标准文本格式使用的转义 规则,它产生并且识别一般的 CSV 转义机制。每个记录中的值用
DELIMITER字符分隔。如果值包含 定界符字符、QUOTE字符、NULL字符串、 一个回车或者换行字符,那么整个值会被加上QUOTE字符 作为前缀或者后缀,并且在该值内QUOTE字符或者ESCAPE字符的任何一次出现之前放上转义字符。在输出 指定列中非NULL值时,还可以使用FORCE_QUOTE来强制加上引用。
CSV格式没有标准方式来区分NULL值和空字符串。 KingbaseES的COPY用引用来处理 这种区分工作。NULL被按照NULL参数字符串输出 并且不会被引用,而匹配NULL参数字符串的非NULL值会被加上引用。例如,使用默认设置时,NULL被写作一个未 被引用的空字符串,而一个空字符串数据值会被写成带双引号("")。 值的读取遵循类似的规则。你可以用FORCE_NOT_NULL来防止 对指定列的NULL输入比较。你还可以使用FORCE_NULL把带引用的空值字符串数据值转换成NULL。因为反斜线在
CSV格式中不是一种特殊字符,数据结束标记\.也可以作为一个数据值出现。为了避免任何解释误会,在 一行上作为孤项出现的\.数据值输出时会自动被引用,并且 输入时如果被引用,则不会被解释为数据结束标记。如果正在载入一个由 另一个应用创建的文件并且其中具有一个未被引用的列且可能具有\.值,你可能需要在输入文件中引用该值。注意
CSV格式中,所有字符都是有意义的。一个被空白或者其他 非DELIMITER字符围绕的引用值将包括那些字符。在导入 来自用空白填充CSV行到固定长度的系统的数据时,这可能 会导致错误。如果出现这种情况,在导入数据到 KingbaseES之前,你可能需要预处理该CSV文件以移除拖尾的空白。注意
CSV 格式将识别并且产生带有包含嵌入的回车和换行的引用值的 CSV 文件。因此文件并不限于文本格式文件的每个表行一行的形式。
注意
很多程序会产生奇怪的甚至偶尔是不合常理的 CSV 文件,因此该文件 格式更像是一种习惯而不是标准。因此你可能会碰到一些无法使用这种 机制导入的文件,并且
COPY也可能产生其他程序无 法处理的文件。二进制格式
binary格式选项导致所有数据被以二进制格式 而不是文本格式存储/读取。它比文本和CSV格式要 快一些,但是二进制格式文件在不同的机器架构和 KingbaseES版本之间的可移 植性要差些。还有,二进制格式与数据格式非常相关。例如不能从 一个smallint列中输出二进制数据并且把它读入到一个integer列中,虽然这样做在文本格式中是可行的。
binary人间格式由一个文件头、零个或者更多个包含 行数据的元组以及一个文件尾构成。头部和数据都以网络字节序表示。
文件头
文件头由 15 字节的固定域构成,后面跟着一个变长的头部扩展区。 固定域有:
签名
11-字节的序列
KBCOPY\n\377\r\n\0— 注意 零字节是签名的一个必要的部分(该签名是为了能容易地发现文件被 无法正确处理 8 位字符编码的传输所破坏。这个签名将被行尾翻译过 滤器、删除零字节、删除高位或者奇偶修改等改变)。标志域
32-位整数位掩码,用以表示该文件格式的重要方面。位被编号为 从 0 (LSB)到 31(MSB)。 注意这个域以网络字节序存放(最高有效位在前),所有该文件格式 中使用的整数域都是这样。16-31 位被保留用来表示严重的文件格式 问题, 读取者如果在这个范围内发现预期之外的被设置位,它应该 中止。0-15位被保留用来表示向后兼容的格式问题,读取者应该简单 地略过这个范围内任何预期之外的被设置位。当前只定义了一个标志 位,其他位必须为零:
位 16
如果为 1,表示数据中包含 OID;如果为 0,则不包含 在KingbaseES中不再支持Oid系统列,但是格式仍然包含指示器。
头部扩展区长度
32-为整数,表示头部剩余部分的以字节计的长度,不包括其本身。 当前,这个长度为零,并且其后就紧跟着第一个元组。未来对该 格式的更改可能会允许在头部中表示额外的数据。如果读取者不知 道要对头部扩展区数据做什么,可以安静地跳过它。
头部扩展区域被预期包含一个能自我解释的块的序列。 该标志域并不想告诉读取者扩展数据是什么。详细的 头部扩展内容的设计留给后来的发行去做。
这种设计允许向后兼容的头部增加(增加头部扩展块或者设置低位标志位)以及 非向后兼容的更改(设置高位标志位来表示这类更改并且在需要时向扩展区域 中增加支持数据)。
元组
每一个元组由一个表示元组中域数量的 16 位整数计数开始(当前,一个表中 的所有元组都应该具有相同的计数,但是这可能不会总是为真)。然后是元组 中的每一个域,它是一个 32 位的长度字,后面则跟随着这么多个字节的域数 据(长度字不包括其本身,并且可以是零)。作为一种特殊情况,-1 表示一个 NULL 域值。在 NULL 情况下,后面不会跟随值字节。
在域之间没有对齐填充或者任何其他额外的数据。
当前,一个二进制格式文件中的所有数据值都被假设为二进制格式(格式代码一)。 可以预见未来的扩展可能会增加一个允许独立指定各列的格式代码的头部域。
要为实际的元组数据决定合适的二进制格式,你应该参考 KingbaseES源码,特别是用于各列 数据类型的
*send和*recv函数(通常可 以在源码的src/backend/utils/adt/目录中找到 这些函数)。如果文件中包含 OID,OID 域会紧跟在域计数字之后。它是一个普通域, 不过它没有被包含在域计数中。注意,oid系统列在当前版本的KingbaseES中不受支持。
文件尾
文件位由一个包含 -1 的 16 位整数字组成。这很容易与一个元组的域计数字区分开。
如果一个域计数字不是 -1 也不是期望的列数,读取者应该报告错误。这提供了一种针对某种数据不同步的额外检查。
14.4. CREATE ACCESS METHOD
CREATE ACCESS METHOD创建一种新的访问方法。访问方法名称在数据库中必须唯一。
只有超级用户可以定义新的访问方法。
CREATE ACCESS METHOD name
TYPE access_method_type
HANDLER handler_function
name要创建的访问方法的名称。
access_method_type这个子句指定要定义的访问方法的类型。当前只支持
TABLE和INDEX。
handler_function``handler_function``是一个之前已注册的 函数的名称(可能被模式限定),该函数表示要创建的访问方法。处理器函数必须被声明为接收 一个单一的
internal类型的参数,并且它的返回类型取决于访问方法的类型: 对于TABLE访问方法,它必须是table_am_handler;INDEX访问方法,必须是index_am_handler;处理器函数 必须实现的 C 级别 API 取决于访问方法的类型。
用处理器函数
heptree_handler创建一种索引访问方法heptree:CREATE ACCESS METHOD heptree TYPE INDEX HANDLER heptree_handler;
CREATE ACCESS METHOD是一种KingbaseES扩展。
参见 DROP ACCESS METHOD , CREATE OPERATOR CLASS , CREATE OPERATOR FAMILY
14.5. CREATE AGGREGATE
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-valueKingbaseES创建一个数据类型 ``stype``的临时变量来 保持聚集的当前内部状态。对每一个输入行,聚集参数值会被计算并且状态 转移函数会被调用,它用当前状态值和新参数值计算一个新的内部状态值。 等所有行都被处理完后,最终函数会被调用一次来计算该聚集的返回值。如果 没有最终函数,则最终的状态值会被返回。
一个聚集函数可以提供一个初始条件,即一个用于内部状态值的初始值。它被 作为一个类型
text的值指定并且存储在数据库中,但是它必须 是状态值数据类型的一个常量的合法外部表示。如果没有提供,则状态值从空值 开始。如果状态转移函数被声明为“strict”,那么不能用空值输入来 调用它。如果有这种转移函数,聚集将按照下面的行为执行。带有任何空值的 行会被忽略(函数不被调用并且之前的状态值被保持)。如果初始状态值就是 空值,那么碰到第一个没有空值的行时,状态值会被替换成第一个参数值,并且 对于每一个后续的没有空值的行都会调用该转移函数。这对实现
max这样的聚集很方便。注意只有当 ``state_data_type`` 和第一个 ``arg_data_type``相同时, 这种行为才可用。当这些类型不同时,你必须提供一个非空初始条件或者使用 一个非严格转移函数。如果状态转移函数不是严格的,那么在碰到每个输入行时都将会调用它,并且 它必须自行处理空值输入和空状态值。这允许聚集的作者完全控制该聚集如何 处理空值。
如果最终函数被声明为“strict”,那么当最终状态值为空时将 不会调用它,而是自动地返回一个空结果(当然,这只是严格函数的普通行为)。 在任何情况下最终函数都可以返回一个空值。例如,
avg的最终函数会在看到零个 输入行时返回空。有时候把最终函数声明成不仅采用状态值还采用对应于聚集输入值的额外参数 是有用的。这样做的主要原因是,如果最终函数是多态的,那么状态值的数据 类型将不适合于用来确定结果类型。这些额外的参数总是以 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-树索引操作符类的“小于”或者“大于” 策略成员,优化将永远不会产生实际效果。
要能够创建一个聚集函数,你必须具有参数类型、状态类型和返回类型上的
USAGE特权,还有在支持函数上的EXECUTE特权。
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 ]
)
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``的默认估计值。规划器 使用这个值来估计一个分组聚集查询所需的内存。只有估计哈希表能够放在 work_mem 大小的内存中时,规划器才会对这类查询 使用哈希聚集。因此,对这个参数设置大的值会阻止使用哈希聚集。
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`` 值。这个函数可以有选择性地被标记为“strict”。在被标记的情况下, 当任何一个输入状态为空时,将不会调用该函数,而是把另一个状态当作正确的结果。
对于``state_data_type``为
internal的聚集函数, ``combinefunc``不能为 strict。这种情况下, ``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的参数可以用任意顺序书写,而无需遵照以上说明的顺序。
见 用户定义的聚集 。
CREATE AGGREGATE是一种 KingbaseES的语言扩展。SQL标准没有提供 用户定义的聚集函数。
在指定支持函数名的参数中,如果需要你可以写一个模式名,例如
SFUNC = public.sum。在这里不能写参数类型 — 支持函数 的参数类型是根据其他参数决定的。通常,KingbaseES函数应该是不修改输入值的真函数。但是,当在聚合上下文中使用聚合转换函数时,允许对其转换状态参数进行欺骗和修改。与每次复制转换状态相比,这可以提供大量的性能优势。
同样地,虽然聚合最终函数通常不希望修改其输入值,但有时避免修改转换状态参数是不切实际的。必须使用
FINALFUNC_MODIFY参数声明这种行为。READ_WRITE值表示最后一个函数以未指定的方式修改转换状态。此值防止将聚合用作窗口函数,也防止将共享相同输入值和转换函数的聚合调用的转换状态合并。SHAREABLE值表示在最后一个函数之后不能应用转换函数,但是可以对结束的转换状态值执行多个最终函数调用。此值阻止将聚合用作窗口函数,但允许合并转换状态。(也就是说,这里的优化不是重复地应用相同的最终函数,而是对相同的结束过渡状态值应用不同的最终函数。这是允许的,只要最后一个函数没有被标记为READ_WRITE。)如果一个聚集支持移动聚集模式,当该聚集被用于一个具有移动帧起点(即帧起点 模式不是
UNBOUNDED PRECEDING)的窗口函数时,它将提升计 算效率。在概念上,当从底部进入窗口帧时前向转移函数会把输入值加到聚集的状 态上,而逆向转移函数会在从顶部离开帧时再次移除输入值。因此,当值被移除时, 它们总是按照被加入的相同顺序被移除。无论何时调用逆向转移函数,它都将因此 接收最近增加但是还未被移除的参数值。逆向转移函数可以假定在它移除最旧的行 之后至少有一行保留在当前状态中(当情况不是这样时,窗口函数机制会简单地开 始一次新的聚集,而不是使用逆向转移函数)。用于移动聚集模式的前向转移函数不允许返回 NULL 作为新的状态值。如果逆向 转移函数返回 NULL,这表明逆向函数无法为这个特定的输入逆转状态计算,并且 该聚集计算因此必须从当前帧的开始位置“从零开始”重新被计算。在一些少见的情 况中,逆转正在计算中的状态值是不切实际的,这种习惯可以允许在此类情形中使用 移动聚集模式。
如果没有提供移动聚集实现,聚集仍然可以被用于移动帧,但是 只要帧起点移动,KingbaseES都将会重新计算 整个聚集。注意不管聚集有没有支持移动聚集模式, KingbaseES都能处理一个移动帧结束而无需重 新计算,这可以通过增加新值到聚集状态完成。 这就是为什么使用聚合作为窗口函数要求最后的函数是只读的:它不会破坏聚集的状 态值,这样即使已经为一组帧边界得到了一个聚集结果值,该聚集也能继续下去。
有序集聚集的语法允许为最后一个直接参数以及最后一个聚集(
WITHIN GROUP)参数指定VARIADIC。但是,当前的 实现限制只能以两种方式使用VARIADIC。第一种,有续集聚集只能 使用VARIADIC "any",不能使用其他可变数组类型。第二种,如果最 后一个直接参数是VARIADIC "any",那么只能有一个聚集参数并且它 也必须是VARIADIC "any"(在系统目录中使用的表示中,这两个参数 会被合并为一个单一的VARIADIC "any"项,因为sys_proc无法表示具有超过一个VARIADIC参数的 函数)。如果该聚集是一个假想集聚集,匹配VARIADIC "any"参数的 直接参数就是假想参数。任何在前面的参数表示额外的直接参数,它们不被约束为需 要匹配聚集参数。当前,有序集聚集无须支持移动聚集模式,因为它们不能被用作窗口函数。
部分(包括并行)聚集当前不被有续集聚集支持。还有,包括
DISTINCT或者ORDER BY子句的聚集调用将不会使用 部分聚集,因为在部分聚集时无法支持那些语义。
14.6. CREATE CAST
CREATE CAST定义一种新的造型。 一种造型指定如何在两种数据类型之间执行转换。例如,SELECT CAST(42 AS float8);通过调用一个之前指定的函数(这种情况中是
float8(int4))把整型常量 42 转换成类型float8(如果没有定义合适的造型, 该转换会失败)。两种类型可以是二进制可强制,这表示该转换 可以被“免费”执行而不用调用任何函数。这要求相应的 值使用同样的内部表示。例如,类型
text和varchar在双向都是二进制可强制的。二进制可强制性并 不必是一种对称关系。例如,在当前实现中从xml到text的造型可以被免费执行,但是反向则需要一个函数来 执行至少一次语法检查(两种在双向都二进制值兼容的类型也被称作二进 制兼容)。通过使用
WITH INOUT语法,你可以把一种造型定义 成I/O 转换造型。一种 I/O 转换造型执行时,会调用源 数据类型的输出函数,并且把结果字符串传递给目标数据类型的输入函数。 在很多常见情况中,这种特性避免了为转换单独定义一个造型函数。一种 I/O 转换造型表现得和一个常规的基于函数的造型相同,只是实现不同而已。默认情况下,只有一次显式造型请求才会调用造型, 形式是
CAST(xAS ``typename``) or ``x``::``typename``。如果造型被标记为
AS ASSIGNMENT,那么在为一个目标数据 类型的列赋值时会隐式地调用它。例如,假设foo.f1是 一个类型text