打印

PostgreSQL学习文档

8.1. 数值类型

数值类型由2、4或8字节的整数以及4或8字节的浮点数和可选精度小数组成。 Table 8-2 列出了所有可用类型。

Table 8-2. 数值类型

名字 存储空间 描述 范围
smallint 2 字节 小范围整数 -32768 到 +32767
integer 4 字节 常用的整数 -2147483648 到 +2147483647
bigint 8 字节 大范围的整数 -9223372036854775808 到 9223372036854775807
decimal 变长 用户声明精度,精确 无限制
numeric 变长 用户声明精度,精确 无限制
real 4 字节 变精度,不精确 6 位十进制数字精度
double precision 8 字节 变精度,不精确 15 位十进制数字精度
serial 4 字节 自增整数 1 到 +2147483647
bigserial 8 字节 大范围的自增整数 1 到 9223372036854775807

数值类型常量的语法在 Section 4.1.2 里描述。 数值类型对应有一套完整的数学操作符和函数。相关信息请参考 Chapter 9。 下面的几节详细描述这些类型。

TOP

8.1.1. 整数类型

类型 smallint,integer,和 bigint 存储各种范围的全部是数字的数,也就是没有小数部分的数字。 试图存储超出范围以外的数值将导致一个错误。

常用的类型是 integer,因为它提供了在范围,存储空间, 和性能之间的最佳平衡。一般只有在磁盘空间紧张的时候才使用 smallint。而只有在 integer 的范围不够的时候才使用 bigint,因为前者绝对快得多。

bigint 类型可能不是在所有平台上都运转正确, 因为它依赖编译器对八字节整数的支持。在那些没有这样支持的机器上, bigint 的作用和 integer 一样(但是仍然占据八字节存储)。不过,我们还不知道任何有这样的情况的平台。

SQL只声明了整数类型 integer(或int)和 smallint。类型 bigint,和类型名 int2,int4,和 int8 都是扩展, 也在许多其它 SQL 数据库系统中使用。

TOP

8.1.2. 任意精度数值

类型 numeric 可以存储最多1000位精度的数字并且准确地进行计算。 我们特别建议将它用于货币金额和其它要求计算准确的数量。不过,numeric 类型上的算术运算比整数类型或者我们下一节描述的浮点数类型要慢很多。

在随后的内容里,我们使用了下述术语: 一个 numeric 的比例是到小数点右边为止小数部分的位数, numeric 的精度是整个数字里全部数据位的数目,也就是小数点两边的数据数目。 因此数字 23.5141 的精度为6而比例为4。你可以认为整数的比例为零。

numeric 字段的最大精度和最大比例都是可以配置的。要声明一个类型为 numeric 的字段,你可以用下面的语法

NUMERIC(precision, scale)
精度必须为正数,比例可以为零或者正数。 另外,

NUMERIC(precision)
选择了 0 为比例。不带任何精度或者比例声明

NUMERIC
则创建一个可以存储一个直到实现精度上限的任意精度和比例的数值, 一个这样类型的字段将不会把输入数值转化成任何特定的比例, 而带有比例声明的 numeric 字段将把输入值转化为该比例。 (SQL标准要求缺省的比例是 0。也就是转化成整数精度。 我们觉得这样做有点没用。如果你关心移植性,那你最好总是明确声明精度和比例。)

如果一个要存储的数值的比例比字段声明的比例高, 那么系统将尝试圆整该数值到指定的小数位。 然后,如果小数点左边的数据位数超过了声明的精度减去声明的比例, 那么抛出一个错误。

数值数据值物理上是不带任何前导或者后缀零的形式存储的。 因此,字段上声明的精度和比例都是最大值,而不是固定分配的。 (在这个方面,numeric 类型更类似于 varchar(n), 而不像 char(n)。) 实际存储是每四个十进制位两个字节,然后在整个数据上加上八个字节的额外开销。

除了普通的数字值之外,numeric 类型允许特殊值 NaN, 表示"不是一个数字"。任何在 NaN 上面的操作都生成另外一个 NaN。 如果在 SQL 命令里把这些值当作一个常量写,你必须在其周围放上单引号,比如 UPDATE table SET x = 'NaN'。在输入时,字串 NaN 当作大小写无关看待。

