打印

PostgreSQL学习文档 8.0

PostgreSQL学习文档 8.0

7.3. 选择列表

如前面的小节说明的那样, 在 SELECT 命令里的表表达式构造了一个中介性的虚拟表, 方法可能有组合表,视图,删除行,分组等等。 这个表最后传递给选择列表处理。 选择列表判断中间表的哪个字段最终实际输出。
7.3.1. 选择列表项

最简单的选择列表类型是 *,它发出表表达式生成的所有字段。 否则,一个选择列表是一个逗号分隔的值表达式的列表, (和在Section 4.2 里定义的一样)。 比如,它可能是一个字段名字的列表:

SELECT a, b, c FROM ...

字段名字a,b,和c要么是在 FROM子句里引用的表中字段的实际名字, 要么是象 Section 7.2.1.2 里解释的那样的别名。 在选择列表里的名字空间和在 WHERE 子句里的名字空间是一样的, 除非你使用了分组,这时候它和HAVING子句一样。

如果超过一个表有同样的字段名字,那么你还必须给出表名字,象

SELECT tbl1.a, tbl2.a, tbl1.b FROM ...

(又见 Section 7.2.2)。

如果将任意值表达式用于选择列表,那么它在概念上向返回的表中增加了一个新的虚拟字段。 值表达式为结果的每一行进行一次计算,计算之前用该行的数值代换任何表达式里引用的字段。 不过选择列表中的这个表达式并非一定要引用来自FROM子句中表表达式里面的字段, 比如,它也可以是任意常量算术表达式。
7.3.2. 字段标签

选择列表中的记录可以赋予名字,用于进一步的处理。 这里的"进一步处理"是一个可选的排序声明和客户端应用(比如,用于显示的字段头)。比如:

SELECT a AS value, b + c AS sum FROM ...

如果没有使用AS声明字段名字,那么系统赋予一个缺省值。对于简单的字段引用, 它是该字段的名字。对于函数调用,它是函数的名字。对于复杂表达式,系统会生成一个通用的名字。

    注意: 输出字段的命名和在FROM子句里的命名是不一样的 (参阅 Section 7.2.1.2)。 这个管道实际上允许你对同一个列命名两次,但是在选择列表中选择的名字是要传递的名字。

7.3.3. DISTINCT

在处理完选择列表之后,生成的表可以删除重复行。 我们可以直接在 SELECT 后面写上 DISTINCT 关键字声明:

SELECT DISTINCT select_list ...

(如果不用 DISTINCT 你可以用 ALL 声明保留所有行的缺省行为。)

显然,如果两行里至少有一个列有不同的值,那么我们认为它是独立的。空值在这种考虑中认为是相同的。

另外,我们还可以用任意表达式来判断什么行可以认为是独立的:

SELECT DISTINCT ON (expression [, expression ...]) select_list ...

这里 expression 是任意值表达式, 它为所有行计算。如果一个行集合里所有行计算出的该表达式的值是一样的, 那么我们认为它们是重复的并且因此只有第一行保留在输出中。 请注意这里的一个集合的"第一行"是不可预料的, 除非你在足够多的字段上对该查询排了序,保证到达DISTINCT过滤器的行的顺序是唯一的。 (DISTINCT ON处理是发生在ORDER BY排序后面的。)

DISTINCT ON子句不是 SQL 标准的一部分, 有时候有人认为它是一个糟糕的风格,因为它的结果是不可判定的。 如果用有选择的GROUP BY和在FROM中的子查询,那么我们可以避免使用这个构造, 但是通常它是更方便的候选方法。

TOP

7.4. 组合查询

两个查询的结果可以用集合操作并,交,差进行组合。语法是

query1 UNION [ALL] query2
query1 INTERSECT [ALL] query2
query1 EXCEPT [ALL] query2

query1 和 query2 都是可以使用我们到此为止讨论的所有查询特性的查询。集合操作也可以嵌套和级连,比如

query1 UNION query2 UNION query3

实际上说的是

(query1 UNION query2) UNION query3

