数字数据类型
PostgreSQL的数字数据类型比我们现在为止遇到的类型都稍复杂,但是它们也不是特别难理解。我们可以存储两类不同的数字到数据库中,整数和浮点数字。再细分,整数类型有一些子类型,包括serial类型(我们已经使用过,用于在一个表中建立一个唯一的值)和不同大小的整数,如表8-3所示。
表8-3 PostgreSQL整数数据类型
浮点数据也可以再细分,分为提供通用功能的浮点值和固定精度的数字,如表8-4所示。
表8-4 PostgreSQL浮点数据类型
被分成整数和浮点数据这两类的原因很容易理解,但numeric类型的用途不太明显。
浮点数据以科学计数法方式,使用尾数和幂存储。对于numeric类型,你可以在执行计算时同时指出精度和准确的存储的数字。你还可以指出小数点后的数字个数。实际的小数点位置变得非常自由了!
警告:最常见的错误时认为numeric(5,2)可以存储一个类似于12345.12的数字。这是错误的。在这里头存储的总归数字个数只有五个,所以定义为numeric(5,2)的数字在溢出前最大只能存储999.99。
PostgreSQL一般会捕捉对无法存储到字段中的值的插入,所以尝试插入很大的数字到任何类型的数字列将失败。
尝试:使用数字类型
现在,我们可以实验数字数据类型。首先,我们需要删除我们的testtype表,然后使用一些不同的列类型来重新建立它:
test=> DROP TABLE testtype;
DROP TABLE
test=> CREATE TABLE testtype (
test(> asmallint smallint,
test(> anint int,
test(> afloat float(2),
test(> areal real,
test(> anumeric numeric(5,2)
test(> );
CREATE TABLE
test=> INSERT INTO testtype VALUES(2, 2, 2.0, 2.0, 2.0);
INSERT 17883 1
test=> INSERT INTO testtype VALUES(-100, -100, 123.456789, 123.456789, 123.456789);
INSERT 17884 1
test=> INSERT INTO testtype VALUES(-32768, -123456789, 1.23456789,
test-> 1.23456789, 1.23456789);
INSERT 17885 1
test=> INSERT INTO testtype VALUES(-32768, -123456789, 123456789.123456789,
test-> 23456789.123456789, 123456789.123456789);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^8 for field with
precision 5, scale 2.
test=>
test=> INSERT INTO testtype VALUES(-32768, -123456789, 123456789.123456789,
test-> 123456789.123456789, 123.123456789);
INSERT 17886 1
test=>
test=> SELECT * FROM testtype;
asmallint | anint | afloat | areal | anumeric
———–+————+————–+————–+———-
2 | 2 | 2 | 2 | 2.00
-100 | -100 | 123.457 | 123.457 | 123.46
-32768 | -123456789 | 1.23457 | 1.23457 | 1.23
-32768 | -123456789 | 1.23457e+008 | 1.23457e+008 | 123.12
(4 rows)
test=>
解析
我们建立了一个表,包含一个短整数列,一个普通整数列,一个浮点数字列,一个实数列,一个精度为5,小数点后为2的数字列。
你会发现float和real类型的行为非常相似,但是numeric列的行为有点不同。Numeric类型不是存储接近的数,而是在小数后面进行后超出固定长度的部分进行四舍五入。如果我们存储太大的数据到其中,INSERT将失败。还要注意float和real也会对数字四舍五入;例如123.456789被四舍五入为123.457。
时间型数据类型
时间型数据类型存储和时间相关的信息,在第四章,我们看到了如何控制数据的格式。PostgreSQL有一系列的与日期和时间相关的类型,如表8-5所示,但是我们在本书中通常只限制于SQL92标准的类型。
表8-5 PostgreSQL的时间数据类型
由于PostgreSQL源于一个用于研究的数据库系统,PostgreSQL拥有一些少见的数据类型用于存储几何和网络数据类型,如表8-6所示。使用PostgreSQL的这些任何一种特殊功能都会使一个Postgresql数据库的可移植性变得非常的差,所以通常,我们趋向于避免这些扩展。要获得更多的关于这些类型的信息,查询PostgreSQL的文档,在“数据类型”部分。
表8-5 PostgreSQL的特殊数据类型
注:PostgreSQL也允许你使用SQL命令CREATE TYPE在数据库中建立你自己的类型。这通常不需要,而且在一定程度上,它是PostgreSQL独有的。更多的信息可以在官方文档中找到。注意建立你自己的类型可能导致数据库的模式非常限于PostgreSQL中使用,因为用户自定义类型无法被移植。
数组
PostgreSQL有另一个独特的功能:能够在表中存储数组。在SQL99标准之前,这不是一个标准的功能,所以在数据库实践中很少见。通常,一个数组需要通过使用一个附加表实现。但是,数组的能力有时候很有用,特别是当你需要存储固定数量的重复元素时,而且它非常容易使用。
建立数组的方法有两种:传统的PostgreSQL的方法和SQL99标准的方法。我们在这里会简单介绍这两种方法。
PostgreSQL样式的数组
要将一个表的列定义为数组,你可以简单地在类型后面添加[];不需要定义元素的个数。如果你使用了大小来定义,PostgreSQL接受你的定义,但它不强制接受指定数量的元素。
尝试:使用PostgreSQL语法定义数组
作为一个示例,假设我们决定要有一个雇员表,表中要包含一个指示他们工作日的指示器。通常,我们需要为每一天分配一个列,或者一个单独的表来储存工作日。在PostgreSQL中,我们可以简化这个工作,直接存储工作日的数组,就像这样:
test=> CREATE TABLE empworkday (
test(> refcode char(5),
test(> workdays int[]
test(> );
CREATE TABLE
test=>
这建立了一个有两个列的empworkday表:一个参考字符串以及一个叫做workdays的整数数组。要网数组列中插入值,我们需要用大括号分隔符包围由逗号分割的值的列表,就像这样:
test=> INSERT INTO empworkday VALUES(‘val01′, ‘{0,1,0,1,1,1,1}’);
INSERT 17892 1
test=> INSERT INTO empworkday VALUES(‘val02′, ‘{0,1,1,1,1,0,1}’);
INSERT 17893 1
test=>
我们可以一次性选择数组元素的所有值,就像这样:
test=> SELECT * FROM empworkday;
refcode | workdays
———+—————–
val01 | {0,1,0,1,1,1,1}
val02 | {0,1,1,1,1,0,1}
(2 rows)
test=>
我们也可以通过给出数组的索引值来取出单个元素:
test=> SELECT workdays[2] FROM empworkday WHERE refcode = ‘val02′;
workdays
———-
1
(1 row)
test=>
解析
PostgreSQL的行为很像传统的编程语言,存储一个数组的值,甚至还有不需要指出数组的大小的好处。如果你选择整个数组,PostgreSQL显示在花括号之间的所有的用逗号分隔的值。
有一个需要注意的事情是PostgreSQL的数组中第一个元素的索引值是1而不是0,而很多编程语言通常是0.如果你尝试选择一个不存在的数组元素,将返回NULL。
注:PostgreSQL也允许多维数组。要知道更多PostgreSQL关于数组的内容,请参考文档。
SQL99样式的数字
在SQL99标准中,新的数组定义语法被提出。这比PostgreSQL样式更明确的一种语法,必须指出元素的个数,而PostgreSQL在实现时是不强制执行这个标准的。
尝试:使用SQL99语法的数组
让我们定义我们早前的表,使用SQL99样式的定义来做实验:
test=> DROP TABLE empworkday;
DROP TABLE
test=> CREATE TABLE empworkday (
test(> refcode char(5),
test(> workdays int array[7]
test(> );
CREATE TABLE
test=> INSERT INTO empworkday VALUES(‘val01′, ‘{0,1,0,1,1,1,1}’);
INSERT 17899 1
test=> INSERT INTO empworkday VALUES(‘val02′, ‘{0,1,1,1,1,0,1}’);
INSERT 17900 1
test=>
test=> SELECT * FROM empworkday;
refcode | workdays
———+—————–
val01 | {0,1,0,1,1,1,1}
val02 | {0,1,1,1,1,0,1}
(2 rows)
test=>
test=> SELECT workdays[2] FROM empworkday WHERE refcode = ‘val02′;
workdays
———-
1
(1 row)
test=>
解析
就像你看到的,SQL99样式的数组和PostgreSQL样式的数组基本一样。唯一的不同是定义的语法有点不同。
本文转自: http://www.mysqlops.com/2012/05/06/postgresql-date-type-3.html