跳到主要内容

CREATE ACCESS METHOD 到 CREATE MATERIALIZED VIEW

命令数:16 条。

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_handler创建一种索引访问方法heptree:

CREATE ACCESS METHOD heptree TYPE INDEX HANDLER heptree_handler;

另见

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 ]
[ , 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 ]
[ , HYPOTHETICAL ]
[ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
)

或者旧的语法

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

创建一个数据类型 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和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特权。

参数

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表示它不会修改;其他两个值表示它可能会更改迁移状态值。请参见Notes 以获取更多详细信息。除了有序集合的聚合使用默认值READ_WRITE,其他默认值均为READ_ONLY。

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的参数可以用任意顺序书写,而无需遵照以上说明的顺序。

注解

在指定支持函数名的参数中,如果需要你可以写一个模式名,例如 SFUNC = public.sum。在这里不能写参数类型 --- 支持函数的参数类型是根据其他参数决定的。

通常,函数是不要修改输入值的真函数。然而,一个聚合迁移函数在聚合上下文中使用时被允许诈欺并修改已在迁移状态的参数。因为与每次创建一个迁移状态的新的拷贝相比,这样可以提供实质的性能提升。

同样,虽然人们一般不期望聚合最终函数修改它的输入值,但有时回避修改迁移态参数是不切实际的。这种行为必须使用FINALFUNC_MODIFY参数声明。READ_WRITE值表示最终函数以某种未指定的方式修改了迁移状态值。这个值防止将聚合用作窗口函数,并且还可以防止因共用相同的输入值和迁移函数的聚合调用而合并迁移状态。SHAREABLE值表示过渡函数不能在最终功能之后使用用,但多重最终函数调用可以对最终的迁移状态值执行调用。这个值阻止将聚合用作窗口函数,但允许合并过渡状态。(也就是说,此处所关注的优化不是重复地使用相同的最终函数,而是把不同的最终函数应用到相同的最终迁移状态值。只要所有最终功能都没有标记为READ_WRITE就被允许。)

如果一个聚集支持移动聚集模式,当该聚集被用于一个具有移动帧起点(即帧起点模式不是UNBOUNDED PRECEDING)的窗口函数时,它将提升计 算效率。在概念上,当从底部进入窗口帧时前向转移函数会把输入值加到聚集的状态上,而逆向转移函数会在从顶部离开帧时再次移除输入值。因此,当值被移除时,它们总是按照被加入的相同顺序被移除。无论何时调用逆向转移函数,它都将因此接收最近增加但是还未被移除的参数值。逆向转移函数可以假定在它移除最旧的行之后至少有一行保留在当前状态中(当情况不是这样时,窗口函数机制会简单地开始一次新的聚集,而不是使用逆向转移函数)。

用于移动聚集模式的前向转移函数不允许返回 NULL 作为新的状态值。如果逆向转移函数返回NULL,这表明逆向函数无法为这个特定的输入逆转状态计算,并且该聚集计算因此必须从当前帧的开始位置"从零开始"重新被计算。在一些少见的情况中,逆转正在计算中的状态值是不切实际的,这种习惯可以允许在此类情形中使用移动聚集模式。

如果没有提供移动聚集实现,聚集仍然可以被用于移动帧,但是只要帧起点移动,系统都将会重新计算整个聚集。注意不管聚集有没有支持移动聚集模式,系统都能处理一个移动帧结束而无需重新计算,这可以通过增加新值到聚集状态完成。这就是为什么使用聚合作为窗口函数需要最终函数只读的原因。人们认为最终函数不能破坏聚集的状态值,这样即使已经为一组帧边界得到了一个聚集结果值,该聚集也能继续下去。

有序集聚集的语法允许为最后一个直接参数以及最后一个聚集(WITHIN GROUP)参数指定VARIADIC。但是,当前的实现限制只能以两种方式使用VARIADIC。第一种,有续集聚集只能使用VARIADIC "any",不能使用其他可变数组类型。第二种,如果最后一个直接参数是VARIADIC "any",那么只能有一个聚集参数并且它 也必须是VARIADIC "any"(在系统目录中使用的表示中,这两个参数会被合并为一个单一的VARIADIC "any"项,因为 pg_proc无法表示具有超过一个VARIADIC参数的函数)。如果该聚集是一个假想集聚集,匹配VARIADIC "any"参数的直接参数就是假想参数。任何在前面的参数表示额外的直接参数,它们不被约束为需要匹配聚集参数。

当前,有序集聚集无须支持移动聚集模式,因为它们不能被用作窗口函数。

部分(包括并行)聚集当前不被有续集聚集支持。还有,包括 DISTINCT或者ORDER BY子句的聚集调用将不会使用部分聚集,因为在部分聚集时无法支持那些语义。

另见

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 转换造型执行时,会调用源数据类型的输出函数,并且把结果字符串传递给目标数据类型的输入函数。

在很多常见情况中,这种特性避免了为转换单独定义一个造型函数。一种 I/O 转换造型表现得和一个常规的基于函数的造型相同,只是实现不同而已。

默认情况下,只有一次显式造型请求才会调用造型,形式是CAST(x AS typename) or x::typename。

如果造型被标记为AS ASSIGNMENT,那么在为一个目标数据类型的列赋值时会隐式地调用它。例如,假设foo.f1是 一个类型text的列,那么如果从类型integer 到类型text的造型被标记为AS ASSIGNMENT,则:

INSERT INTO foo (f1) VALUES (42);

将被允许,否则不会允许(我们通常使用赋值造型来描述此类造型)。

如果造型被标记为AS IMPLICIT,那么可以在任何上下文中隐式地调用它,无论是赋值还是在一个表达式内部(我们通常用术语隐式造型来描述这类造型)。例如,考虑这个查询:

SELECT 2 + 4.0;

解析器初始会把常量分别标记为类型integer和numeric。在系统目录中没有integer + numeric操作符,但是有一个numeric + numeric操作符。 因此,如果有一种可用的从integer到 numeric的造型且被标记为AS IMPLICIT --- 实际上确实有 --- 该查询将会成功。

解析器将应用该隐式转换并且解决该查询,就好像它被写成:

SELECT CAST ( 2 AS numeric ) + 4.0;

系统默认支持从numeric到integer的隐式转换。如果类型转换被标记为AS IMPLICIT --- 实际上并没有 --- 那么解析器将面临选择:是用前面介绍的过程,还是把numeric常量造型成integer并且应用integer + integer操作符。由于缺少哪种选择更好的判断,解析器会放弃并且说明查询有歧义。

对隐式转换持保守态度是明智的。过多的隐式转换可能导致系统以莫名其妙的方式解释命令,或者由于有多种可能解释而根本无法解析命令。一种好的实践是让一种类型转换只对于同一种类型分类中的类型间的信息保持转换隐式可调用。例如,

从int2到int4的造型 可以被合理地标记为隐式,但是从float8到 int4的造型可能应该只能在赋值时使用。

注意:有时为了可用性或者标准兼容的原因,有必要提供在一个类型集合之间 的多种隐式造型,这会导致上述不可避免的歧义。解析器还有一招基于类型分类和优先类型的后手,它能帮助 提供这类情况下预期的行为。详见 CREATE TYPE。

要创建一种造型,你必须拥有源数据类型和目标数据类型并且具有在其他类型上 的USAGE特权。要创建一种二进制可强制造型,你必须是一个超级用户(这种限制是因为错误的二进制可强制造型转换很容易让服务器崩溃)。