UNION 有效地把 query2 的结果附加到 query1 的结果上(不过我们不能保证这就是这些行实际返回的顺序)并且删除结果中所有重复的行, 就象DISTINCT做的那样,除非你声明了UNION ALL。

INTERSECT 返回那些同时存在于 query1 的结果中和 query2的结果中的行,除非声明了INTERSECT ALL, 否则所有重复行都被删除。

EXCEPT 返回所有在 query1 的结果中但是不在 query2 的结果中的行。 (有时侯这叫做两个查询的差。) 除非声明了 EXCEPT ALL,否则所有重复行都被删除。

为了计算两个查询的并,交,差,这两个查询必须是"并集兼容的",也就意味着它们都返回同样数量的列, 并且对应的列有兼容的数据类型,象 Section 10.5 里描述的那样。

TOP

7.5. 行排序

在一个查询生成一个输出表之后(在处理完选择列表之后), 你还可以对它进行排序。如果没有选择排序,那么行将以未声明的顺序返回。 这时候的实际顺序将取决于扫描和连接规划类型和在磁盘上的顺序,但是肯定不能依赖这些东西。 一定的顺序只能在明确地使用了排序步骤之后才能保证。

ORDER BY子句声明了排序顺序

SELECT select_list
        FROM table_expression
        ORDER BY column1 [ASC | DESC] [, column2 [ASC | DESC] ...]

column1,等指向选择列表: 它可以是一个列的名字(可以是明确的列标签也可以是缺省名字,象 Section 7.3.2 里解释的那样) 或者是一个列的编号。一些例子:

SELECT a, b FROM table1 ORDER BY a;
SELECT a + b AS sum, c FROM table1 ORDER BY sum;
SELECT a, sum(b) FROM table1 GROUP BY a ORDER BY 1;

作为对标准 SQL 的扩展,PostgreSQL 还允许对任意表达式进行排序:

SELECT a, b FROM table1 ORDER BY a + b;

还允许引用 FROM 子句中的字段名,但是没有出现在选择列表中的字段名字:

SELECT a FROM table1 ORDER BY b;

但是这个特性在涉及UNION,INTERSECT,或 EXCEPT的查询中是不能用的,而且也不可移植到其它 DBMS。

声明的每个字段都可以跟着一个可选的ASC或DESC 以设置排序方向。 缺省是ASC。升序先输出小的数值,这里的"小"是以 < 操作符的角度定义的。类似的是, 降序是以 > 操作符来判断的。

如果声明了多于一个排序列,那么在前面的排序字段排序相等的情况下使用后面的排序项做进一步排序。

TOP

7.6. LIMIT 和 OFFSET

附加上 LIMIT和OFFSET 子句之后,你就可以检索原来查询语句查询出来的结果中的一部分数据行:

SELECT select_list
        FROM table_expression
        [LIMIT { number | ALL }] [OFFSET number]

如果给出了一个限制计数,那么返回不超过那么多的行。 (但可能更少些,因为查询本身可能生成的行数就比较少。) LIMIT ALL和省略 LIMIT子句一样。

OFFSET说明在开始返回行之前忽略多少行。 OFFSET 0和省略OFFSET子句是一样的。 如果OFFSET和LIMIT都出现了, 那么在计算LIMIT个行之前忽略OFFSET行。

如果使用LIMIT,那么用ORDER BY 子句把结果行约束成一个唯一的顺序是一个好主意。 否则你就会拿到一个不可预料的该查询的行的子集。 — 你要的可能是第十到二十行,但以什么顺序的十到二十? 除非你声明了ORDER BY,否则顺序是不知道的。

查询优化器在生成查询规划的时候会考虑LIMIT,因此如果你给 LIMIT和OFFSET不同的东西,那么你很可能收到不同的规划(产生不同的行顺序)。 因此,使用不同的LIMIT/OFFSET值选择不同的查询结果的子集将生成不一致的结果, 除非你用ORDER BY强制一个可预料的顺序。这可不是臭虫; 这是一个很自然的结果,因为 SQL 没有许诺把查询的结果按照任何特定的顺序发出,除非用了ORDER BY来约束顺序。