类型 decimal 和 numeric 是等效的。 两种类型都是SQL标准。

TOP

8.1.3. 浮点数类型

数据类型 real 和 double precision 是不准确的,变精度的数字类型。 实际上,这些类型是 IEEE 标准 754 二进制浮点数算术(分别对应单和双精度)的一般实现, 外加下层处理器,操作系统和编译器对它的支持。

不准确意味着一些数值不能准确地转换成内部格式并且是以近似的形式存储的,因此存储然后把数据再打印出来可能显示一些缺失。 处理这些错误以及这些错误是如何在计算中传播的属于数学和计算机科学的一个完整的分支, 我们不会在这里进一步讨论它,这里的讨论仅限于如下几点:



如果你要求准确的计算(比如计算货币金额),应使用 numeric 类型。

如果你想用这些类型类型做任何重要的复杂计算,尤其是那些你对范围情况(无穷,下溢)严重依赖的事情,那你应该仔细评诂你的实现。

拿两个浮点数值进行相等性比较可能象,也可能不象想像那样运转。


通常,real 类型的范围是至少 -1E+37 到 +1E+37, 精度至少是 6 位小数。double precision 类型通常有 -1E+308 到 +1E+308 的范围,精度是至少 15 位数字。太大或者太小的数值都会导致错误。 如果输入数据太高,那么可能发生园整。太接近零的数字,如果无法与零值的表现形式相区分就会产生下溢错。

除了普通的数字值之外,浮点类型还有几个特殊值:

Infinity
-Infinity
NaN

这些值分别表示 IEEE 754 特殊值"正无穷大","负无穷大", 以及"不是一个数字"。(在不遵循 IEEE 754 浮点算术的机器上,这些值的含义可能不是预期的。) 如果在 SQL 命令里把这些数值当作常量写,你必须在它们周围放上单引号, 像这样 UPDATE table SET x = 'Infinity'。 输入时,这些值是以大小写无关的方式识别的。

PostgreSQL 还支持 SQL 标准表示法 float 和 float(p) 用于声明非精确的数值类型。 在这里,p 声明以二进制位表示的最低可接受精度。 在选取 real 类型的时候,PostgreSQL 接受 float(1) 到 float(24),在选取 double precision 的时候,接受 float(25) 到 float(53)。在允许范围之外的 p 值将导致一个错误。 没有声明精度的 float 将被当作是 double precision。

注意: 在 PostgreSQL 7.4 以前,在 float(p) 里面的精度会被当作是这么多位数的十进制位。到 7.4 已经被修改成与 SQL 标准匹配,标准声明这个精度是以二进制位度量的。假设 real 和 double precision 分别有 24 和 53 个二进制位的位数对 IEEE 标准的浮点实现来说是正确的。 在非 IEEE 平台上,这个数值可能略有偏差,但是为了简化,我们在所有平台上都用了同样的 p 值范围。

TOP

8.1.4. Serial(序号)类型

serial 和 bigserial 类型不是真正的类型, 只是为在表中设置唯一标识做的概念上的便利。(类似其它一些数据库中的 AUTO_INCREMENT 属性)。 在目前的实现中,下面一句话:

CREATE TABLE tablename (
        colname SERIAL
);
等价于声明下面几句话:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename(
        colname integer DEFAULT nextval('tablename_colname_seq') NOT NULL
);
因此,我们就创建了一个整数字段并且把它的缺省数值安排为从一个序列发生器取值。 应用了一个 NOT NULL 约束以确保空值不会被明确地插入。 在大多数情况下你可能还希望附加一个 UNIQUE 或者 PRIMARY KEY 约束避免意外地插入重复的数值,但这个不是自动发生的。

注意: 在 PostgreSQL 7.3 以前,serial 隐含 UNIQUE。但现在不再如此。 如果你希望一个序列字段有一个唯一约束或者一个主键,那么你现在必须声明,就像其它数据类型一样。

要使用 serial 字段插入序列的下一个数值到表中, 主要是要注意 serial 应该赋予缺省值。 我们可以通过在 INSERT 语句中把该字段排除在字段列表之外来实现, 也可以通过使用 DEFAULT 关键字来实现。