参数

source_type

该造型的源数据类型的名称。

target_type

该造型的目标数据类型的名称。

**function_name[(argument_type [, ...])]**

被用于执行该造型的函数。函数名称可以用模式限定。如果没有被限定,将在模式搜索路径中查找该函数。函数的结果数据类型必须是该造型的目标数据类型。它的参数讨论如下。

如果没有指定参数列表,则该函数名称在其模式中必须是唯一的。

WITHOUT FUNCTION

指示源类型可以二进制强制到目标类型,因此执行该造型不需要函数。

WITH INOUT

指示该造型是一种 I/O 转换造型,执行需要调用源数据类型的输出函数, 并且把结果字符串传递给目标数据类型的输入函数。

AS ASSIGNMENT

指示该造型可以在赋值的情况下被隐式调用。

AS IMPLICIT

指示该造型可以在任何上下文中被隐式调用。

造型实现函数可以具有1到3个参数。第一个参数类型必须等于源类型或者能从源类型二进制强制得到。第二个参数(如果存在)必须是类型 integer,它接收与目标类型相关联的类型修饰符,如果没有类型修饰符,它会收到-1。第三个参数(如果存在)必须是类型boolean,如果该造型是一种显式造型,它会收到 true,否则会收到false(奇怪地是,SQL 标准在某些情况中对显式和隐式造型要求不同的行为。这个参数被提供给必须实现这类造型的函数。不推荐在设计自己的数据类型时用它)。

一个造型函数的返回类型必须等于目标类型或者能二进制强制到目标类型。

通常,强制转换必须具有不同的源和目标数据类型。但是,如果它有一个带有多个参数的强制转换实现函数,则可以声明具有相同源类型和目标类型的造型。它用于表示系统目录中特定类型的长度强制函数。命名函数用于将类型的值强制转为其第二个参数提供的类型修饰符的值。

当强制转换具有不同的源类型和目标类型,并且一个函数使用多个参数时,它支持从一种类型转换为另一种类型,并在单个步骤中应用长度强制。如果没有这样的条目,强制转换为使用类型修饰符的类型将涉及两个强制转换步骤,一个是在数据类型之间进行转换,另一个是应用修饰符。

向域类型强制转换或从域类型强制转换当前无效。向域或从域强制转换使用与其基础类型关联的造型。

注解

使用DROP CAST移除用户定义的造型。

记住如果你想要能够双向转换类型,你需要在两个方向上都显式声明造型。

通常没有必要创建用户定义类型和标准字符串类型(text、varchar和char(n),以及被定义在字符串分类中的用户定义类型)之间的造型。系统会为它们提供自动的 I/O 转换造型。到字符串类型的自动造型被当做赋值造型,而字符串类型作为源的自动造型只能是显式的。通过声明你自己的造型来替换自动造型可以覆盖这种行为,但是这样做的唯一原因是你想让该转换比标准的设置更容易被调用。另一种可能的原因是你想让该转换的行为与该类型的 I/O 函数不同,但这种原因足够令人感到意外,你应该考虑再三它是不是个好主意(确实有少量内建类型对转换具有不同的行为,绝大部分是因为 SQL 标准的要求)。

虽然不必要,推荐你继续遵循这种在目标数据类型后面命名造型实现函数的习惯。很多用户习惯于能够使用一种函数风格的记法来造型数据类型,即typename(x)。 这种记法正好是对造型实现函数的调用,这里它没有被作为造型特殊对待。如果你的转换函数没有被指定支持这种习惯,那么你的用户会觉得意外。由于系统允许用不同的参数类型重载同一个函数名,因此存在多个从不同类型到同一目标类型的同名转换函数并不困难。

注意:实际上前一段过于简化了:有两种情况中一个函数调用结构在没有被匹配到 一个实际函数时将被当作一次造型请求。如果函数调用 name(x)没有正好匹配任何现有函数,但name是一种数据类型的名称并且 pg_cast提供了一种从x的类型到这种类型的二进制可强制造型,那么该调用将被翻译为一次二进制可强制造型。通过这种例外,二进制可强制造型能够以函数语法调用,即便没有该函数。同样的,如果没有pg_cast项,但是该造型是要造型到一种字符串类型或者是要从一种字符串类型造型,调用将被翻译成一次 I/O 转换 造型。这种例外允许以函数语法调用 I/O 转换造型。

注意:还有一种例外中的例外:从组合类型到字符串类型的 I/O 转换造型不能使用函数语法调用,而必须被写成显式造型语法(CAST或者 ::记号)。增加这种例外是因为在引入了自动提供的 I/O 转换造型之后,在想要引用一个函数或者列时太容易意外地调用这种造型。

示例

要使用函数int4(bigint)创建一种从类型 bigint到类型int4的赋值造型:

CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;

(在系统中这种造型已经被预定义)。

另见

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。确定性比较认为那些在字节上不相等的字符串是不相等的,即使它们在逻辑上被比较认为相等。系统使用字节比较来断开连接。不确定的比较可能会使排序规则大小写不敏感或音调不敏感。因此,您需要选择一个适当的LC_COLLATE设置并且在此处将排序规则设置为不确定。非确定性排序规则仅被ICU提供者支持。

version

指定使用该排序规则存储的版本字符串。通常忽略该选项,这会导致版本从操作系统提供的排序规则实际版本中计算出来。此选项旨在供pg_upgrade用于复制现有安装中的版本。

又见ALTER COLLATION获取如何处理排序规则版本错误匹配。

existing_collation

要复制的一种现有的排序规则的名称。新的排序规则将和现有的具有同样的属性,但是它是一个独立的对象。

注解

CREATE COLLATION 采用SHARE ROW EXCLUSIVE锁,在pg_collation系统分类上,这是自我冲突的,所以一次只能运行一条CREATE COLLATION 命令。

使用DROP COLLATION可移除用户定义的排序规则。

使用libc排序规则提供程序时,语言环境必须适用于当前的数据库编码。 有关精确的规则,请参见CREATE DATABASE。

示例

从操作系统区域fr_FR.utf8创建一种排序规则(假定当前数据库编码是UTF8):

CREATE COLLATION french (locale = 'fr_FR.utf8');

使用German phone book排序顺序使用ICU提供程序创建排序规则:

CREATE COLLATION german_phonebook (provider = icu, locale = 'de-u-co-phonebk');

从一个现有的排序规则创建一个新的排序规则:

CREATE COLLATION german FROM "de_DE";

能在应用中使用与操作系统无关的排序规则名称就很方便了。

另见

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

cstring, -- 源字符串(空值终止的 C 字符串)

internal, -- 目标(用一个空值终止的 C 字符串填充)

integer -- 源字符串长度

) RETURNS void;

注解

源编码和目标编码都不可以是SQL_ASCII,因为在涉及SQL_ASCII "encoding"的情况下,服务器的行为是硬连接的。

使用DROP CONVERSION可以移除用户定义的转换。

创建转换所要求的特权可能在未来的发行中被更改。

示例

使用myfunc创建一个从编码UTF8到 LATIN1的转换:

CREATE CONVERSION myconv FOR 'UTF8' TO 'LATIN1' FROM myfunc;

另见

ALTER CONVERSION, CREATE FUNCTION, DROP CONVERSION

CREATE DATABASE​

CREATE DATABASE --- 创建一个新数据库

大纲

