pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
CREATE CAST — 定义一种新的类型转换
CREATE CAST (sourcetypeAStargettype) WITH FUNCTIONfuncname(argtypes) [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (sourcetypeAStargettype) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST定义一种新的类型转换。 类型转换规定如何在两种数据类型之间执行转换。例如,
SELECT CAST(42 AS text);
通过调用一个预先指定的函数(此处是 text(int4))把整型常量 42 转换成 text类型。(如果没有定义合适的类型转换, 转换就会失败。)
两种类型可以是二进制兼容的,这意味着无需调用任 何函数,就可以把它们“免费”地互相转换。这要求对应的值使用相同 的内部表示。例如,text和varchar这两种类型就是 二进制兼容的。
默认情况下,只有显式请求类型转换时才会调用一种类型转换,也就是显式使 用CAST(或 x AS typename)x::typename 这种构造。
如果一种类型转换被标记为AS ASSIGNMENT,那么在把值赋 给目标数据类型的列时就可以隐式调用它。例如,假设foo.f1 是一个text类型的列,那么如果从integer到 text的类型转换被标记为AS ASSIGNMENT, 则:
INSERT INTO foo (f1) VALUES (42);
就会被允许,否则不会。(我们通常用术语赋值类型转换 来描述这种类型转换。)
如果一种类型转换被标记为AS IMPLICIT,那么无论是在赋 值上下文中还是在表达式内部,都可以在任何上下文中隐式调用它。例如,由 于||接受text操作数,
SELECT 'The time is ' || now();
只有在从timestamp到text的类型转换被标记为 AS IMPLICIT时才会被允许。否则就必须显式写出该类型转 换,例如
SELECT 'The time is ' || CAST(now() AS text);
(我们通常用术语隐式类型转换来描述这种类型转 换。)
把类型转换标记为隐式时应当保持保守。过多的隐式类型转换路径可能导致 PostgreSQL对命令作出令人意外的解释,或 者因为存在多种可能的解释而根本无法解析命令。一个好的经验法则是,只有 对同一一般类型分类中且能保留信息的类型间转换,才让它可以被隐式调用。 例如,从int2到int4的类型转换可以合理地设为隐 式,但从float8到int4的类型转换大概应仅限赋值 使用。跨类型分类的类型转换,例如从text到int4, 最好只允许显式调用。
要能够创建一个类型转换,你必须拥有源数据类型或目标数据类型之一。要创建一个二进制兼容的类型转换,你必须 是超级用户。(之所以有这一限制,是因为错误的二进制兼容类型转换很容易 使服务器崩溃。)
sourcetype该类型转换的源数据类型的名称。
targettype该类型转换的目标数据类型的名称。
funcname(argtypes)用于执行该类型转换的函数。函数名可以用模式限定;如果没有,则会在模 式搜索路径中查找该函数。该函数的结果数据类型必须与类型转换的目标类 型一致。其参数见下文。
WITHOUT FUNCTION表示源类型和目标类型是二进制兼容的,因此执行该类型转换不需要函 数。
AS ASSIGNMENT表示该类型转换可以在赋值上下文中隐式调用。
AS IMPLICIT表示该类型转换可以在任何上下文中隐式调用。
类型转换实现函数可以有一到三个参数。第一个参数类型必须与类型转换的源类 型相同。第二个参数(如果有)必须是 integer类型;它接收与目标类型关联的类型修饰符,如果没有 则为-1。第三个参数(如果有)必须是boolean 类型;如果该类型转换是显式类型转换,它接收true,否则 接收false。(奇怪的是,SQL 标准在某些情况下要求显式类 型转换和隐式类型转换具有不同的行为。这个参数是为必须实现这类类型转换 的函数提供的。不建议你把自己的数据类型设计成需要关心这一点。)
通常,类型转换的源数据类型和目标数据类型必须不同。不过,如果它具有一 个接受多个参数的类型转换实现函数,则允许声明源类型和目标类型相同的类 型转换。这用于在系统目录中表示特定类型的长度强制函数。所命名的函数用 于将该类型的值强制为其第二个参数给定的类型修饰符值。
当一种类型转换的源类型和目标类型不同,且其函数接受多个参数时,它支持 在一个步骤中同时完成从一种类型到另一种类型的转换并应用长度强制。如果 没有这样的条目,对使用类型修饰符的类型进行强制就需要两个类型转换步 骤:先在数据类型之间进行转换,再应用该修饰符。
使用 DROP CAST 删除用户定义的转换。
请记住,如果你希望能够双向转换类型,就需要在两个方向上分别显式声明类 型转换。
在 PostgreSQL 7.3 之前,每个与某种数据类型同名、返回该数据类型且接受一个不同类型参数的函数都会自动成为类型转换函数。随着模式的引入,以及为了能在系统目录中表示二进制兼容的类型转换,这一惯例已被放弃。内建的类型转换函数仍然遵循这一命名方案,但它们也必须显示为系统目录 pg_cast 中的转换。
虽然这不是强制要求,但仍建议你继续遵循这种老惯例,即按目标数据类型为 类型转换实现函数命名。许多用户已经习惯于用函数风格的记法进行类型转 换,也就是typename(x)。 这种记法实际上无非就是调用类型转换实现函数;它不会被特别当作类型转换 处理。如果你的转换函数没有按这种惯例命名,那么用户会感到意外。由于 PostgreSQL允许同一函数名按不同参数类型重 载,因此让来自不同类型的多个转换函数都使用目标类型的名称并不存在困 难。
前一段有一个小小的谎言:仍然存在一种情况,pg_cast 会被用来解析一个表面上是函数调用的含义。如果函数调用 name(x)没有匹配到任何 实际存在的函数,但name是一个数据类型名,并且 pg_cast显示存在从x的类型 到该类型的二进制兼容类型转换,那么该调用会被解释为一个显式类型转换。 作出这一例外,是为了让二进制兼容的类型转换即使没有任何函数,也能使 用函数语法调用。
要使用函数int4(text)创建一种从类型 text到类型int4的类型转换:
CREATE CAST (text AS int4) WITH FUNCTION int4(text);
CREATE CAST命令符合 SQL:1999, 不过 SQL:1999 没有对二进制兼容的类型转换或实现函数的额外参数作出规定。 AS IMPLICIT也是 PostgreSQL的扩展。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。