OFFSET 子句忽略的行仍然需要在服务器内部计算;因此,一个很大的 OFFSET 可能还是不够有效率的。

TOP

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。 下面的几节详细描述这些类型。
8.1.1. 整数类型

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

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

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

SQL只声明了整数类型 integer(或int)和 smallint。类型 bigint,和类型名 int2,int4,和 int8 都是扩展, 也在许多其它 SQL 数据库系统中使用。
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 值范围。

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 以前,太长的字串总会被不声不响地咔喳掉, 而且不会生成错误。不管是明确的还是隐含的转换情况下。

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 20.2。

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

逃逸"不可打印"字节的要求因区域设置而异。在某些场合下,你可以不逃逸它们。 请注意Table 8-7里的每个例子都是刚好一个字节长,虽然字节零和反斜杠输出形式比一个字符要长。

你必须写这么多反斜杠的原因,如 Table 8-7 所示, 是因为一个写成字串文本的输入字串必须通过 PostgreSQL 服务器里的两个分析阶段。 每个反斜杠对的第一个反斜杠会被字串文本分析其理解成一个逃逸字符而消耗掉, 剩下反斜杠对中的第二个。剩下的反斜杠被 bytea 输入函数当作一个三位八进制值或者是逃逸另外一个反斜杠的开始。 比如,一个传递给服务器的字串文本 '\\001' 在通过字串分析器之后会成为 \001。而 \001 则发送给 bytea 输入函数,在这里它被转换成一个十进制值为 1 的单个字节。请注意,省略字符不会被 bytea 特殊对待, 因此它遵循字串文本的普通规则。(又见 Section 4.1.2.1。)

Bytea 字节也在输出中逃逸的。通常, 每个"不可打印"的字节值都转化成对应的前导反斜杠的三位八进制数值。 大多数"可打印的"字节值是以客户端字符集的标准表现形式出现的。 十进制值为 92 (反斜杠)的字节有一个特殊的可选输出形式。细节在 Table 8-8 里描述。

Table 8-8. bytea 输出逃逸序列
字节的十进制值        描述        逃逸的输出形式        例子        输出结果
92         反斜杠         \\         select '\\134'::bytea;         \\
0 到 31 和 127 到 255         "不可打印"八进制字符        \xxx(octal value)         select '\\001'::bytea;         \001
32 到 126         "可打印"八进制字符        客户端字符集表现形式         select '\\176'::bytea;         ~

根据你使用的前端的不同,在逃不逃逸 bytea 字串的问题上你可能有一些额外的工作要做。 比如,如果你的接口自动转换进行(发音:hang)和回车,那你可能还要逃逸它们。

SQL 标准定义了一种不同的二进制字串类型, 叫做 BLOB 或者 BINARY LARGE OBJECT。 期输入格式和 bytea 不同,但是提供的函数和操作符大多一样。

TOP

8.5. 日期/时间类型

PostgreSQL 支持 SQL 中所有的日期和时间类型。 在 Table 8-9 中显示。 这些数据类型上可以进行的操作在 Section 9.9 描述。

Table 8-9. 日期/时间类型
名字        存储空间        描述        最低值        最高值        分辨率
timestamp [ (p) ] [without time zone]        8 字节        包括日期和时间        4713 BC        5874897 AD        1 毫秒 / 14 位
timestamp [ (p) ] with time zone        8 字节        日期和时间,带时区        4713 BC        5874897 AD        1 毫秒 / 14 位
interval [ (p) ]        12 字节        时间间隔        -178000000 年        178000000 年        1 毫秒
date        4 字节        只用于日期        4713 BC        32767 AD        1 天
time [ (p) ] [ without time zone ]        8 字节        只用于一日内时间        00:00:00.00        23:59:59.99        1 毫秒
time [ (p) ] with time zone        只用于一日内时间,带时区        12 字节        00:00:00.00+12        23:59:59.99-12        1 毫秒

    注意: 在 PostgreSQL 7.3 以前,只写 timestamp 等效于 timestamp with time zone。 这样是为了和 SQL 兼容。