CREATE DATABASE name
[ [ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ LOCALE [=] locale ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ TABLESPACE [=] tablespace_name ]
[ ALLOW_CONNECTIONS [=] allowconn ]
[ CONNECTION LIMIT [=] connlimit ]
[ IS_TEMPLATE [=] istemplate ] ]

描述

CREATE DATABASE创建一个数据库或者也叫做容器。

要创建一个数据库,你必须是一个超级用户或者具有特殊的CREATEDB特权。见CREATE ROLE。

默认情况下,新数据库将通过克隆标准系统数据库template1被创建。可以通过写TEMPLATE name指定一个不同的模板。特别地,通过写TEMPLATE template0你可以创建一个原始的数据库(其中没有用户定义的对象存在并且系统对象没有被更改),它将只包含标准对象。如果你希望避免拷贝任何可能被加入到template1中的本地安装对象,这将有所帮助。

参数

name

要创建的数据库名。

user_name

将拥有新数据库的用户的角色名,或者用DEFAULT来使用默认值(即,执行该命令的用户)。要创建一个被另一个角色拥有的数据库,你必须是该角色的一个直接或间接成员,或者是一个超级用户。

template

要从其创建新数据库的模板名称,或者用DEFAULT来使用默认模板(template1)。

encoding

要在新数据库中使用的字符集编码。指定一个字符串常量(例如'SQL_ASCII'),或者一个整数编码编号,或者DEFAULT来使用默认的编码(即,模板数据库的编码)。

locale

这是一个同时设置LC_COLLATE和LC_CTYPE的快捷方式。如果指定此参数,您不能指定这些参数中的任何一个。

提示:其他语言环境设置 lc_messages, lc_monetary, lc_numeric, and lc_time不是每个数据库固定的,也不是由该命令设置的。如果要将它们设置为特定数据库的默认值,则可以使用 ALTER DATABASE... SET.

lc_collate

要在新数据库中使用的排序规则顺序(LC_COLLATE)。这会影响应用到字符串的排序顺序,例如在带 ORDER BY 的查询中,以及文本列上索引所使用的顺序。默认是使用模板数据库的排序规则顺序。附加限制见下文。

lc_ctype

要在新数据库中使用的字符分类(LC_CTYPE)。这会影响字符的类别,如小写、大写和数字。默认是使用模板数据库的字符分类。附加限制见下文。

tablespace_name

将与新数据库相关联的表空间名称,或者DEFAULT来使用模板数据库的表空间。这个表空间将是在这个数据库中创建的对象的表空间。详见CREATE TABLESPACE。

allowconn

如果为假,则没有人能连接到这个数据库。默认为真,表示允许连接(除了 被其他机制约束以外,例如GRANT/REVOKE CONNECT)。

connlimit

这个数据库允许多少并发连接。-1 (默认值)表示没有限制。

istemplate

如果为真,则任何具有CREATEDB特权的用户都可以从这个数据库克隆。如果为假(默认),则只有超级用户或者该数据库的拥有者可以克隆它。

可选的参数可以被写成任何顺序,不用按照上面说明的顺序。

注解

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是不会含有任何可能被影响的数据或索引的。

CONNECTION LIMIT选项大概是唯一会被强制的,如果两个新会话在大约同一时间开始并且那时该数据库只剩有一个连接"槽",可能两者都会失败。还有,该限制对超级用户或后台工作进程无效。

例子

要创建一个新数据库:

CREATE DATABASE lusiadas;

要在一个默认表空间salesspace中创建一个被用户salesapp拥有的新数据库sales:

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;

指定的区域设置和编码设置必须匹配,否则会报告错误。

请注意,区域名称是特定于操作系统的,因此上述命令可能无法在任何地方以相同的方式工作。

参见

ALTER DATABASE, DROP DATABASE

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子句为该域数据类型的列指定一个默认值。该值是任何没有变量的表达式(但不允许子查询)。默认值表达式 的数据类型必须匹配域的数据类型。如果没有指定默认值,那么默认值就是空值。

默认值表达式将被用在任何没有指定列值的插入操作中。如果为一个 特定列定义了默认值,它会覆盖与域相关的默认值。继而,域默认值会覆盖任何与底层数据类型相关的默认值。

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

空的标量子-SELECT 将产生一个空值,它被认为是该域类型的值,因此不会 在其上应用任何进一步的约束检查,并且插入将会成功。

要避免这类问题很难,因为 SQL 的一般假设是空值也是每一种数据类型的合法值。 因此,最好的方法是设计一个允许空值的域约束,然后根据需要在该域类型的列上应用列的NOT NULL约束。

系统假定CHECK约束的条件是不可变的,也就是说,对于相同的输入值它们总会给出相同的结果。仅在首次将值转换为域类型时,此假设检查CHECK约束的正确性,而不是在其他时候。

打破此假设的常见方法的一个示例是在 CHECK表达式中引用一个用户定义的函数,然后更改该函数的行为。 系统不会禁止这样做,但是此间如果有域类型的存储值违反CHECK约束,它也不会注意到。这将导致后续数据库转储和重新加载失败。处理此类更改的建议方法是删除约束(使用ALTER DOMAIN),调整函数定义,重新添加约束,然后根据存储的数据

重新检查约束。

示例

这个例子创建us_postal_code数据类型并且把它用在一个表定义中。一个正则表达式测试被用来验证值是否看起来像一个合法的 US 邮政编码:

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

另见

ALTER DOMAIN, DROP DOMAIN

CREATE EVENT TRIGGER​

CREATE EVENT TRIGGER --- 定义一个新的事件触发器

大纲

CREATE EVENT TRIGGER name
ON event
[ WHEN filter_variable IN (filter_value [, ... ]) [ AND ... ] ]
EXECUTE { FUNCTION | PROCEDURE } function_name()

描述

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的语法中,关键字CREATE EVENT TRIGGER和PROCEDURE是等效的,但是被引用的函数在任何情况下都必须是函数,而不是过程。此处关键字PROCEDURE的使用是历史性的,已弃用。

注解

只有超级用户能创建事件触发器。

在单用户模式中事件触发器被禁用。如果一个错误的事件触发器禁用了数据库让你甚至无法删除它,可以重启到单用户模式,这样你就能删除它。

示例

禁止执行任何DDL命令:

CREATE OR REPLACE FUNCTION abort_any_command()
RETURNS event_trigger
LANGUAGE plpgsql
AS \$\$
BEGIN
RAISE EXCEPTION 'command % is disabled', tg_tag;
END;
\$\$;
CREATE EVENT TRIGGER abort_ddl ON ddl_command_start
EXECUTE FUNCTION abort_any_command();

另见

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的用户成为扩展的所有者, 以进行以后的特权检查,并且通常也成为由扩展的脚本创建的任何对象的所有者。

通常,加载扩展需要与创建扩展组件对象所需的特权相同的特权。对于许多扩展,这意味着需要超级用户特权。但是,如果扩展名在其控制文件中标记为trusted,则该扩展名可以由对当前数据库具有CREATE特权的任何用户安装。在这种情况下,扩展对象本身将由主叫用户拥有,但是包含的对象将由引导超级用户拥有(除非扩展的脚本将其明确分配给主叫用户)。此配置使呼叫用户有权删除该扩展名,但不能修改其中的单个对象。

参数

IF NOT EXISTS

已有同名扩展存在时不要抛出错误。这种情况下会发出一个提示。注意,不保证现有的扩展与将要从当前可用的脚本文件创建的脚本有任何相似。

extension_name

