CREATE CAST

Name

CREATE CAST -- 定义一个用户定义的转换

Synopsis

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 ]

Description

CREATE CAST 定义一个新的转换。一个转换说明如何在两个类型之间进行转换。比如:

SELECT CAST(42 AS float8);

通过调用前面指定的函数将整数常量42转化为float8类型,按照 float8(int4)的形式。(如果没有定义合适的投射, 转换将失败。)

两种形式是二进制可压缩的,这意味转换可以在不调用函数的情况下 自由执行。这要求相应的值使用相同的内部表示。例如,textvarchar 形式都是二进制可强制的两种方法。二进制可压缩性未必是一个对称的关系。例如: xmltext的映射可以在当前的映射中自由执行。但相反的方向需要一个函数 来执行至少一个语法检查。(两种二进制可强迫的形式也被称为二进制兼容。)

您可以定义一个映射为使用 WITH INOUT语法的I/O转化映射。 一个I/O转化映射通过调用原数据库类型的输出函数来执行,并将结果传给 目标数据类型的输入函数。

缺省时,只有在明确要求转换的情况下才调用一个转换,也就是一个明确的 CAST(x AS typename)x::typename构造。

如果转换被标记为AS ASSIGNMENT,那么在给目标数据类型的字段赋值的时候, 可以隐含调用它。比如,假设foo.f1是一个类型为text的字段, 那么:

INSERT INTO foo (f1) VALUES (42);

如果从integer类型到text类型的转换标记为AS ASSIGNMENT,上面的这句就被允许,否则就不允许。(通常用术语assignment cast来描述这种转换。)

若果映射标记了AS IMPLICIT,那么可以在任何环境下调用,不管是 作业还是在一个内部表达式中。(我们通常使用术语implicit cast 来描述这种映射。 例如,考虑下面这个查询;)

SELECT 2 + 4.0;

解析器初始时标记常量分别为integernumeric。 在系统目录中没有integer + numeric, 但是有一个numeric + numeric操作符。 若integernumeric的映射是可获得的并且标记为 AS IMPLICIT — 则该查询将因此获得成功。解析器将使用隐性的映射并按所写的处理查询。

SELECT CAST ( 2 AS numeric ) + 4.0;

现在,目录提供了一个从numericinteger的映射。 如果那个映射标记了 AS IMPLICIT —而它并不是— 然后解析器会面临对选择上面的解释还是选择numeric常量到integer的 映射以及应用integer + integer 操作符。 缺乏选择优等项的能力,则会将放弃和声明查询模棱两可的。两映射中仅有一个 是阴性的事实正是我们设计的方式,我们让解析器更偏向于将numeric-and-integer 的混合表达式的结果视作numeric;没有关于那方面的内置知识。

在是否将转换标记为隐含的问题上保守一些是明智的。过于丰富的隐含转换路径 会导致PostgreSQL选择让人奇怪的命令解析,或者 是完全不能解析命令,因为存在多个可能的解析。一条好的拇指定律是,只有在同 一个通用类型范畴里面的那些可以保留转换信息的类型之间才标记为可隐含调用转换。 比如,从int2int4可以合理地标记为隐含转换,但 是从float8int4也许应该标记为赋值转换。跨类型 范畴的转换,比如textint4,最好只能明确地转换。

Note: 有时,有必要为了可用性和标准支持的原因在一组类型中提供多个隐式投射,导致上述 无法避免的模棱两可的问题。解析器有一个基于type categoriespreferred types的撤销启发式,有助于在这种情况下提供所期望的行为。 参阅CREATE TYPE获取更多详细信息。

为了能够创建一个映射,您必须拥有源或者目标数据类型。为了创建一个强制 二进制的映射,您必须是超级用户。(做这个约束的原因是错误的二进制可强迫映射 转换可以很容易摧毁服务器。)

参数

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), 以及被定义为字符串的范畴的用户定义的类型)。 PostgreSQL为此提供自动I/O转换映射。字符串类型的自动映射可以认为是 分配映射,而来自字符串的自动映射是唯一显式的。您可以通过声明自己的映射替换自动映射 来重写此性能,但是,通常这么做的唯一原因是,你想让转化比标准唯一分配或者唯一显式 设置更容易调用。另一个可能的原因是你想让转化变现的不同于类型的I/O函数;但是足够惊人的是 您应该反复考虑这是否是一个好主意。(少量内部类型确实对转换有不同的性能要求,大部分是 因为要求SQL标准。)

PostgreSQL7.3之前,每个与数据类型有相同名称,会返回那个 数据类型,并取一个不同类型的参数的函数,自动成为一个映射函数。 在面临模式引入时约定已取消并且能代表系统表中的二进制可强制映射。内置的映射 功能仍然遵循这种命名模式,但是他们必须像系统表pg_cast中的映射 一样显示。

虽然不是必须的,但是还是建议你遵循旧的命名类型转换实现函数的习惯,也就是说, 函数名和目标数据类型同名。许多用户习惯于使用函数风格的表示法 typename(x)来做数据类型转换。这种表示法恰好 就是调用类型转换实现函数,这样并不会被当作一种类型转换而被特殊看待。如果你的 转换函数没有按照这种传统命名,那么你就会让用户很奇怪。因为PostgreSQL 允许同名不同参数的函数重载,因此同时存在多个从不同类型向同样类型转换的同名转 换函数一点问题都没有。

Note: Actually the preceding paragraph is an oversimplification: there are two cases in which a function-call construct will be treated as a cast request without having matched it to an actual function. If a function call name(x) does not exactly match any existing function, but name is the name of a data type and pg_cast provides a binary-coercible cast to this type from the type of x, then the call will be construed as a binary-coercible cast. This exception is made so that binary-coercible casts can be invoked using functional syntax, even though they lack any function. Likewise, if there is no pg_cast entry but the cast would be to or from a string type, the call will be construed as an I/O conversion cast. This exception allows I/O conversion casts to be invoked using functional syntax. 事实上前节是过分简化的:在两种情况下函数调用结构被认为是一个映射请求而不需 要将其匹配为一个实际函数。如果函数调用name(x) 不准确匹配任何现有函数,但是name是一个数据类型的名称并且 pg_castx类型提供了一个二进制可强制映射到这个类型。 设了该异常所以二进制可强制映射可以通过使用功能性语法来调用,即使他们没有任何函数。 同样的,若无pg_cast条目,但映射会到达或者来自一个字符串类型, 调用将会被视为一个I/O转换映射。该异常允许I/O转换映射通过使用功能性语法来调用。

示例

为了从类型bigint到类型 int4创建一个指派映射要通过使用函数int4(bigint):

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

(这个转换在系统中已经预先定义了。)

兼容性

CREATE CAST指令符合SQL标准, 除了SQL不会为二进制可强制类型或者实现函数的额外参数来指定条款。 AS IMPLICIT也是一个PostgreSQL扩展。

又见

CREATE FUNCTION, CREATE TYPE, DROP CAST