类型名 serial 和 serial4 是等效的: 两个都创建 integer 字段。类型名 bigserial 和 serial8 也一样,只不过它创建一个 bigint 字段。 如果你预计在表的生存期中使用的标识数目超过 231 个,那么你应该使用 bigserial。

一个 serial 类型创建的序列在所属的字段被删除的时候自动删除,其它情况下是不会被删除的。 (这一点在 PostgreSQL 版本 7.3 之前可不是真的。请注意,这种自动删除的关联在通过重载 7.3 以前的数据库转储的时候可不会自动发生; 那样的转储文件不包含需要建立这种关联关系的信息。) 另外,这样的序列和字段之间的依赖性只在 serial 字段本身上有; 如果任何其它字段引用了序列(可能是手工调用 nextval 函数), 那么,如果这个序列被删除了,它们就会被破坏。我们认为这样使用 serial 字段是一种不好的形式;如果你想用同一个序列发生器给几个字段喂数据,那么还是把序列发生器作为独立对象创建。

TOP

8.2. 货币类型
注意: money (货币)现在已经废弃,用 numeric 或 decimal 以及和 to_char 函数一起使用就可以取代它。

money 类型存储固定小数点位置的货币数字。 参阅 Table 8-3。 可接受的输入格式很多,包括整数和浮点数文本,以及""货币格式,象 '$1,000.00' 这样的。 输出是最后一种形式,但和区域相关。

Table 8-3. 货币类型

名字 存储空间 描述 范围
money 4 字节 货币金额 -21474836.48 到 +21474836.47

TOP

8.3. 字符类型
Table 8-4. 字符类型

名字 描述
character varying(n), varchar(n) 变长,有长度限制
character(n), char(n) 定长,不足补空白
text 变长,无长度限制

Table 8-4 显示了在 PostgreSQL 里可用的一般用途的字符类型。

SQL 定义了两种基本的字符类型: character varying(n) 和 character(n), 这里的 n 是一个正整数。两种类型都可以存储最多 n 个字符长的字串。 试图存储更长的字串到这些类型的字段里会产生一个错误, 除非超出长度的字符都是空白,这种情况下该字串将被截断为最大长度。 (这个看上去有点怪异的例外是SQL标准要求的。) 如果要存储的字串比声明的长度短, 类型为 character 的数值将会用空白填满; 而类型为 character varying 的数值将只是存储短些的字串。

如果我们明确地把一个数值转换成 character(n) 或者 character varying(n), 那么超长的数值将被截断成 n 个字符,而不会抛出错误。(这也是SQL标准的要求。)

注意: 在PostgreSQL7.2 以前,太长的字串总会被不声不响地咔喳掉, 而且不会生成错误。不管是明确的还是隐含的转换情况下。

TOP

char(n) 和 varchar(n) 的概念分别是 character(n) 和 character varying(n) 的别名, 没有长度声明词的character 等于 character(1);如果不带长度说明词使用 character varying,那么该类型接受任何长度的字串。 后者是PostgreSQL的扩展。

另外,PostgreSQL 提供 text 类型,它可以存储任何长度的字串。 尽管类型 text 不是SQL标准,但是许多其它 SQL 数据库系统也有它。

类型 character 的数值物理上都用空白填充到指定的长度 n, 并且以这种方式存储和显示。不过,填充的空白在语意上是无所谓的。 在比较两个 character 的值的时候,填充的空白都不会被关注, 在转换成其它字串类型的时候,character 值里面的空白会被删除。 请注意,在 character varying 和 text 数值里, 结尾的空白语意上是有含义的。

这些类型的存储需求是 4 字节加上实际的字串,如果是 character 的话再加上填充的字节。长的字串将会自动被系统压缩, 因此在磁盘上的物理需求可能会更少些。长的数值也会存储在后台表里面,这样它们就不会干扰对短字段值的快速访问。 不管怎样,允许存储的最长字串大概是 1 GB。 (允许在数据类型声明中出现的的 n 的最大值比这还小。 修改这个行为没有甚么意义,因为在多字节编码下字符和字节的数目可能差别很大。 如果你想存储没有特定上限的长字串,那么使用 text 或者没有长度声明词的 character varying, 而不要选择一个任意长度限制。)

