Postgresql 中文操作指南

CREATE CAST

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

通过调用以前指定的函数(在此情况下为 float8(int4) )将整数常量 42 转换为 float8 类型。(如果没有定义适当的类型转换,则转换将失败。)

两种类型可以是 binary coercible ,这意味着可以免费执行转换,而无需调用任何函数。这需要相应的值使用相同的内部表示形式。例如,类型 textvarchar 在两个方向上都是二进制可转换的。二进制可转换性并不一定是对称关系。例如,从 xmltext 的类型转换可在当前实现中免费执行,但反向则需要一个至少执行语法检查的函数。(在两个方向上均可进行二进制转换的两种类型也称为二进制兼容。)

您可以使用 WITH INOUT 语法将类型转换定义为 I/O conversion cast 。通过调用源数据类型的输出函数并传入所得字符串到目标数据类型的输入函数,便能执行 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 -和- integer 表达式解析为 numeric 的方式;这是没有内置知识的。

将转换标记为隐式时最好保持保守态度。过多的隐式转换路径会导致 PostgreSQL 对命令进行令人惊讶的解释,或者由于有多重可能的解释而无法解析命令。一条好的经验法则是仅对同一类型类别中类型之间保留信息的转换进行隐式调用。例如,从 int2int4 的转换可以合理地是隐式的,但从 float8int4 的转换可能应该仅用于赋值。跨类型类别的转换,例如 textint4 ,最好仅显式进行。

Note

有时出于可用性或标准遵守原因,需要在类型集之间提供多个隐式转换,导致在上述情况下无法避免的歧义。解析器有一个基于 type categoriespreferred types 的后备启发式算法,可以在这种情况下帮助提供所需的的行为。有关更多信息,请参见 CREATE TYPE

要创建转换,您必须拥有源数据类型或目标数据类型并在另一类型上拥有 USAGE 权限。要创建二进制可强制转换,您必须是超用户。(此限制的制定是因为错误的二进制可强制转换可能会轻松导致服务器崩溃。)

Parameters

  • source_type

    • 转换的源数据类型的名称。

  • target_type

    • 转换的目标数据类型的名称。

  • _function_name[(argument_type [, …​])]_

    • 用于执行转换的函数。此函数名称可以带模式限定符。如果没有,将在模式搜索路径中查找该函数。此函数的结果数据类型必须与转换目标类型匹配。其参数在下面讨论。如果未指定参数列表,则函数名称在其模式中必须是唯一的。

  • WITHOUT FUNCTION

    • 指示源类型可以对目标类型进行二进制强制转换,因此不需要函数来执行转换。

  • WITH INOUT

    • 指示转换是 I/O 转换转换,它通过调用源数据类型的输出函数并将其结果字符串传递到目标数据类型的输入函数来执行。

  • AS ASSIGNMENT

    • 指示能在赋值上下文中隐式调用转换。

  • AS IMPLICIT

    • 指示能在任何上下文中隐式调用转换。

转换实现函数可以有一个、两个或三个参数。第一个参数类型必须与转换源类型相同或可从转换源类型进行二进制强制转换。第二个参数(如果存在)必须为类型 integer ;它接收与目标类型关联的类型修饰符,或者在没有类型修饰符时接收 -1 。第三个参数(如果存在)必须为类型 boolean ;它接收 true (如果转换是显式转换),否则接收 false 。(奇怪的是,SQL 标准在某些情况下要求显式和隐式转换的行为不同。为必须实现此类转换的函数提供此参数。不建议您设计自己的数据类型,使得这些设置至关重要。)

转换函数的返回类型必须与转换目标类型相同或可从转换目标类型进行二进制强制转换。

通常,转换必须具有不同的源数据类型和目标数据类型。但是,如果转换具有具有多个参数的转换实现函数,则允许声明具有相同源数据类型和目标数据类型的转换。这用于在系统编目中表示特定于类型的长度强制转换函数。命名的函数用于将此类型的的值强制转换为由其第二个参数给出的类型修饰符值。

当转换具有不同的源数据类型和目标数据类型以及一个采用多个参数的函数时,它支持以单步方式从一种类型转换到另一种类型并应用长度强制转换。当没有此类条目时,对使用类型修饰符的类型的强制转换涉及两个转换步骤,一个用于在数据类型之间进行转换,另一个用于应用修饰符。

当前对域类型进行或从域类型进行转换无效。对域进行或从域进行转换使用与该域的底层类型关联的转换。

Notes

DROP CAST 删除用户自定义转换。

请记住,如果您希望能够双向转换类型,您需要显式地声明双向转换。

通常不需要在用户自定义类型和标准字符串类型 ( textvarcharchar(_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 转换转换之后,发现很容易在打算调用函数或列引用时意外调用此类转换。

Examples

若要使用函数 int4(bigint) 创建从类型 bigint 到类型 int4 的赋值转换:

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

(此转换已经在系统中预定义。)

Compatibility

CREATE CAST 命令符合 SQL 标准,但 SQL 没有针对二进制可强制转换类型或针对实现函数的额外参数做出规定。 AS IMPLICIT 也是 PostgreSQL 的扩展。