time ,timestamp 和interval 接受一个可选的精度值 p,这个精度值声明在秒域后面小数点之后保留的位数。 缺省的时候在精度上是没有明确的绑定的, p 有用的范围对 timestamp和 interval 是从 0 到大约 6。

    注意: 如果 timestamp 数值是以双精度浮点数(目前的缺省)的方式存储的, 那么精度的有效限制会小于 6。 timestamp 值是以 2000-01-01 午夜之前或之后以来的秒数存储的,而微秒的精度是为那些在 2000-01-01 前后几年的日期实现的, 对于那些远一些的日子,精度会下降。如果 timestamp 以八字节整数存储(一个编译时的选项),那么微秒的精度就可以在数值的全部范围内都可以获得。 不过,八位整数的时间戳的日期范围缩小到 4713 BC 到 294276 AD。

对于 time 类型,如果使用了八字节的整数存储,那么 p 允许的范围是从 0 到 6,如果使用的是浮点数存储,那么这个范围是 0 到 10。

类型time with time zone是 SQL 标准定义的, 但是整个定义有些方面会导致有问题的用法。在大多数情况下, date,time,timestamp without time zone 和 timestamp with time zone 的组合就应该能提供提供任何应用需要的日期/时间的完整功能。

类型 abstime 和 reltime 是低分辨率类型,它们被用于系统内部。 我们不鼓励你在新的应用里面使用这些类型,同时我们支持合适的时候把旧应用中对应的类型转换成目前上面指明的。 因为这些旧类型的部分或全部可能会在未来的版本里消失。
8.5.1. 日期/时间输入

日期和时间的输入几乎可以是任何合理的格式,包括 ISO 8601,SQL-兼容的, 传统 POSTGRES 的和其他的形式。 对于一些格式,日期输入里的月份和日子输入可能会让人模糊, 因此系统支持声明自己预期的这些字段的顺序。 把 DateStyle 参数设置为 MDY, 就是“月-日-年”的解析,设置为 DMY 就是 “日-月-年”,而 YMD 是 “年-月-日”。

PostgreSQL 在处理日期/时间输入上比 SQL 标准要求的更灵活。 参阅 Appendix B 获取关于日期/时间输入的准确的分析规则和可识别文本字段,包括月份,星期几,和时区。

请记住任何日期或者时间的文本输入需要由单引号包围, 就象一个文本字符串一样。 参考 Section 4.1.2.5 获取更多信息。SQL 要求下面的语法

type [ (p) ] 'value'

在这里可选的精度声明中的 p 是一个整数, 对应在秒域中小数部分的位数, 我们可以对 time, timestamp,和 interval 类型声明精度。 允许的精度在上面已经说明。如果在常量声明中没有声明精度,缺省是文本值的精度。
8.5.1.1. 日期

Table 8-10 显示了 date 类型可能的输入方式。

Table 8-10. 日期输入
例子        描述
January 8, 1999        在任何datestyle输入模式下都无歧义
1999-01-08        ISO-8601 格式,任何方式下都是199年1月8号,(建议格式)
1/8/1999        歧义,在MDY下是一月八号;在 DMY 模式下读做八月一日
1/18/1999        在MDY模式下读做一月十八日,其它模式下被拒绝
01/02/03        MDY 模式下的2003年一月2日; DMY 模式下的 2003 年 2月 1日; YMD 模式下的2001年二月三日;
1999-Jan-08        任何模式下都是一月8日
Jan-08-1999        任何模式下都是一月8日
08-Jan-1999        任何模式下都是一月8日
99-Jan-08        在 YMD 模式下是一月8日,否则错误
08-Jan-99        一月八日,除了在 YMD 模式下是错误的之外
Jan-08-99        一月八日,除了在 YMD 模式下是错误的之外
19990108        ISO-8601; 任何模式下都是1999年1月8日
990108        ISO-8601; 任何模式下都是1999年1月8日
1999.008        年和年里的第几天
J2451187        儒略日
January 8, 99 BC        公元前99年

TOP


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

Designed By 17DST