CREATE CAST — 定义一种新的造型
CREATE CAST (source_type
AStarget_type
) WITH FUNCTIONfunction_name
[ (argument_type
[, ...]) ] [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type
AStarget_type
) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type
AStarget_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(
or
x
AS
typename
)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
操作符。由于
缺少哪种选择更好的知识,解析器会放弃并且说明查询有歧义。我们能
告诉解析器把一个混合了numeric
和integer
的
表达式解析成numeric
更好的方法就是只让这两种造型中的
一个是隐式的,没有有关于此的内建知识。
对标记造型为隐式持保守态度是明智的。过多的隐式造型路径可能导致
PostgreSQL以令人吃惊的方式解
释命令,或者由于有多种可能解释而根本无法解析命令。一种好的经验
是让一种造型只对于同一种一般类型分类中的类型间的信息保持转换隐式
可调用。例如,从int2
到int4
的造型
可以被合理地标记为隐式,但是从float8
到
int4
的造型可能应该只能在赋值时使用。跨类型分类
的造型(如text
到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(
,
以及被定义在字符串分类中的用户定义类型)之间的造型。
PostgreSQL会为它们提供自动的 I/O 转换造型。
到字符串类型的自动造型被当做赋值造型,而字符串类型作为源的自动
造型只能是显式的。通过声明你自己的造型来替换自动造型可以覆盖这
种行为,但是这样做的唯一原因是你想让该转换比标准的设置更容易被
调用。另一种可能的原因是你想让该转换的行为与该类型的 I/O 函数不
同,但这种原因足够令人感到意外,你应该考虑再三它是不是个好主意
(确实有少量内建类型对转换具有不同的行为,绝大部分是因为 SQL
标准的要求)。
n
)
虽然不必要,推荐你继续遵循这种在目标数据类型后面命名造型
实现函数的习惯。很多用户习惯于能够使用一种函数风格的记法来造型
数据类型,即typename
(x
)。
这种记法正好是对造型实现函数的调用,这里它没有被作为造型特殊对待。
如果你的转换函数没有被指定支持这种习惯,那么你的用户会觉得意外。
由于PostgreSQL允许用不同的参数类型重载同一个
函数名,因此存在多个从不同类型到同一目标类型的同名转换函数并不困难。
实际上前一段过于简化了:有两种情况中一个函数调用结构在没有被匹配到
一个实际函数时将被当作一次造型请求。如果函数调用
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 CAST
命令符合
SQL标准,不过 SQL 没有为二进制可强制
类型或者实现函数的额外参数做好准备。
AS IMPLICIT
也是一种
PostgreSQL扩展。