8.1. 數字類型
數字類型由2、4或8位元組的整數以及4或8位元組的浮點數和可選精度小數組成。
表 8.2列出了所有可用類型。
表 8.2. 數字類型
名字 | 存儲尺寸 | 描述 | 範圍 |
---|---|---|---|
| 2位元組 | 小範圍整數 | -32768 to +32767 |
| 4位元組 | 整數的典型選擇 | -2147483648 to +2147483647 |
| 8位元組 | 大範圍整數 | -9223372036854775808 to +9223372036854775807 |
| 可變 | 使用者指定精度,精确 | 最高小數點前131072位,以及小數點後16383位 |
| |||
| 可變精度,不精确 | 6位十進制精度 | |
| 15位十進制精度 | ||
| 自動增加的小整數 | 1到32767 | |
| 自動增加的整數 | 1到2147483647 | |
| 自動增長的大整數 | 1到9223372036854775807 |
數字類型常量的文法在
第 4.1.2 節裡描述。數字類型有一整套對應的數學操作符和函數。相關資訊請參考
第 9 章。下面的幾節較長的描述這些類型。
8.1.1. 整數類型
類型
smallint
、
integer
和
bigint
存儲各種範圍的全部是數字的數,也就是沒有小數部分的數字。試圖存儲超出範圍以外的值将導緻一個錯誤。
常用的類型是
integer
,因為它提供了在範圍、存儲空間和性能之間的最佳平衡。一般隻有在磁盤空間緊張的時候才使用
smallint
類型。而隻有在
integer
的範圍不夠的時候才使用
bigint
。
SQL隻聲明了整數類型
integer
(或
int
)、
smallint
bigint
。類型
int2
int4
int8
都是擴充,也在許多其它SQL資料庫系統中使用。
8.1.2. 任意精度數字
numeric
可以存儲非常多位的數字。我們特别建議将它用于貨币金額和其它要求計算準确的數量。
numeric
值的計算在可能的情況下會得到準确的結果,例如加法、減法、乘法。不過,
numeric
類型上的算術運算比整數類型或者下一節描述的浮點數類型要慢很多。
在随後的内容裡,我們使用了下述術語:一個
numeric
的比例是到小數部分的位數,
numeric
的精度是整個數字裡全部位的數目,也就是小數點兩邊的位數目。是以數字 23.5141 的精度為6而比例為4。你可以認為整數的比例為零。
numeric
列的最大精度和最大比例都是可以配置的。要聲明一個類型為
numeric
的列,你可以用下面的文法:
NUMERIC(precision, scale)
精度必須為正數,比例可以為零或者正數。另外:
NUMERIC(precision)
選擇比例為 0 。如果使用
NUMERIC
建立一個列時不使用精度或比例,則該列可以存儲任何精度和比例的數字值,并且值的範圍最多可以到實作精度的上限。一個這種列将不會把輸入值轉化成任何特定的比例,而帶有比例聲明的
numeric
列将把輸入值轉化為該比例(SQL标準要求預設的比例是 0,即轉化成整數精度。我們覺得這樣做有點沒用。如果你關心移植性,那你最好總是顯式聲明精度和比例)。
注意
顯式指定類型精度時的最大允許精度為 1000,沒有指定精度的
NUMERIC
受到
中描述的限制所控制。
如果一個要存儲的值的比例比列聲明的比例高,那麼系統将嘗試圓整(四舍五入)該值到指定的分數位數。 然後,如果小數點左邊的位數超過了聲明的精度減去聲明的比例,那麼抛出一個錯誤。
數字值在實體上是以不帶任何前導或者字尾零的形式存儲。 是以,列上聲明的精度和比例都是最大值,而不是固定配置設定的 (在這個方面,
numeric
類型更類似于
varchar(
n
)
, 而不像
char(
n
)
)。 實際存儲要求是每四個十進制位組用兩個位元組, plus three to eight bytes overhead.
除了普通的數字值之外,
numeric
類型允許特殊值
NaN
, 表示“不是一個數字”。任何在
NaN
上面的操作都生成另外一個
NaN
。 如果在 SQL 指令裡把這些值當作一個常量寫,你必須在其周圍放上單引号,例如
UPDATE table SET x = 'NaN'
。在輸入時,字串
NaN
被識别為大小寫無關。
在“不是一個數字”概念的大部分實作中,
NaN
被認為不等于任何其他數字值(包括
NaN
)。為了允許
numeric
值可以被排序和使用基于樹的索引,PostgreSQL把
NaN
值視為相等,并且比所有非
NaN
值都要大。
decimal
numeric
是等效的。兩種類型都是SQL标準的一部分。
在對值進行圓整時,
numeric
類型會圓到遠離零的整數,而(在大部分機器上)
real
double precision
類型會圓到最近的偶數上。例如:
SELECT x,
round(x::numeric) AS num_round,
round(x::double precision) AS dbl_round
FROM generate_series(-3.5, 3.5, 1) as x;
x | num_round | dbl_round
------+-----------+-----------
-3.5 | -4 | -4
-2.5 | -3 | -2
-1.5 | -2 | -2
-0.5 | -1 | -0
0.5 | 1 | 0
1.5 | 2 | 2
2.5 | 3 | 2
3.5 | 4 | 4
(8 rows)
8.1.3. 浮點類型
資料類型
real
double precision
是不準确的、變精度的數字類型。實際上,這些類型是IEEE标準 754 二進制浮點算術(分别對應單精度和雙精度)的一般實作, 一直到下層處理器、作業系統和編譯器對它的支援。
不準确意味着一些值不能準确地轉換成内部格式并且是以近似的形式存儲的,是以存儲和檢索一個值可能出現一些缺失。 處理這些錯誤以及這些錯誤是如何在計算中傳播的主題屬于數學和計算機科學的一個完整的分支, 我們不會在這裡進一步讨論它,這裡的讨論僅限于如下幾點:
- 如果你要求準确的存儲和計算(例如計算貨币金額),應使用
類型。numeric
- 如果你想用這些類型做任何重要的複雜計算,尤其是那些你對範圍情況(無窮、下溢)嚴重依賴的事情,那你應該仔細評诂你的實作。
- 用兩個浮點數值進行等值比較不可能總是按照期望地進行。
在大部分平台上,
real
類型的範圍是至少 -1E+37 到 +1E+37,精度至少是 6 位小數。
double precision
類型通常有 -1E+308 到 +1E+308 的範圍,精度是至少 15 位數字。太大或者太小的值都會導緻錯誤。 如果輸入數字的精度太高,那麼可能發生園整。太接近零的數字,如果無法與零值的表現形式相區分就會産生下溢錯誤。
extra_float_digits
設定控制當一個浮點值被轉換為文本輸出時要包括的額外有效數字的數目。其預設值為
,在每一個PostgreSQL支援的平台上輸出都相同。增加該設定将産生能更精确表示存儲值的輸出,但是可能無法移植。
除了普通的數字值之外,浮點類型還有幾個特殊值:
Infinity
-Infinity
NaN
這些值分别表示 IEEE 754 特殊值“正無窮大”、“負無窮大”以及“不是一個數字”(在不遵循 IEEE 754 浮點算術的機器上,這些值的含義可能不是預期的)。如果在 SQL 指令裡把這些數值當作常量寫,你必須在它們周圍放上單引号,例如
UPDATE table SET x = '-Infinity
。 在輸入時,這些串是以大小寫無關的方式識别的。
IEEE754指定
NaN
不應該與任何其他浮點值(包括
NaN
)相等。為了允許浮點值被排序或者在基于樹的索引中使用,PostgreSQL将
NaN
NaN
值要更大。
PostgreSQL還支援 SQL 标準表示法
float
float(
p
)
用于聲明非精确的數字類型。在這裡,
p
指定以二進制位表示的最低可接受精度。 在選取
real
類型的時候,PostgreSQL接受
float(1)
到
float(24)
,在選取
double precision
的時候,接受
float(25)
float(53)
。在允許範圍之外的
p
值将導緻一個錯誤。沒有指定精度的
float
将被當作是
double precision
認為
real
double precision
分别有 24 和 53 個二進制位的假設對 IEEE 标準的浮點實作來說是正确的。在非 IEEE 平台上,這個數值可能略有偏差,但是為了簡化,我們在所有平台上都用了同樣的
p
值範圍。
8.1.4. 序數類型
本節介紹了一種建立自動增量列的PostgreSQL特定方法。另一種方法是使用
CREATE TABLE中描述的SQL标準辨別列功能。
smallserial
serial
bigserial
類型不是真正的類型,它們隻是為了建立唯一辨別符列而存在的友善符号(類似其它一些資料庫中支援的
AUTO_INCREMENT
屬性)。 在目前的實作中,下面一個語句:
CREATE TABLE tablename (
colname SERIAL
);
等價于以下語句:
CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
是以,我們就建立了一個整數列并且把它的預設值安排為從一個序列發生器取值。應用了一個
NOT NULL
限制以確定空值不會被插入(在大多數情況下你可能還希望附加一個
UNIQUE
或者
PRIMARY KEY
限制避免意外地插入重複的值,但這個不是自動發生的)。最後,該序列被标記為“屬于”該列,這樣當列或表被删除時該序列也會被删除。
因為
smallserial
serial
bigserial
是用序列實作的,是以即使沒有删除過行,在出現在列中的序列值可能有“空洞”或者間隙。如果一個從序列中配置設定的值被用在一行中,即使該行最終沒有被成功地插入到表中,該值也被“用掉”了。例如,當插入事務復原時就會發生這種情況。更多資訊參見
第 9.16 節中的
nextval()
要使用
serial
列插入序列的下一個數值到表中, 請指定
serial
列應該被賦予其預設值。我們可以通過在
INSERT
語句中把該列排除在列清單之外來實作,也可以通過使用
DEFAULT
關鍵字來實作。
類型名
serial
serial4
是等效的: 兩個都建立
integer
列。類型名
bigserial
serial8
也一樣,隻不過它們建立一個
bigint
列。如果你預計在表的生存期中使用的辨別符數目超過 231個,那麼你應該使用
bigserial
。類型名
smallserial
serial2
也以相同方式工作,隻不過它們建立一個
smallint
列。
為一個
serial
列建立的序列在所屬的列被删除的時候自動删除。你可以在不删除列的情況下删除序列,但是這會強制删除該列的預設值表達式。
本文轉自PostgreSQL中文社群,原文連結: