Chapter 10. 扩展的 SQL:类型

正如前面所说, 在 PostgreSQL里有两种数据类型: 基本类型(在编程语言里定义)和复合类型(记录). 本章描述如何定义新的基本类型.

本章的例子可以在 complex.sqlcomplex.c 里找到.复合类型的例子在 funcs.sql 里.

一个用户定义的类型总是有输入和输出函数. 这些函数决定该类型如何在字串里出现(让用户输入和输出给用户)以及 类型如何在存储器里组织. 输入函数以一个以空(null)为分隔符的字符串为输入并且返回该类型的 内部(内存里)的表现形式.输出类型以该类型的内部表现形式 为输入并且返回一个以空(null)为分隔符的字符串.

假设我们要定义一个复数类型用来表示复数.通常,我们选用下面的 C 结构来在存储器里表现复数:

typedef struct Complex {
    double      x;
    double      y;
} Complex;

并且以 (x,y) 形式的字串做为外部的表现形式.

这些函数通常比较容易写,尤其是输出函数.不过,我们还是要注意几点:

要定义 complex 类型,我们要在创建该类型前先创建两个用户定义函数 complex_incomplex_out

CREATE FUNCTION complex_in(cstring)
    RETURNS complex
    AS 'PGROOT/tutorial/complex'
    LANGUAGE C;

CREATE FUNCTION complex_out(complex)
    RETURNS cstring
    AS 'PGROOT/tutorial/complex'
    LANGUAGE C;

最后,我们可以声明数据类型∶

CREATE TYPE complex (
    internallength = 16,
    input = complex_in,
    output = complex_out
);

请注意输入和输出函数的声明必须引用还未定义的类型。 这么做是允许的,但是会生成可以忽略的警告信息。

正如我们前面讨论的,PostgreSQL 完全支持基本类型的数组.另外 PostgreSQL 同样还支持用户定义类型的数组. 当你定义类型时, PostgreSQL 自动提供对该类型的数组的支持. 因为历史原因, 数组类型的类型名是与类型同名字串前面加个下划线_. 不需要为复合类型定义任何函数,因为系统已经知道它们在里面看起来象什么.

复合类型不需要定义人和函数,因为系统已经知道它们在内部 看起来是什么样子.

如果你的数据类型的大小可能超过几百个字节(内部形式), 那么你应该很仔细地把它们标记为可 TOAST 的.要做到这一点, 该类型地内部形式必需遵循变长数据内部形式地标准布局∶ 头四个字节必需是一个 int32,包含数据地全长 (包括其自身).然后,所有接受该类型地你地函数必需在所提供地数值上仔细调用 pg_detoast_datum() --- 如果你的函数不是严格地, 那么是在检查完该数值不是 NULL 之后, 最后,在使用 CREATE TYPE 命令的时候 选择恰当地存储选项.