要安装的扩展的名称。PostgreSQL 将使用文件 SHAREDIR/extension/ extension_name.control 中的指令来创建该扩展。

schema_name

假定该扩展允许其内容被重定位,这是要在其中安装该扩展的对象的模式名称。被提到的模式必须已经存在。如果没有指定并且该扩展的控制文件也没有指定一个模式,将使用当前的默认对象创建模式。

如果该扩展在其控制文件中指定了一个schema参数,那么不能用SCHEMA子句覆盖该模式。通常,如果 给出了一个SCHEMA子句并且它与扩展的 schema参数冲突,则会发生错误。不过,如果也给出了CASCADE子句,则schema冲突时会忽略 schema_name。给定的schema_name 将被用来安装任何需要的并且没有在其控制文件中指定 schema的扩展。

记住扩展本身被认为不在任何模式中:扩展具有无限定的名称,并且 要在整个数据库范围内唯一。但是属于扩展的对象可以在模式中。

version

要安装的扩展的版本。这可以写成一个标识符或者一个字符串。 默认版本在该扩展的控制文件中指定。

CASCADE

自动安装这个扩展所依赖的任何还未安装的扩展。它们的依赖也会同样被自动安装。如果给出SCHEMA子句,它会应用于这种方式下安装的所有扩展。这个语句的其他选项不会被应用于自动安装的扩展。特别地,这些自动安装的扩展的默认版本将被选中。

注解

在使用CREATE EXTENSION载入扩展到数据库中之前,必须先安装好该扩展的支持文件。

当前可以用于载入的扩展可以在系统视图 pg_available_extensions 或者pg_available_extension_versions 中看到。

示例

安装hstore扩展到当前数据库中,将其对象放置在 addons模式中:

CREATE EXTENSION hstore SCHEMA addons;

另一种方法:

SET search_path = addons;
CREATE EXTENSION hstore;

另见

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' [, ... ] )**

这个子句为新的外部数据包装器指定选项。允许的选项名称和值与每一个 外部数据包装器有关,并且它们会被该外部数据包装器的验证器函数验证。 选项名称必须唯一。

示例

创建一个无用的外部数据包装器dummy:

CREATE FOREIGN DATA WRAPPER dummy;

用处理器函数file_fdw_handler创建一个外部数据包装器 file:

CREATE FOREIGN DATA WRAPPER file HANDLER file_fdw_handler;

用一些选项创建一个外部数据包装器mywrapper:

CREATE FOREIGN DATA WRAPPER mywrapper
OPTIONS (debug 'true');

另见

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 }
[, ... ]
) ] partition_bound_spec
SERVER server_name
[ OPTIONS ( option 'value' [, ... ] ) ]

其中 column_constraint 是:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
CHECK ( expression ) [ NO INHERIT ] |
DEFAULT default_expr |
GENERATED ALWAYS AS ( generation_expr ) STORED }

而 table_constraint 是:

[ CONSTRAINT constraint_name ]
CHECK ( expression ) [ NO INHERIT ]

描述

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 VALUES partition_bound_spec

此语句可以用来将外部表创建为父表的一个指定区间的分区表。详见CREATE TABLE的类似形式。注意如果父表存在UNIQUE类型的索引时,当前是不允许将外部表创建为该父表的分区表。(另见 ALTER TABLE ATTACH PARTITION。)

CONSTRAINT constraint_name

一个可选的用于列或者表约束的名字。如果该约束被违背,这个约束名字会 出现在错误消息中,这样col must be positive这种约束名就可以被用来与客户端应用交流有用的约束信息(指定包含空格的约束名需要 使用双引号)。如果没有指定约束名,系统会自动生成一个。

NOT NULL

该列不允许包含空值。

NULL

该列可以包含空值,这是默认值。

提供这个子句只是为了兼容非标准的 SQL 数据库。在新的应用中不鼓励使用它。

**CHECK ( expression ) [ NO INHERIT ]**

CHECK子句指定一个产生布尔结果的表达式,该外部表中的每一行都应该满足该表达式。也就是说,对于该外部表中所有的行,这个表达式应该产生 TRUE 或者 UNKNOWN 而不能产生 FALSE。被作为列约束指定的检查约束应该只引用该列的值,而出现在表约束中的表达式可以引用多列。

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

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

DEFAULT default_expr

DEFAULT子句为包含它的列定义赋予一个默认数据值。该值是任意不包含变量的表达式(不允许子查询和对当前表中其他列的交叉引用)。默认值表达式的数据类型必须匹配列的数据类型。

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

GENERATED ALWAYS AS ( generation_expr ) STORED

该子句创建一个生成列。 此列不能写入,只能在读取时返回所指定的表达式的值。

关键字STORED是必须的,用来表明该列将在写入时计算。(计算出的值将会传递给外部数据封装器负责保存,并在读取时返回。)

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

server_name

要用于该外部表的一个现有外部服务器的名称。有关定义一个服务器的细节可以参考CREATE SERVER。

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

要与新外部表或者它的一个列相关联的选项。被允许的选项名称和值是与 每一个外部数据包装器相关的,并且它们会被该外部数据包装器的验证器 函数验证。不允许重复的选项名称(不过一个表选项和一个列选项重名是可以的)。

注解

系统不会强制外部表上的约束(例如CHECK或NOT NULL子句),大部分外部数据包装器也不会尝试强制它们。也就是说,这类约束会被简单地认为保持为真。这种强制其实没什么意义,因为它只适用于通过该外部表插入或者更新的行,而对通过其他方式修改的行(例如直接在远程服务器上修改)没有作用。附着在外部表上的约束应该表示由外部服务器强制的一个约束。有些特殊目的的外部数据包装器可能是它们所访问的数据的唯一一种访问机制,在那种情况下让外部数据包装器自己来执行约束强制可能是合适的。但是不应该假设包装器会这样做,除非它的文档说它会。

尽管系统会尝试强制外部表上的约束,但它确实假定它们对于查询优化的目的是正确的。如果在外部表中有不满足约束的行可见,在该表上的查询可能会产生不正确的回答。确保约束定义符合实际是用户的责任。

类似的要点也适用于生成列。生成列在本地服务器发生插入或更新时进行计算,并将计算结果传递给外部数据封装器,由外部数据封装器负责把结果写到外部数据存储中,但是并不强制要求查询外部表时返回的生成列的值一定是与生成表达式一致。总而言之,此行为可能导致查询到不正确的结果。

虽然列可以从本地分区移到外部表分区(使用的外部数据封装器支持元组路由),但是不能将列从外部表分区移动到本地分区。

示例

创建外部表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_y2016m07,通过服务器 server_07访问它,作为范围分区表measurement 的分区:

CREATE FOREIGN TABLE measurement_y2016m07
PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01')
SERVER server_07;

另见

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 'definition'
| AS 'obj_file', 'link_symbol'
} ...

描述

CREATE FUNCTION定义一个新函数。CREATE OR REPLACE FUNCTION将创建一个新函数或者替换一个现有的函数。要定义一个函数,用户必须具有该语言上的USAGE特权。

如果包括了一个模式名,那么该函数会被创建在指定的模式中。否则,它会被创建在当前模式中。新函数的名称不能匹配同一个模式中具有相同输入参数类型的任何现有函数或过程。

不过,不同参数类型的函数和过程能够共享一个名字(这被称作重载)。

