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操作符。由于 缺少哪种选择更好的知识,解析器会放弃并且说明查询有歧义。我们能 告诉解析器把一个混合了numeric和integer的 表达式解析成numeric更好的方法就是只让这两种造型中的 一个是隐式的,没有有关于此的内建知识。
对标记造型为隐式持保守态度是明智的。过多的隐式造型路径可能导致 PostgreSQL以令人吃惊的方式解 释命令,或者由于有多种可能解释而根本无法解析命令。一种好的经验 是让一种造型只对于同一种一般类型分类中的类型间的信息保持转换隐式 可调用。例如,从int2到int4的造型 可以被合理地标记为隐式,但是从float8到 int4的造型可能应该只能在赋值时使用。跨类型分类 的造型(如text到int4)最好只被用于显式使用。
Note: 有时为了可用性或者标准兼容的原因,有必要提供在一个类型集合之间 的多种隐式造型,这会导致上述不可避免的歧义。解析器还有一招基于 类型分类和优先类型的后手,它能帮助 提供这类情况下预期的行为。详见 CREATE TYPE。
要创建一种造型,你必须拥有源数据类型和目标数据类型并且具有在其他类型上 的USAGE特权。要创建一种二进制可强制造型,你必须是一 个超级用户(这种限制是因为错误的二进制可强制造型转换很容易让服务器崩溃)。
该造型的源数据类型的名称。
该造型的目标数据类型的名称。
被用于执行该造型的函数。函数名称可以用模式限定。如果没有被限定, 将在模式搜索路径中查找该函数。函数的结果数据类型必须是该造型的 目标数据类型。它的参数讨论如下。
指示源类型可以二进制强制到目标类型,因此执行该造型不需要函数。
指示该造型是一种 I/O 转换造型,执行需要调用源数据类型的输出函数, 并且把结果字符串传递给目标数据类型的输入函数。
指示该造型可以在赋值的情况下被隐式调用。
指示该造型可以在任何上下文中被隐式调用。
造型实现函数可以具有 1 到 3 个参数。第一个参数类型必须等于源类型或者 能从源类型二进制强制得到。第二个参数(如果存在)必须是类型 integer,它接收与目标类型相关联的类型修饰符,如果没有类型 修饰符,它会收到-1。第三个参数(如果存在)必须是类型 boolean,如果该造型是一种显式造型,它会收到 true,否则会收到false(奇怪地是,SQL 标准在 某些情况中对显式和隐式造型要求不同的行为。这个参数被提供给必须实现这 类造型的函数。不推荐在设计自己的数据类型时用它)。
一个造型函数的返回类型必须等于目标类型或者能二进制强制到目标类型。
Ordinarily a cast must have different source and target data types. However, it is allowed to declare a cast with identical source and target types if it has a cast implementation function with more than one argument. This is used to represent type-specific length coercion functions in the system catalogs. The named function is used to coerce a value of the type to the type modifier value given by its second argument.
When a cast has different source and target types and a function that takes more than one argument, it supports converting from one type to another and applying a length coercion in a single step. When no such entry is available, coercion to a type that uses a type modifier involves two cast steps, one to convert between data types and a second to apply the modifier.
A cast to or from a domain type currently has no effect. Casting to or from a domain uses the casts associated with its underlying type.
使用DROP CAST移除用户定义的造型。
记住如果你想要能够双向转换类型,你需要在两个方向上都 显式声明造型。
通常没有必要创建用户定义类型和标准字符串类型(text、 varchar和char(n), 以及被定义在字符串分类中的用户定义类型)之间的造型。 PostgreSQL会为它们提供自动的 I/O 转换造型。 到字符串类型的自动造型被当做赋值造型,而字符串类型作为源的自动 造型只能是显式的。通过声明你自己的造型来替换自动造型可以覆盖这 种行为,但是这样做的唯一原因是你想让该转换比标准的设置更容易被 调用。另一种可能的原因是你想让该转换的行为与该类型的 I/O 函数不 同,但这种原因足够令人感到意外,你应该考虑再三它是不是个好主意 (确实有少量内建类型对转换具有不同的行为,绝大部分是因为 SQL 标准的要求)。
虽然不必要,推荐你继续遵循这种在目标数据类型后面命名造型 实现函数的习惯。很多用户习惯于能够使用一种函数风格的记法来造型 数据类型,即typename(x)。 这种记法正好是对造型实现函数的调用,这里它没有被作为造型特殊对待。 如果你的转换函数没有被指定支持这种习惯,那么你的用户会觉得意外。 由于PostgreSQL允许用不同的参数类型重载同一个 函数名,因此存在多个从不同类型到同一目标类型的同名转换函数并不困难。
Note: 实际上前一段过于简化了:有两种情况中一个函数调用结构在没有被匹配到 一个实际函数时将被当作一次造型请求。如果函数调用 name(x)没有正好匹配任何现有函数, 但name是一种数据类型的名称并且 pg_cast提供了一种从x的类型到这种 类型的二进制可强制造型,那么该调用将被翻译为一次二进制可强制造型。 通过这种例外,二进制可强制造型能够以函数语法调用,即便没有该函数。 同样的,如果没有pg_cast项,但是该造型是要造型到一种 字符串类型或者是要从一种字符串类型造型,调用将被翻译成一次 I/O 转换 造型。这种例外允许以函数语法调用 I/O 转换造型。
Note: 还有一种例外中的例外:从组合类型到字符串类型的 I/O 转换造型不能使用 函数语法调用,而必须被写成显式造型语法(CAST或者 ::记号)。增加这种例外是因为在引入了自动提供的 I/O 转换 造型之后,在想要引用一个函数或者列时太容易意外地调用这种造型。