本文介紹了數字類型的定義及相關語法。
數字類型
名字 | 存儲尺寸 | 說明 | 范圍 |
| 2字節 | 小范圍整數。 | -32768 to +32767 |
| 4字節 | 整數的典型選擇。 | -2147483648 to +2147483647 |
| 8字節 | 大范圍整數。 | -9223372036854775808 to +9223372036854775807 |
| 可變 | 用戶指定精度,精確。 | 最高小數點前131072位,以及小數點后16383位 |
| 可變 | 用戶指定精度,精確。 | 最高小數點前131072位,以及小數點后16383位 |
| 4字節 | 可變精度,不精確。 | 6位十進制精度 |
| 8字節 | 可變精度,不精確。 | 15位十進制精度 |
| 2字節 | 自動增加的小整數。 | 1到32767 |
| 4字節 | 自動增加的整數。 | 1到2147483647 |
| 8字節 | 自動增長的大整數。 | 1到9223372036854775807 |
BINARY_INTEGER | 4字節 | 有符號整數,integer的別名。 | -2,147,483,648 到+2,147,483,647 |
NUMBER | 可變 | 用戶指定的精度,精確。 | 最高1000位十進制精度 |
NUMBER(p [, s ] ) | 可變 | 最大精度p和可選刻度s的精確數字。 | 最高1000位十進制精度 |
PLS_INTEGER | 4字節 | 有符號整數,integer的別名。 | -2,147,483,648 到 +2,147,483,647 |
ROWID | 8字節 | 帶符號的8位整數。 | -9223372036854775808 到9223372036854775807 |
整數類型
類型smallint
、integer
和bigint
存儲各種范圍的全部是數字的數,也就是沒有小數部分的數字。試圖存儲超出范圍以外的值將導致一個錯誤。
常用的類型是integer
,因為它提供了在范圍、存儲空間和性能之間的最佳平衡。一般只有在磁盤空間緊張的時候才使用 smallint
類型。而只有在integer
的范圍不夠的時候才使用bigint
。
SQL 只聲明了整數類型integer
(或int
)、smallint
和bigint
。類型int2
、int4
和int8
都是擴展,也在許多其它 SQL 數據庫系統中使用。
任意精度數字
類型numeric
可以存儲非常多位的數字。我們特別建議將它用于貨幣金額和其它要求計算準確的數量。numeric
值的計算在可能的情況下會得到準確的結果,例如加法、減法、乘法。不過,numeric
類型上的算術運算比整數類型或者下一節描述的浮點數類型要慢很多。
在隨后的內容里,我們使用了下述術語:一個numeric
的precision(精度)是整個數中有效位的總數,也就是小數點兩邊的位數。numeric
的scale(刻度)是小數部分的數字位數,也就是小數點右邊的部分。因此數字 23.5141 的精度為 6 而刻度為 4??梢哉J為整數的刻度為零。
numeric
列的最大精度和最大比例都是可以配置的。要聲明一個類型為numeric
的列,你可以用下面的語法:
NUMERIC(precision, scale)
精度必須為正數,比例可以為零或者正數。另外:
NUMERIC(precision)
選擇比例為 0 。如果使用
NUMERIC
創建一個列時不使用精度或比例,則該列可以存儲任何精度和比例的數字值,并且值的范圍最多可以到實現精度的上限。一個這種列將不會把輸入值轉化成任何特定的比例,而帶有比例聲明的numeric
列將把輸入值轉化為該比例(SQL 標準要求缺省的比例是 0,即轉化成整數精度。我們覺得這樣做有點沒用。如果你關心移植性,那你最好總是顯式聲明精度和比例)。
顯式指定類型精度時的最大允許精度為 1000,沒有指定精度的NUMERIC
受到數字類型的限制所控制。
如果一個要存儲的值的比例比列聲明的比例高,那么系統將嘗試圓整(四舍五入)該值到指定的分數位數。 然后,如果小數點左邊的位數超過了聲明的精度減去聲明的比例,那么拋出一個錯誤。
數字值在物理上是以不帶任何前導或者后綴零的形式存儲。 因此,列上聲明的精度和比例都是最大值,而不是固定分配的 (在這個方面,numeric
類型更類似于varchar(``n``)
, 而不像char(``n``)
)。 實際存儲要求是每四個十進制位組用兩個字節,再加上三到八個字節的開銷。
除了普通的數字值之外,numeric
類型允許特殊值NaN
, 表示“不是一個數字”。任何在 NaN
上面的操作都生成另外一個NaN
。 如果在 SQL 命令里把這些值當作一個常量寫,你必須在其周圍放上單引號,例如UPDATE table SET x = 'NaN'
。在輸入時,字串NaN
被識別為大小寫無關。
在“不是一個數字”概念的大部分實現中,NaN
被認為不等于任何其他數字值(包括NaN
)。為了允許numeric
值可以被排序和使用基于樹的索引,本數據庫把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)
浮點類型
數據類型real
和double precision
是不精確的、變精度的數字類型。 在所有當前支持的平臺上,這些類型是 IEEE 標準 754 二進制浮點算術(分別對應單精度和雙精度)的實現, 一直到下層處理器、操作系統和支持它的編譯器。
不準確意味著一些值不能準確地轉換成內部格式并且是以近似的形式存儲的,因此存儲和檢索一個值可能出現一些缺失。 處理這些錯誤以及這些錯誤是如何在計算中傳播的主題屬于數學和計算機科學的一個完整的分支, 我們不會在這里進一步討論它,這里的討論僅限于如下幾點:
如果你要求準確的存儲和計算(例如計算貨幣金額),應使用
numeric
類型。如果你想用這些類型做任何重要的復雜計算,尤其是那些你對范圍情況(無窮、下溢)嚴重依賴的事情,那你應該仔細評詁你的實現。
用兩個浮點數值進行等值比較不可能總是按照期望地進行。
在所有當前支持的平臺上,real
類型的范圍是 1E-37 to 1E+37 ,精度至少是 6 位小數。 double precision
類型的范圍是 1E-307 to 1E+308 ,精度至少是 15 位數字。 太大或者太小的值都會導致錯誤。 如果輸入數字的精度太高,那么可能發生四舍五入。 太接近零的數字,如果不能體現出與零的區別就會導致下溢錯誤。
默認情況下,浮點值以其最短精確的十進制表示的文本形式輸出;所產生的十進制值與相同二進制精度的任何其他的值表示相比,更接近于真實存儲的二進制值。 (但是,當前輸出值永遠不會精確地處于兩個可表示的值之間,以免輸入程序不能正確遵守舍近取整法則。) 對于float8
值,此值最多使用 17 個有效十進制數字,對于float4
值,最多使用 9 個數字。
生成這種最短精確的輸出格式比歷史的四舍五入的格式要快得多。
為了與本數據庫的較舊版本生成的輸出兼容,并允許降低輸出精度,可以使用 extra_float_digits 參數選擇四舍五入的十進制輸出。 將值設置為 0 將恢復以前的默認值,即將值四舍五入為 6(對于float4
)或 15(對于float8
)個有效的十進制數字。 設置負值會進一步減少位數。 例如-2 會將輸出分別舍入到 4 或 13 位數字。
設置 extra_float_digits 位任何大于 0 的值將選擇最短精確格式。
需要更精確值的應用需要設置 extra_float_digits 為 3 以獲取更精確值。 為了版本之間的最大兼容性,他們可以繼續這樣做。
除了普通的數字值之外,浮點類型還有幾個特殊值:
Infinity
-Infinity
NaN
這些分別代表 IEEE 754 特殊值“infinity”、“negative infinity”以及“not-a-number”, 如果在 SQL 命令里把這些數值當作常量寫,你必須在它們周圍放上單引號,例如UPDATE table SET x = '-Infinity'
。 在輸入時,這些字符串是以大小寫不敏感的方式識別的。
IEEE754 指定NaN
不應該與任何其他浮點值(包括NaN
)相等。為了允許浮點值被排序或者在基于樹的索引中使用,本數據庫將NaN
值視為相等,并且比所有非NaN
值要更大。
本數據庫還支持 SQL 標準表示法float
和float(``p``)
用于聲明非精確的數字類型。在這里,p
指定以二進制位表示的最低可接受精度。 在選取real
類型的時候,本數據庫接受float(1)
到float(24)
,在選取double precision
的時候,接受float(25)
到float(53)
。在允許范圍之外的p
值將導致一個錯誤。沒有指定精度的float
將被當作是double precision
。
序數類型
這一節描述了 PostgreSQL 特有的創建一個自增列的方法。另一種方法是使用 SQL 標準的標識列特性,它在CREATE TABLE中描述。
smallserial
、serial
和bigserial
類型不是真正的類型,它們只是為了創建唯一標識符列而存在的方便符號(類似其它一些數據庫中支持的AUTO_INCREMENT
屬性)。 在目前的實現中,下面一個語句:
CREATE TABLE tablename (
colname SERIAL
);
等價于以下語句:
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
因此,我們就創建了一個整數列并且把它的缺省值安排為從一個序列發生器取值。應用了一個NOT NULL
約束以確??罩挡粫徊迦耄ㄔ诖蠖鄶登闆r下你可能還希望附加一個UNIQUE
或者PRIMARY KEY
約束避免意外地插入重復的值,但這個不是自動發生的)。最后,該序列被標記為“屬于”該列,這樣當列或表被刪除時該序列也會被刪除。
因為smallserial
、serial
和bigserial
是用序列實現的,所以即使沒有刪除過行,在出現在列中的序列值可能有“空洞”或者間隙。如果一個從序列中分配的值被用在一行中,即使該行最終沒有被成功地插入到表中,該值也被“用掉”了。例如,當插入事務回滾時就會發生這種情況。
要使用serial
列插入序列的下一個數值到表中, 請指定serial
列應該被賦予其缺省值。我們可以通過在INSERT
語句中把該列排除在列列表之外來實現,也可以通過使用DEFAULT
關鍵字來實現。
類型名serial
和serial4
是等效的: 兩個都創建integer
列。類型名bigserial
和serial8
也一樣,只不過它們創建一個 bigint
列。如果你預計在表的生存期中使用的標識符數目超過 231 個,那么你應該使用bigserial
。類型名smallserial
和serial2
也以相同方式工作,只不過它們創建一個smallint
列。
為一個serial
列創建的序列在所屬的列被刪除的時候自動刪除。你可以在不刪除列的情況下刪除序列,但是這會強制刪除該列的默認值表達式。