要替换一个现有函数的当前定义,可以使用CREATE OR REPLACE FUNCTION。但不能用这种方式更改函数的名称或者参数类型(如果尝试这样做,实际上就会创建一个新的不同的函数)。还有,CREATE OR REPLACE FUNCTION将不会让你更改一个现有函数的返回类型。要这样做,你必须先删除再重建该函数(在使用OUT参数时,这意味着除了删除函数之外无法更改任何OUT参数的类型)。

当CREATE OR REPLACE FUNCTION被用来替换一个现有的函数,该函数的拥有权和权限不会改变。所有其他的函数属性会按照该命令中所指定的或者隐含的来赋值。必须拥有(包括成为拥有角色的成员)该函数才能替换它。

如果你删除并且重建一个函数,新函数将和旧的不一样,你将必须删掉引用旧函数的现有规则、视图、触发器等。使用CREATE OR REPLACE FUNCTION更改一个函数定义不会破坏引用该函数的对象。还有,ALTER FUNCTION可以被用来更改一个现有函数的大部分辅助属性。

创建该函数的用户将成为该函数的拥有者。

要创建一个函数,你必须拥有参数类型和返回类型上的USAGE特权。

参数

name

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

argmode

一个参数的模式:IN、OUT、INOUT或者VARIADIC。如果省略,默认为IN。只有OUT参数能跟在一个VARIADIC参数后面。还有,OUT和INOUT参数不能和RETURNS TABLE符号一起使用。

argname

一个参数的名称。一些语言(包括 SQL 和 PL/pgSQL)让你在函数体中使用该名称。对于其他语言,一个输入参数的名字只是额外的文字(就该函数本身所关心的来说)。在任何情况下,输出参数的名称是有意义的,因为它定义了结果行类型中的列名(如果忽略一个输出参数的名称,系统将选择一个默认的列名)。

argtype

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

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

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

default_expr