提示: 这三种类型之间没有性能差别,只不过是在使用填充空白的类型的时候增加了存储尺寸。 虽然在某些其它的数据库系统里,character(n) 有一定的性能优势, 但在 PostgreSQL 里没有。在大多数情况下,应该使用 text 或者 character varying。

请参考 Section 4.1.2.1 获取关于字串文本的语法的信息, 以及参阅 Chapter 9 获取关于可用操作符和函数的信息。 数据库的字符集决定用于存储文本值的字符集;有关字符集支持的更多信息, 请参考 Section 21.2。

TOP

Example 8-1. 使用字符类型

CREATE TABLE test1 (a character(4));
INSERT INTO test1 VALUES ('ok');
SELECT a, char_length(a) FROM test1; -- (1)
  a   | char_length
------+-------------
ok   |           2

CREATE TABLE test2 (b varchar(5));
INSERT INTO test2 VALUES ('ok');
INSERT INTO test2 VALUES ('good      ');
INSERT INTO test2 VALUES ('too long');
ERROR:  value too long for type character varying(5)
INSERT INTO test2 VALUES ('too long'::varchar(5)); -- 明确截断
SELECT b, char_length(b) FROM test2;
   b   | char_length
-------+-------------
ok    |           2
good  |           5
too l |           5
(1)
函数 char_length 在 Section 9.4中讨论。
在 PostgreSQL 里另外还有两种定长字符类型。 在 Table 8-5 里显示。 name类型只用于在内部系统表中存储标识符并且不是给一般用户使用的。 该类型长度当前定为 64 字节 (63 可用字符加结束符)但应该使用常量 NAMEDATALEN 引用。这个长度是在编译的时候设置的,(因而可以为特殊用途调整); 缺省的最大长度在以后的版本可能会改变。 类型 "char" (注意引号)和 char(1) 是不一样的,它只用了一个字节的存储空间。它在系统内部用于系统表当做穷人的枚举类型用。

Table 8-5. 特殊字符类型

名字 存储空间 描述
"char" 1 字节 单字节内部类型
name 64 字节 用于对象名的内部类型

TOP

8.4. 二进制数据类型

bytea 数据类型允许存储二进制字串。 参阅Table 8-6。

Table 8-6. 二进制数据类型

名字 存储空间 描述
bytea 4 字节加上实际的二进制字串 变长的二进制字串  

二进制字串是一个字节数值的序列。 二进制字串和字符字串的区别有两个: 首先,二进制字串完全可以允许存储字节零值以及其它"不可打印的"字节 (定义为范围在 32 到 126 之外的字节)。 字符串不允许字节零,并且也不允许那些从数据库选定的字符集编码里面认为是非法的其它字节值或者字节序列。 第二,对二进制串的处理就是实际上的字节,而字符串的处理和取决于区域设置。 简单说,二进制字串适用于存储那些程序员认为是"裸字节"的数据, 而字符串适合存储文本。

在输入 bytea 数值的时候, 在一个 SQL 语句的文本串里面, 你必须逃逸某些字节值(但可以逃逸所有字节值) 通常,要逃逸一个字节值,需要把它的数值转换成与其十进制字节值对应的三位八进制数字, 并且前导两个反斜杠。有些八进制数值有可选的逃逸序列, 在 Table 8-7 中显示, 同时给出了可选的逃逸序列。

Table 8-7. bytea 文本逃逸八进制

十进制数值 描述 输入逃逸表现形式 例子 输出形式
0  零的八进制  '\\000'  select '\\000'::bytea;  \000  
39  单引号  '\'' 或者 '\\047'  select '\''::bytea;  '  
92  反斜杠  '\\\\' 或者 '\\134'  select '\\\\'::bytea;  \\  
0 到 31 和 127 到 255 "不可打印"字节 '\\xxx' (八进制值) SELECT '\\001'::bytea; \001

TOP


感谢一直以来您对我们的支持!
当前时区 GMT+8, 现在时间是 2008-9-6 14:33 京ICP证060528 号

Designed By 17DST