數值類型包含二、四和八位元組的整數,四和八位元組的浮點數,以及可選擇精度的十進位數。表 8.2 列出了可用的類型。
表 8.2. 數值類型
名稱 | 儲存大小 | 描述 | 範圍 |
---|---|---|---|
smallint |
2 位元組 | 小範圍整數 | -32768 到 +32767 |
integer |
4 位元組 | 整數的典型選擇 | -2147483648 到 +2147483647 |
bigint |
8 位元組 | 大範圍整數 | -9223372036854775808 到 +9223372036854775807 |
decimal |
可變 | 使用者指定的精度,精確 | 小數點前最多 131072 位數字;小數點後最多 16383 位數字 |
numeric |
可變 | 使用者指定的精度,精確 | 小數點前最多 131072 位數字;小數點後最多 16383 位數字 |
real |
4 位元組 | 可變精度,不精確 | 6 位十進位數字精度 |
double precision |
8 位元組 | 可變精度,不精確 | 15 位十進位數字精度 |
smallserial |
2 位元組 | 小型自動遞增整數 | 1 到 32767 |
serial |
4 位元組 | 自動遞增整數 | 1 到 2147483647 |
bigserial |
8 位元組 | 大型自動遞增整數 | 1 到 9223372036854775807 |
數值類型的常數語法在第 4.1.2 節中描述。數值類型有一整套相應的算術運算符和函數。有關更多訊息,請參閱第 9 章。以下章節詳細描述這些類型。
smallint
、integer
和 bigint
類型儲存整數,也就是沒有小數部分的數字,範圍各不相同。嘗試儲存超出允許範圍的值將導致錯誤。
integer
類型是常見的選擇,因為它在範圍、儲存大小和效能之間提供了最佳平衡。smallint
類型通常僅在磁碟空間有限時使用。bigint
類型設計用於 integer
類型的範圍不足時。
SQL僅指定整數類型 integer
(或 int
)、smallint
和 bigint
。類型名稱 int2
、int4
和 int8
是擴展,其他一些SQL資料庫系統也使用它們。
numeric
類型可以儲存具有非常多位數字的數字。特別建議用於儲存貨幣金額和其他需要精確度的數量。使用 numeric
值進行的計算在可能的情況下會產生精確的結果,例如,加法、減法、乘法。但是,與整數類型或下一節中描述的浮點類型相比,對 numeric
值進行的計算非常慢。
我們在下面使用以下術語:numeric
的精度是整個數字中有效數字的總數,也就是小數點兩側的數字數量。 numeric
的小數位數是小數部分中小數位數字的數量,即小數點右側的數字數量。因此,數字 23.5141 的精度為 6,小數位數為 4。整數可以被認為具有零的小數位數。
可以配置 numeric
欄位的最大精度和最大小數位數。若要宣告 numeric
類型的欄位,請使用以下語法
NUMERIC(precision
,scale
)
精度必須為正數,而小數位數可以為正數或負數(見下文)。或者
NUMERIC(precision
)
選擇小數位數 0。指定
NUMERIC
不帶任何精度或小數位數會建立一個“無限制的數值”欄位,其中可以儲存任何長度的數值,直到達到實作限制。這種欄位不會將輸入值強制轉換為任何特定的小數位數,而具有宣告小數位數的 numeric
欄位會將輸入值強制轉換為該小數位數。(SQL標準要求預設小數位數為 0,也就是強制轉換為整數精度。我們覺得這有點沒用。如果您擔心可移植性,請始終明確指定精度和小數位數。)
在 numeric
類型宣告中,可以明確指定的最大精度為 1000。未受限的 numeric
欄位會受到表 8.2中所述的限制。
如果要儲存的值的小數位數大於欄位宣告的小數位數,系統會將該值四捨五入到指定的小數位數。然後,如果小數點左側的位數超過宣告的精度減去宣告的小數位數,則會引發錯誤。例如,宣告為以下的欄位:
NUMERIC(3, 1)
會將值四捨五入到小數點後 1 位,並且可以儲存 -99.9 到 99.9(含)之間的值。
從 PostgreSQL 15 開始,允許宣告小數位數為負數的 numeric
欄位。然後,值將四捨五入到小數點的左側。精度仍然表示未四捨五入的最大位數。因此,宣告為以下的欄位:
NUMERIC(2, -3)
會將值四捨五入到最接近的千位數,並且可以儲存 -99000 到 99000(含)之間的值。也允許宣告大於宣告精度的刻度。這樣的欄位只能容納小數值,並且要求小數點右側的零位數至少為宣告的刻度減去宣告的精度。例如,宣告為以下的欄位:
NUMERIC(3, 5)
會將值四捨五入到小數點後 5 位,並且可以儲存 -0.00999 到 0.00999(含)之間的值。
PostgreSQL 允許 numeric
類型宣告中的小數位數為 -1000 到 1000 範圍內的任何值。但是,SQL標準要求小數位數在 0 到 precision
的範圍內。使用該範圍之外的刻度可能無法移植到其他資料庫系統。
數值在物理上儲存時,沒有任何額外的開頭或結尾零。因此,欄位的宣告精度和小數位數是最大值,而不是固定的分配。(從這個意義上講,numeric
類型更像是 varchar(
而不是 n
)char(
。)實際的儲存需求是每四個十進制數字一組需要兩個位元組,加上三到八個位元組的開銷。n
)
除了普通的數值之外,numeric
類型還有幾個特殊值:
Infinity(無限大)
-Infinity(負無限大)
NaN(非數字)
這些是從 IEEE 754 標準改編而來,分別代表“無限大”、“負無限大”和“非數字”。在 SQL 命令中將這些值寫為常數時,必須用引號將它們括起來,例如 UPDATE table SET x = '-Infinity'
。在輸入時,這些字串會以不區分大小寫的方式識別。無限大值也可以拼寫為 inf
和 -inf
。
無限大值的行為符合數學期望。例如,Infinity
加上任何有限值等於 Infinity
,Infinity
加上 Infinity
也是如此;但是 Infinity
減去 Infinity
會產生 NaN
(非數字),因為它沒有明確定義的解釋。請注意,無限大值只能儲存在未受限的 numeric
欄位中,因為它在概念上超過了任何有限的精度限制。
NaN
(非數字)值用於表示未定義的計算結果。通常,任何具有 NaN
輸入的運算都會產生另一個 NaN
。唯一的例外是當運算的其他輸入使得如果將 NaN
替換為任何有限或無限的數值時,會獲得相同的輸出;那麼,該輸出值也用於 NaN
。(此原則的一個例子是 NaN
的零次方產生 1。)
在大多數 “非數字” 概念的實作中,NaN
不被認為等於任何其他數值(包括 NaN
)。為了允許對 numeric
值進行排序並在基於樹的索引中使用,PostgreSQL 將 NaN
值視為相等,並且大於所有非 NaN
值。
decimal
和 numeric
類型是等效的。這兩種類型都是SQL標準的一部分。
在四捨五入值時,numeric
類型會將 ties away from zero(距離零最遠的值)四捨五入,而(在大多數機器上)real
和 double precision
類型會將 ties 四捨五入到最接近的偶數。例如:
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 到 1E+37,精度至少為 6 個十進制數字。double precision
類型的範圍約為 1E-307 到 1E+308,精度至少為 15 位數字。太大或太小的值將導致錯誤。如果輸入數字的精度太高,則可能會進行四捨五入。太接近零而無法與零區分的數字將導致下溢錯誤。
預設情況下,浮點數值以文本形式輸出,採用其最短的精確十進制表示形式;產生的十進制值比同一二進制精度中任何其他可表示的值更接近真實儲存的二進制值。(但是,為了避免輸入例程不能正確遵守 round-to-nearest-even 規則的廣泛錯誤,目前輸出值從不是 精確地 位於兩個可表示值的中間。)對於 float8
值,此值最多使用 17 個有效十進制數字,對於 float4
值,最多使用 9 個數字。
這種最短精確輸出格式比舊式的四捨五入格式產生速度快很多。
為了與舊版 PostgreSQL 產生的輸出相容,並允許降低輸出精度,可以使用 extra_float_digits 參數來選擇四捨五入的十進制輸出。將其值設為 0 會恢復先前的預設值,將值四捨五入到 6 位 (對於 float4
) 或 15 位 (對於 float8
) 有效數字。設定負值會進一步減少位數;例如 -2 會將輸出分別四捨五入到 4 位或 13 位數字。
任何大於 0 的 extra_float_digits 值都會選擇最短精確格式。
過去,想要精確值的應用程式必須將 extra_float_digits 設定為 3 才能獲得它們。為了在版本之間獲得最大的相容性,它們應該繼續這樣做。
除了普通的數值之外,浮點型別還有幾個特殊值
Infinity(無限大)
-Infinity(負無限大)
NaN(非數字)
這些分別代表 IEEE 754 特殊值 “infinity”、“negative infinity” 和 “not-a-number”。在 SQL 命令中將這些值寫為常數時,您必須用引號將它們括起來,例如 UPDATE table SET x = '-Infinity'
。在輸入時,這些字串會以不區分大小寫的方式識別。無限大值也可以拼寫為 inf
和 -inf
。
IEEE 754 規定 NaN
不應與任何其他浮點數值(包括 NaN
)進行比較。為了允許浮點數值進行排序並在基於樹狀結構的索引中使用,PostgreSQL 將 NaN
值視為相等,並且大於所有非 NaN
值。
PostgreSQL 也支援 SQL 標準表示法 float
和 float(
來指定不精確的數值型別。這裡,p
)p
指定了 二進制 位數中最小的可接受精度。PostgreSQL 接受 float(1)
到 float(24)
作為選擇 real
型別,而 float(25)
到 float(53)
選擇 double precision
。超出允許範圍的 p
值會產生錯誤。未指定精度的 float
被認為是指 double precision
。
本節介紹一種 PostgreSQL 特有的建立自動遞增欄位的方式。另一種方式是使用 SQL 標準身分欄位功能,詳情請參閱 第 5.3 節。
資料型別 smallserial
、serial
和 bigserial
並非真正的型別,而僅僅是為了方便建立唯一識別碼欄位(類似於某些其他資料庫支援的 AUTO_INCREMENT
屬性)。在目前的實作中,指定
CREATE TABLEtablename
(colname
SERIAL );
等同於指定
CREATE SEQUENCEtablename
_colname
_seq AS integer; CREATE TABLEtablename
(colname
integer NOT NULL DEFAULT nextval('tablename
_colname
_seq') ); ALTER SEQUENCEtablename
_colname
_seq OWNED BYtablename
.colname
;
因此,我們建立了一個整數欄位,並安排從序列產生器中分配其預設值。應用了 NOT NULL
限制,以確保無法插入 null 值。(在大多數情況下,您還需要附加 UNIQUE
或 PRIMARY KEY
限制,以防止意外插入重複值,但這不是自動的。)最後,該序列被標記為 “屬於” 該欄位,以便在刪除該欄位或資料表時將其刪除。
由於 smallserial
、serial
和 bigserial
是使用序列實作的,因此即使從未刪除任何列,欄位中出現的值序列中也可能存在「漏洞」或間隙。即使包含該值的列從未成功插入資料表欄位,從序列中分配的值仍然會被「用完」。例如,如果插入交易回滾,則可能會發生這種情況。有關詳細資訊,請參閱 第 9.17 節中的 nextval()
。
要將序列的下一個值插入到 serial
欄位中,請指定應將 serial
欄位分配給其預設值。這可以通過從 INSERT
語句中的欄位清單中排除該欄位,或通過使用 DEFAULT
關鍵字來完成。
型別名稱 serial
和 serial4
是等效的:兩者都建立 integer
欄位。型別名稱 bigserial
和 serial8
的工作方式相同,只是它們建立了一個 bigint
欄位。如果您預計在資料表的生命週期內使用超過 231 個識別碼,則應使用 bigserial
。型別名稱 smallserial
和 serial2
的工作方式也相同,只是它們建立了一個 smallint
欄位。
當刪除擁有欄位時,會自動刪除為 serial
欄位建立的序列。您可以刪除序列而不刪除該欄位,但這會強制刪除欄位的預設表達式。
如果您在文件中發現任何不正確的地方,與您在使用特定功能時的體驗不符,或需要進一步說明,請使用 此表單 來報告文件問題。