如果参数没有被指定值时要用作默认值的表达式。该表达式必须能被强制为该参数的参数类型。只有输入(包括INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默认值。

rettype

返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一个表列的类型。根据实现语言,也可以允许指定cstring之类的"伪类型"。如果该函数不会返回一个值,可以指定返回类型为void。

当有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或者一个用户定义的过程语言的名称,例如plpgsql。不推荐用单引号包围该名称,并且要求区分大小写。

**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选项创建的视图或者开启了行级安全性的表上执行查询。对于包含有非防泄漏函数的查询,系统将在任何来自查询本身的用户提供条件之前强制来自安全策略或者安全屏障的条件,防止无意中的数据暴露。被标记为防泄漏的函数和操作符被假定是可信的,并且可以在安全性策略和安全性屏障视图的条件之前被执行。此外,没有参数的函数或者不从安全屏障视图或表传递任何参数的函数不一定要被标记为防泄漏的。这个选项只能由超级用户设置。

CALLED ON NULL INPUT

RETURNS NULL ON NULL INPUT

STRICT

CALLED ON NULL INPUT(默认)表示在某些参数为空值时应正常调用该函数。如果有必要,函数的作者应该负责检查空值并且做出适当的相应。

RETURNS NULL ON NULL INPUT或STRICT表示只要其任意参数为空值,该函数就会返回空值。如果指定了这个参数,当有空值参数时该函数不会被执行,而是自动返回一个空值结果。

**[EXTERNAL] SECURITY INVOKER**
**[EXTERNAL] SECURITY DEFINER**

SECURITY INVOKER表示要用调用该函数的用户的特权来执行它。这是默认值。SECURITY DEFINER指定要用拥有该函数的用户的特权来执行该函数。

为了符合 SQL,允许使用关键词EXTERNAL。但是它是可选的,因为与 SQL 中不同,这个特性适用于所有函数而不仅是那些外部函数。

PARALLEL

PARALLEL UNSAFE表示该函数不能在并行模式中运行并且 SQL 语句中存在一个这样的函数会强制使用顺序执行计划。这是默认选项。PARALLEL RESTRICTED表示该函数能在并行模式中运行,但是其执行被限制在并行组的领导者中。PARALLEL SAFE表示该函数对于在并行模式中运行是安全的并且不受限制。如果函数修改任何数据库状态、会使用子事务之类的方式改变事务、访问序列或者对设置(如setval)做出持久性的更改,它们就应该被标记为并行不安全。如果它们访问临时表、客户端连接状态、游标、预备语句或者系统无法在并行模式中同步的本地后端状态(例如setseed只能在组领导者中执行,因为另一个进程所作的更改不会在领导者中被反映出来),它们应该被标为并行受限。通常,如果一个函数是受限的或者不安全的却

被标成了安全,或者它本来是不安全的却被标成了受限,在并行查询中执行时它可能会抛出错误或者产生错误的答案。如果被错误的标记,C 语言函数理论上可能展现出完全无法定义的行为,因为系统没有办法保护自己不受任意的 C 代码影响,但是在大部分情况下其结果也不会比任何其他函数差到哪里去。如果有疑问,函数应该被标为UNSAFE,这也是默认值。

COST execution_cost

一个给出该函数的估计执行代价的正数,单位是cpu_operator_cost。如果该函数返回一个集合,这就是每个被返回行的代价。如果没有指定代价,对 C 语言和内部函数会指定为 1 个单位,对其他语言的函数则会指定为 100 单位。更大的值会导致规划器尝试避免对该函数的不必要的过多计算。

ROWS result_rows

一个正数,它给出规划器期望该函数返回的行数估计。只有当该函数被声明为返回一个集合时才允许这个参数。默认假设为 1000 行。

SUPPORT support_function

用于此函数的planner support function的名称(可选的模式限定)。

你必须是超级用户才能使用此选项。

configuration_parameter

value

SET子句导致进入该函数时指定配置参数将被设置为指定值。并且在该函数退出时恢复到该参数之前的值。SET FROM CURRENT会把CREATE FUNCTION被执行时该参数的当前值保存为进入该函数时将被应用的值。

如果一个SET子句被附加到一个函数,那么在该函数内为同一个变量执行的SET LOCAL命令会被限制于该函数:在函数退出时该配置参数之前的值仍会被恢复。不过,一个普通的SET命令(没有LOCAL)会覆盖SET子句,更像一个之前的SET LOCAL命令所做的那样:这种命令的效果在函数退出后将会持续,除非当前事务被回滚。

definition

一个定义该函数的字符串常量,其含义取决于语言。它可以是一个内部函数名、一个对象文件的路径、一个 SQL 命令或者用一种过程语言编写的文本。

obj_file, link_symbol

当 C 语言源代码中该函数的名称与 SQL 函数的名称不同时,这种形式的AS子句被用于动态可载入 C 语言函数。字符串obj_file是包含编译好的C函数的动态库文件的名称,它会由LOAD命令解析。字符串link_symbol是该函数的链接符号,也就是该函数在 C 语言源代码中的名称。如果省略链接符号,它将被假定为要定义的 SQL 函数的名称。所有函数的C名称都必须不同,因此必须为重载的C函数给出不同的C名称(例如把参数类型作为

C名称的一部分)。

在重复调用引用同一对象文件的CREATE FUNCTION时,对每个会话该文件只会被载入一次。要卸载并且重新装载该文件(可能是在开发期间),需要开始一个新会话。

重载

Halo允许函数重载,也就是说同一个名称可以被用于多个不同的函数,只要它们具有可区分的输入参数类型。不管是否使用它,在有些用户不信任另一些用户的数据库中调用函数时,这种兼容性需要安全性的预防措施,

如果两个函数具有相同的名称和输入参数类型,它们被认为相同(不考虑任何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类型语法用于声明一个函数的参数和返回值。不过,CREATE FUNCTION会抛弃带圆括号的类型修饰符(例如类型numeric的精度域)。例如CREATE FUNCTION foo (varchar(10)) ...和CREATE FUNCTION foo (varchar) ...完全一样。

在用CREATE OR REPLACE FUNCTION替换一个现有函数时,对于更改参数名是有限制的。不能更改已经分配给任何输入参数的名称(不过可以给之前没有名称的参数增加名称)。如果有多于一个输出参数,不能更改输出参数的名称,因为可能会改变描述函数结果的匿名组合类型的列名。这些限制是为了确保函数被替换时,已有的对该函数的调用不会停止工作。

如果一个被声明为STRICT的函数带有一个VARIADIC参数,会严格检查该可变数组作为一个整体是否为非空。如果该数组有空值元素,该函数仍将被调用。

示例

这里是一些小例子,它们可以帮你了解函数创建。

CREATE FUNCTION add(integer, integer) RETURNS integer
AS 'select \$1 + \$2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;

在PL/pgSQL中,使用一个参数名称增加一个整数:

CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS \$\$
BEGIN
RETURN i + 1;
END;
\$\$ LANGUAGE plpgsql;

返回一个包含多个输出参数的记录:

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应该被设置为排除任何不可信用户可写的模式。这可以阻止恶意用户创建对象(例如表、函数以及操作符)来掩饰该函数所要用到的对象。在这方面特别重要的是临时表模式,默认情况下它会第一个被搜索并且通常对任何用户都是可写的。可以通过强制最后搜索临时模式来得到一种安全的布局。要这样做,把pg_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 plpgsql
SECURITY DEFINER
-- 设置一个安全的 search_path:受信的模式,然后是 'pg_temp'。
SET search_path = admin, pg_temp;

这个函数的目的是为了访问表admin.pwds。但是如果没有SET子句或者带有SET子句却只提到admin,该函数会变成创建一个名为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(uname TEXT, pass TEXT) TO admins;
COMMIT;

另见

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的一种别名。

另见

CREATE ROLE

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 [, ...] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ TABLESPACE tablespace_name ]
[ WHERE predicate ]

描述

CREATE INDEX在指定关系的指定列上构建一个索引,该关系可以是一个表或者一个物化视图。索引主要被用来提升数据库性能(不过不当的使用会导致性能变差)。

索引的键域被指定为列名或者写在圆括号中的表达式。如果索引方法支持 多列索引,可以指定多个域。一个索引域可以是一个从表行的一列或者更多列值进行计算的表达式。这种特性可以被用来获得对基于基本数据某种变换的数据的快速访问。例如,一个在upper(col)上计算的索引可以允许子句 WHERE upper(col) = 'JIM'使用索引。

Halo提供了B-树、哈希、GiST、SP-GiST、GIN 以及 BRIN。用户也可以定义自己的索引方法,但是相对较复杂。

当WHERE子句存在时,会创建一个部分索引。部分索引只包含表中一部分行的项,通常索引这一部分会比表的其他部分更有用。例如,如果有一个表包含了已付和未付订单,其中未付订单占了整个表的一小部分并且是经常被使用的部分,可以通过只在这一部分上创建一个索引来改进性能。另一种可能的应用是使用带有UNIQUE的 WHERE在表的一个子集上强制唯一性。

WHERE子句中使用的表达式只能引用底层表的列,但它可以引用所有列而不仅仅是被索引的列。当前,WHERE中也禁止使用子查询和聚集表达式。同样的 限制也适用于表达式索引中的表达式域。

所有在索引定义中使用的函数和操作符必须是"不可变的",就是说它们的结果必须仅依赖于它们的参数而不受外在因素(例如另一个表的内容和当前的时间)的影响。这种限制确保了索引的行为是 良定的。要在一个索引表达式或者WHERE子句中 使用用户定义的函数,记住在创建函数时把它标记为不可变。

参数

UNIQUE

导致系统在索引被创建时(如果数据已经存在)或者加入数据时检查重复值。会导致重复项的数据插入或者更新尝试将会产生一个错误。

当唯一索引被应用在分区边上时会有额外的限制,请参考CREATE TABLE。

CONCURRENTLY

当使用了这个选项时,系统在构建索引时不会取得任何会阻止该表上并发插入、更新或者删除的锁。而标准的索引构建将会把表锁住以阻止对表的写(但不阻塞读),这种锁定会持续到索引创建完毕。在使用这个选项时有多个需要注意的地方 --- 请见Building Indexes Concurrently。

对于临时表,CREATE INDEX始终是非并发的,因为没有其他会话可以访问它们,并且创建非并发索引的成本更低。

IF NOT EXISTS

如果一个同名关系已经存在则不要抛出错误。这种情况下会发出一个提示。 注意着并不保证现有的索引与将要创建的索引有任何相似。当 IF NOT EXISTS被指定时,需要指定索引名。

INCLUDE

可选的INCLUDE子句指定一个列的列表,其中的列将被包括在索引中作为非键列。非键列不能作为索引扫描的条件,并且该索引所强制的任何唯一性或者排除约束都不会考虑它们。不过,只用索引的扫描可以返回非键列的内容而无需访问该索引的基表,因为在索引项中就能直接拿到它们。因此,非键列的增加允许查询使用只用索引的扫描,否则就无法使用。

保守地向索引中增加非键列是明智的,特别是很宽的列。如果一个索引元组超过索引类型允许的最大尺寸,数据插入将会失败。在任何情况下,非键列都会重复来自索引基表的数据并且让索引的尺寸膨胀,因此可能会拖慢搜索。此外,B树重复数据删除永远不会与具有非关键列的索引一起使用。

INCLUDE子句中列出的列不需要合适的操作符类,甚至数据类型没有为给定的访问方法定义操作符类的列都可以包括在这个子句中。

不支持把表达式作为被包括列,因为它们不能被用在只用索引的扫描中。

当前,有B-树和GiST索引访问方法支持这一特性。在B-树和GiST索引中,INCLUDE子句中列出的列的值被包括在对应于堆元组的叶子元组中,但是不包括在用于树导航的上层索引项中。

name

要创建的索引名称。这里不能包括模式名,因为索引总是被创建在其基表所在的模式中。如果索引名称被省略,系统将基于基 表名称和被索引列名称选择一个合适的名称。

ONLY

如果该表是分区表,指示不要在分区上递归创建索引。默认会递归创建索引。

table_name

要被索引的表的名称(可以被模式限定)。

method

要使用的索引方法的名称。可以选择 btree、hash、 gist、spgist、 gin以及brin。 默认方法是btree。

column_name

一个表列的名称。

expression

一个基于一个或者更多个表列的表达式。如语法中所示,表达式通常必须被写在圆括号中。不过,如果该表达式是一个函数调用的形式,圆括号可以被省略。

collation

要用于该索引的排序规则的名称。默认情况下,该索引使用被索引列的排序规则或者被索引表达式的结果排序规则。当查询涉及到使用非默认排序规则的表达式时,使用非默认排序规则的索引就能排上用场。

opclass

一个操作符类的名称。详见下文。

opclass_parameter

运算符类参数的名称。详情请见下文。

ASC

指定上升排序(默认)。

DESC

指定下降排序。

NULLS FIRST

指定把空值排序在非空值前面。在指定DESC时,这是默认行为。

NULLS LAST

指定把空值排序在非空值后面。在没有指定DESC时,这是默认行为。

storage_parameter

索引方法相关的存储参数的名称。详见 Index Storage Parameters。

tablespace_name

在其中创建索引的表空间。如果没有指定,将会使用 default_tablespace。或者对临时表上的索引使用 temp_tablespaces。

predicate

部分索引的约束表达式。

索引存储参数

可选的WITH子句为索引指定存储参数。每一种索引方法都有自己的存储参数集合。B-树、哈希、GiST以及SP-GiST索引方法都接受这个参数:

fillfactor (integer)

索引的填充因子是一个百分数,它决定索引方法将尝试填充索引页面的充满程度。对于B-树,在初始的索引构建过程中,叶子页面会被填充至该百分数,当在索引右端扩展索引(增加新的最大键值)时也会这样处理。如果页面后来被完全填满,它们就会被分裂,导致索引的效率逐渐退化。B-树使用了默认的填充因子90,但是也可以选择为10到100的任何整数值。如果表是静态的,那么填充因子100 是最好的,因为它可以让索引的物理尺寸最小化。但是对于更新负荷很重的表,较小的填充因子有利于最小化对页面分裂的需求。其他索引方法以不同但是大致类似的方式使用填充因子,不同方法的默认填充因子也不相同。

B-树索引还接受这些参数:

deduplicate_items (boolean)

B 树重复数据删除技术的使用。设置为 ON或OFF以启用或禁

用优化(ON 和 OFF 的其他写法见配置参数参考)。默认值为ON.

注意:通过ALTER INDEX关闭deduplicate_items 可以防止将来的插入触发重复数据删除,但本身不会使现有的发布列表元组使用标准的元组表示。

vacuum_cleanup_index_scale_factor (floating point)

vacuum_cleanup_index_scale_factor针对每个索引的值。

GiST还额外接受这个参数:

buffering (enum)

描述的缓冲构建技术来构建索引。OFF会禁用它,ON则启用该特性,如果设置为AUTO则初始会禁用它,但是一旦索引尺寸到达effective_cache_size就会随时打开。默认值是AUTO。

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)

定义是否只要在下一个页面上检测到插入就为前面的页面范围运行概要操作。

并发构建索引

创建索引可能会干扰数据库的常规操作。通常系统会锁住要被索引的表,让它不能被写入,并且用该表上的一次扫描来执行整个索引的构建。其他事务仍然可以读取表 ,但是如果它们尝试在该表上进行插入、更新或者删除,它们会被阻塞直到索引构建完成。如果系统是一个生产数据库,这可能会导致严重的后果。索引非常大的表可能会需要很多个小时,而且即使是较小的表,在构建索引过程中阻塞写入者一段时间在生产系统中也是不能接受的。

Halo支持构建索引时不阻塞写入。这种方法通过指定CREATE INDEX的CONCURRENTLY选项实现。当使用这个选项时,系统需要执行该表的两次扫描,此外它必须等待所有现有可能会修改或者使用该索引的事务终止。因此这种方法比起标准索引构建过程来说要做更多工作并且需要更多时间。不过,由于它允许在构建索引时继续普通操作,这种方式

对于在生产环境中增加新索引很有用。当然,由索引创建带来的额外 CPU 和 I/O 开销可能会拖慢其他操作。

在并发索引构建中,索引实际上在一个事务中被录入到系统目录,然后在两个事务中发生两次表扫描。在每一次表扫描之前,索引构建必须等待已经修改了表的现有事务终止。在第二次扫描之后,索引构建必须等待任何持有早于第二次扫描的快照的事务终止。然后该索引最终能被标记为准备好使用,并且CREATE INDEX命令终止。不过即便那样,该索引也不是立刻可以用于查询:在最坏的情况下,只要早于索引构建开始时存在的事务存在,该索引就无法使用。

如果在扫描表示出现问题,例如死锁或者唯一索引中的唯一性被违背, CREATE INDEX将会失败,但留下一个"不可用"的索引。这个索引会被查询所忽略,因为它可能不完整。不过它仍将消耗更新 开销。psql的\d命令将把这类索引报告为 INVALID:

Halo0root=# \\d tab
Table "public.tab"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
col | integer | | |

Indexes:

"idx" btree (col) INVALID

这种情况下推荐的恢复方法是删除该索引并且尝试再次执行CREATE INDEX CONCURRENTLY。

(另一种可能性是用REINDEX INDEX CONCURRENTLY重建该索引)。

并发构建一个唯一索引时需要注意的另一点是,当第二次表扫描开始时,唯一约束已经被强制在其他事务上。这意味着在该索引变得可用之前,其他查询中可能就会报告该约束被违背,或者甚至在索引构建最终失败的情况中也是这样。还有,如果在第二次扫描时发生失败,"无效的"索引也会继续强制它的唯一性约束。

表达式索引和部分索引的并发构建也被支持。在这些表达式计算过程中发生的错误可能导致和上述唯一约束违背类似的行为。

常规索引构建允许在同一个表上同时构建其他常规索引,但是在一个表上同时只能有一个并发索引构建发生。在两种情况下,在索引被构建时不允许表的模式修改。另一个不同是,一个常规CREATE INDEX 命令可以在一个事务块中执行,但是 CREATE INDEX CONCURRENTLY不行。

当前不支持在分区表上并发生成索引。然而,你可以在每个分区上单独的并发构建索引,然后最终以非并发的方式创建分区索引,以减少对分区表的写入被锁定的时间。在这种情况下,生成分区索引仅是元数据操作。

注解

当前,只有B-树、GiST、GIN 和 BRIN 索引方法支持多列索引。默认最多可以索引32 个列。当前只有 B-树支持唯一索引。

为索引的每一列可以指定一个带可选参数的操作符类。该操作符类标识要被该索引用于该列的操作符。例如,一个四字节整数上的B-树索引会使用int4_ops类。这个操作符类包括了用于四字节整数的比较函数。实际上,通常列数据类型的默认操作符类就足够了。对某些数据类型指定操作符类的主要原因是,可能会有多于一种有意义的顺序。例如,我们可能想用绝对值或者实数部分对复数类型排序。我们可以通过为该数据类型定义两个操作符类来做到,并且在创建索引时选择其中合适的类。

当在一个分区表上调用CREATE INDEX时,默认的行为是递归到所有的分区上以确保它们都具有匹配的索引。每一个分区首先会被检查是否有一个等效的索引存在,如果有则该索引将被挂接为被创建索引的一个分区索引,而被创建的索引将成为其父索引。如果不存在匹配的索引,则会创建一个新的索引并且自动进行挂接。如果命令中没有指定索引名称,每个分区中的新索引的名称将被自动决定。如果指定了ONLY选项,则不会进行递归,并且该索引会被标记为无效(一旦所有的分区都得到该索引,ALTER INDEX ... ATTACH PARTITION可以把该索引标记为有效)。不过,要注意不管是否指定这一选项,未来使用CREATE TABLE ... PARTITION OF创建的任何分区将自动有一个匹配的索引,不管有没有指定ONLY。

对于支持有序扫描的索引方法(当前只有 B-树),可以指定可选子句ASC、 DESC、NULLS FIRST以及NULLS LAST 来修改索引的排序顺序。由于一个有序索引能前向或者反向扫描,通常创建一个单列DESC索引没什么用处 --- 一个常规索引已经提供了排序顺序。这些选项的价值是可以创建多列索引,让它的排序顺序匹配有混合排序要求的查询,例如SELECT ... ORDER BY x ASC, y DESC。如果你想要在依靠索引避免排序步骤的查询中支持 "空值排序低"这种行为,NULLS选项就能派上用场,默认的行为是"空值排序高"。

对于大多数索引方法,索引的创建速度取决于 maintenance_work_mem的设置。较大的值将会减少索引创建所需的时间,当然不要把它设置得超过实际可用的内存量(那会迫使机器进行交换)。

系统可以在构建索引时利用多个CPU以更快地处理表行。这种特性被称为并行索引构建。对于支持并行构建索引的索引方法(当前只有B-树),maintenance_work_mem指定每次索引构建操作整体可用的最大内存量,而不管启动了多少工作者进程。一般来说,一个代价模型(如果有)自动判断应该请求多少工作者进程。

增加maintenance_work_mem可以让并行索引构建受益,而等效的串行索引构建将无法受益或者得到很小的益处。注意maintenance_work_mem可能会影响请求的工作者进程的数量,因为并行工作者必须在总的maintenance_work_mem预算中占有至少32MB的份额。还必须有32MB的份额留给领袖进程。增加max_parallel_maintenance_workers可以允许使用更多的工作者,这将降低索引创建所需的时间,只要索引构建不是I/O密集型的。当然,还需要有足够的CPU计算能力,否则工作者们会闲置。

通过ALTER TABLE为parallel_workers设置一个值直接控制着CREATE INDEX会对表请求多少并行工作者进程。这会完全绕过代价模型,并且防止maintenance_work_mem对请求多少并行工作者产生影响。通过ALTER TABLE将parallel_workers设置为0将禁用所有情况下的并行索引构建。

提示:在把parallel_workers用于调优一次索引构建之后,你可能想要重置parallel_workers。这可以避免对查询计划的无意更改,因为parallel_workers影响所有的并行表扫描。

虽然带有CONCURRENTLY选项的CREATE INDEX支持并行构建并且没有特殊的限制,但只有第一次表扫描会实际以并行方式执行。

使用DROP INDEX可以移除一个索引。

示例

在表films中的列title上创建一个 B-树索引:

CREATE UNIQUE INDEX title_idx ON films (title);

要在表films的列title上创建一个唯一的B-树索引并且包括列director和rating:

CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);

要创建禁用重复数据删除的 B 树索引:

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 索引,这样我们可以在转换函数的结果 上有效地使用 box操作符:

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

另见

ALTER INDEX, DROP INDEX, REINDEX

CREATE LANGUAGE​

CREATE LANGUAGE --- 定义一种新的过程语言

大纲

CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name
HANDLER call_handler [ INLINE inline_handler ] [ VALIDATOR valfunction ]
CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name

描述

CREATE LANGUAGE为系统注册一种新的过程语言。接着,可以用这种新语言定义函数和存储过程。

CREATE LANGUAGE实际上把该语言名称与负责执行用该语言编写的函数的处理器函数关联在一起。

CREATE OR REPLACE LANGUAGE将创建或者替换一种现有的定义。如果该语言已经存在,其参数会被根据命令更新。但该语言的拥有关系和权限设置不会更改,并且任何已有的用该语言编写的函数仍然被假定有效。

必须使用超级用户权限才能注册新语言或更改现有语言的参数。 然而,一旦语言被创建,将它的所有权分配给非超级用户是有效的,然后他可以删除它、更改其权限、重命名它或将其分配给新的所有者。(但是,不要将底层 C 函数的所有权分配给非超级用户;这会为该用户创建权限提升路径。)不提供任何处理函数的CREATE LANGUAGE形式已过时。为了向后兼容旧的转储文件,它被解释为CREATE EXTENSION。如果语言被打包到同名的扩展中,这将起作用,这是设置过程语言的传统方式。

参数

TRUSTED

TRUSTED指定该语言不会授予用户不该具有的 数据访问。如果在注册语言时这个关键词被省略,只有超级用户特权的用户才能使用该语言创建新函数。

PROCEDURAL

这是一个噪声词。

name

新过程语言的名称。该名称必须在该数据库的语言中唯一。

为了向后兼容,名称可以用单引号围绕。

HANDLER call_handler

call_handler 是一个之前注册的函数的名称,它将被调用来执行该过程语言的函数。一种过程语言的调用处理器必须以一种编译型语言(如 C)编写并且具有版本1的调用约定,它必须在系统内注册为一个没有参数并且返回language_handler类型的函数。 language_handler是一种占位符类型,它被用来标识该函数为一个调用处理器。

INLINE inline_handler

inline_handler 是一个之前注册的函数的名称,它将被调用来执行一个该语言的匿名代码块( DO命令)。如果没有指定 inline_handler函数,则该语言不支持匿名代码块。

该处理器函数必须接受一个internal 类型的参数,该参数将是DO命令的内部表示,而且它通常将返回void。该处理器的返回值会被忽略。

VALIDATOR valfunction

valfunction is the 是一个之前注册的函数的名称,当一个该语言的新函数被创建时会调用该函数来验证新函数。如果没有指定验证器函数,那么一个新函数被创建时不会被检查。验证器函数必须接受一个oid类型的参数,它将是要被创建的函数的 OID,而且它通常将返回void。

一个验证器函数通常会检查函数体中的语法正确性,但是它也能查看函数的其他属性,例如该语言能否处理特定的参数类型。为了发出一个错误,验证器函数应该使用ereport()函数。验证器函数的返回值会被忽略。

注解

使用DROP LANGUAGE删除过程语言。

要以一种过程语言创建函数,用户必须具有对于该语言的 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;

另见

ALTER LANGUAGE, CREATE FUNCTION, DROP LANGUAGE, GRANT, REVOKE

CREATE MATERIALIZED VIEW​

CREATE MATERIALIZED VIEW --- 定义一个新的物化视图

大纲

CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] table_name
[ (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,不过它还会记住被用来初始化该视图的查询,这样它可以在后来被命令刷新。一个物化视图有很多和表相同的属性,但是不支持临时物化视图。

参数

IF NOT EXISTS

如果已经存在一个同名的物化视图时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的物化视图与即将创建的物化视图相似。

table_name

要创建的物化视图的名称(可以被模式限定)。

column_name

新物化视图中的一个列名。如果没有提供列名,会从查询的输出列名来得到。

USING method

此可选子句指定用于存储新具体化视图内容的表访问方法;该方法需要是TABLE类型的访问方法。如果未指定此选项,则为新具体化视图选择默认表访问方法详细信息请参考default_table_access_method 。

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

这个子句为新的物化视图指定可选的存储参数,详见CREATE TABLE的 Storage Parameters。所有CREATE TABLE支持的参数CREATE MATERIALIZED VIEW也支持。 详见CREATE TABLE。

TABLESPACE tablespace_name

tablespace_name是 要把新物化视图创建在其中的表空间的名称。如果没有指定,将查阅default_tablespace。

query

一个SELECT、TABLE 或者VALUES命令。这个查询将在一个安全受限的操作中运行。特别地,对本身会创建临时表的函数的调用将会失败。

**WITH [ NO ] DATA**

这个子句指定物化视图是否在创建时被填充。如果不是,该物化视图将被标记为 不可扫描并且在REFRESH MATERIALIZED VIEW被使用前不能被查询。

另见

ALTER MATERIALIZED VIEW, CREATE TABLE AS, CREATE VIEW, DROP MATERIALIZED VIEW, REFRESH MATERIALIZED VIEW