2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: 開發版
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2

8.1. 數值型別 #

數值型別包括雙位元組、四位元組和八位元組整數,四位元組和八位元組浮點數,以及精度可選的十進位制數。 表 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 章。以下各節將詳細描述這些型別。

8.1.1. 整數型別 #

型別 smallintintegerbigint 儲存整數,即不帶小數部分的數字,具有不同的範圍。嘗試儲存超出允許範圍的值將導致錯誤。

型別 integer 是常見的選擇,因為它在範圍、儲存大小和效能之間提供了最佳平衡。 smallint 型別通常僅在磁碟空間非常有限時使用。 bigint 型別設計用於 integer 類型範圍不足時使用。

SQL僅指定整數型別 integer(或 int)、smallintbigint。型別名稱 int2int4int8 是擴充套件,也被一些其他SQL資料庫系統使用。

8.1.2. 精確數值型別 #

型別 numeric 可以儲存具有非常多位數的數字。特別推薦用於儲存貨幣金額和其他需要精確性的數量。 numeric 值的計算在可能的情況下會產生精確的結果,例如加法、減法、乘法。但是,與整數型別或下一節所述的浮點數型別相比, numeric 值的計算速度非常慢。

我們在下面使用以下術語: numeric精度 是整個數字中有效數字的總位數,即小數點兩側的數字位數。 numeric標度 是小數部分中小數點右側的十進位制數字位數。因此,數字 23.5141 的精度為 6,標度為 4。整數可以被認為標度為零。

可以配置 numeric 列的最大精度和最大標度。要宣告 numeric 型別的列,請使用以下語法:

NUMERIC(precision, scale)

精度必須為正數,而標度可以是正數或負數(見下文)。或者

NUMERIC(precision)

選擇標度為 0。指定

NUMERIC

時不帶任何精度或標度,會建立一個“無約束 numeric”列,其中可以儲存任何長度的數值,直到實現限制。這種列不會將輸入值強制轉換為任何特定標度,而聲明瞭標度的 numeric 列會將輸入值強制轉換為該標度。( numericSQL標準要求預設標度為 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 的範圍內。但是,SQLSQL 標準要求標度在 0 到 精度 的範圍內。使用超出該範圍的標度可能無法移植到其他資料庫系統。

數值在物理儲存時不帶任何額外的首位或尾隨零。因此,列的宣告精度和標度是最大值,而不是固定分配。(從這個意義上說, numeric 型別比 char(n) 更像 varchar(n) 。)實際儲存需求是每四位十進位制數字兩個位元組,加上三到八個位元組的開銷。

除了普通數值外, numeric 型別還包含一些特殊值


無窮大
-無窮大
NaN

這些值取自 IEEE 754 標準,分別代表“無窮大”、“負無窮大”和“非數字”。在 SQL 命令中將這些值寫為常量時,必須用引號括起來,例如 UPDATE table SET x = '-Infinity'。輸入時,這些字串不區分大小寫。無窮大值還可以拼寫為 inf-inf

無窮大值按照數學預期進行運算。例如, Infinity 加上任何有限值等於 InfinityInfinity 加上 Infinity 也等於 Infinity;但是 Infinity 減去 Infinity 會得到 NaN(非數字),因為它沒有明確定義的解釋。請注意,無窮大隻能儲存在無約束的 numeric 列中,因為它名義上超過了任何有限的精度限制。

NaN(非數字)值用於表示未定義的計算結果。通常,任何帶有 NaN 輸入的操作都會產生另一個 NaN。唯一的例外是當操作的其他輸入使得如果將 NaN 替換為任何有限或無限數值,都會得到相同的輸出時;在這種情況下,該輸出值也將用於 NaN。(這個原則的一個例子是 NaN 的零次冪得到 1。)

注意

在“非數字”概念的大多數實現中, NaN 不被認為等於任何其他數值(包括 NaN)。為了允許 numeric 值進行排序並在基於樹的索引中使用, PostgreSQLNaN 值視為相等,並且大於所有非 NaN 值。

型別 decimalnumeric 是等效的。這兩種型別都是SQLSQL 標準的一部分。

在四捨五入值時, numeric 型別將中間值(例如 1.5)四捨五入為遠離零的值,而(在大多數機器上) realdouble 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. 浮點數型別 #

資料型別 realdouble precision 是不精確的、可變精度的數值型別。在所有當前支援的平臺上,這些型別都是IEEE754 二進位制浮點運算標準(單精度和雙精度)的實現,只要底層處理器、作業系統和編譯器支援。這意味著將某些值轉換為內部格式時可能無法精確轉換,而是儲存為近似值,因此儲存和檢索值時可能會顯示輕微的差異。

不精確意味著某些值無法精確轉換為內部格式並存儲為近似值,因此儲存和檢索值時可能會顯示輕微的差異。管理這些錯誤以及它們如何傳播到計算中是整個數學和計算機科學分支的主題,此處不作討論,但以下幾點除外:

  • 如果您需要精確的儲存和計算(例如用於貨幣金額),請使用 numeric 型別。

  • 如果您想對這些型別進行重要的複雜計算,尤其是在您依賴邊界情況(無窮大、下溢)的特定行為時,您應該仔細評估實現。

  • 將兩個浮點數進行相等比較可能並不總是如預期那樣工作。

在所有當前支援的平臺上, real 型別的範圍大約為 1E-37 到 1E+37,精度至少為 6 位十進位制數字。 double precision 型別的範圍大約為 1E-307 到 1E+308,精度至少為 15 位數字。值太大或太小都會導致錯誤。如果輸入數字的精度過高,可能會發生四捨五入。接近零但無法表示為不同於零的值將導致下溢錯誤。

預設情況下,浮點值以文字形式輸出,以其最短精確的十進位制表示形式顯示;生成的十進位制值比同一二進位制精度可表示的任何其他值更接近真實的儲存二進位制值。(但是,當前輸出值永遠不會 正好 位於兩個可表示值之間,以避免輸入例程不正確地遵守四捨五入到最近偶數的規則。)對於 float8 值,此值最多使用 17 位有效十進位制數字,對於 float4 值,最多使用 9 位數字。

注意

這種最短精確輸出格式的生成速度比歷史上的四捨五入格式快得多。

為了與舊版本 PostgreSQL 生成的輸出相容,並允許減少輸出精度,可以使用 extra_float_digits 引數來選擇四捨五入的十進位制輸出。將該值設定為 0 會恢復到以前的預設值,即四捨五入到 6 位(對於 float4)或 15 位(對於 float8)有效十進位制數字。設定負值會進一步減少數字位數;例如, -2 分別會將輸出四捨五入到 4 位或 13 位。

大於 0 的 extra_float_digits 值會選擇最短精確格式。

注意

歷史上,需要精確值的應用程式必須將 extra_float_digits 設定為 3 以獲取精確值。為了在版本之間最大程度地相容,它們應該繼續這樣做。

除了普通數值外,浮點數型別還包含一些特殊值


無窮大
-無窮大
NaN

這些值代表 IEEE 754 特殊值“無窮大”、“負無窮大”和“非數字”。在 SQL 命令中將這些值寫為常量時,必須用引號括起來,例如 UPDATE table SET x = '-Infinity'。輸入時,這些字串不區分大小寫。無窮大值還可以拼寫為 inf-inf

注意

IEEE 754 規定 NaN 不應與任何其他浮點值(包括 NaN)進行比較。為了允許浮點值進行排序並在基於樹的索引中使用, PostgreSQLNaN 值視為相等,並且大於所有非 NaN 值。

PostgreSQL 還支援 SQL 標準的 floatfloat(p) 表示法來指定不精確的數值型別。其中, p 指定最小可接受的 二進位制 位精度。 PostgreSQL 接受 float(1)float(24) 作為選擇 real 型別,而 float(25)float(53) 選擇 double precisionp 值超出允許範圍將引發錯誤。沒有指定精度的 float 被解釋為 double precision

8.1.4. 序列型別 #

注意

本節描述了一種 PostgreSQL 特有的建立自動遞增列的方法。另一種方法是使用 SQL 標準的標識列功能,詳見 第 5.3 節

資料型別 smallserialserialbigserial 並非真正的型別,而只是一種方便的記法,用於建立唯一識別符號列(類似於一些其他資料庫支援的 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 約束以確保不能插入空值。(在大多數情況下,您還希望附加一個 UNIQUEPRIMARY KEY 約束,以防止意外插入重複值,但這並非自動的。)最後,序列被標記為“歸屬於”該列,因此如果列或表被刪除,序列也將被刪除。

注意

由於 smallserialserialbigserial 是透過序列實現的,因此即使沒有刪除任何行,“空洞”或間隙可能會出現在列中的值序列中。即使包含該值的行從未成功插入到列中,從序列分配的值仍然會被“用掉”。例如,這種情況可能發生在插入事務回滾時。有關詳細資訊,請參閱 第 9.17 節 中的 nextval()

要將序列的下一個值插入 serial 列,請指定 serial 列應被分配其預設值。這可以透過在 INSERT 語句的列列表中省略該列,或透過使用 DEFAULT 關鍵字來完成。

型別名稱 serialserial4 是等效的:兩者都建立 integer 列。型別名稱 bigserialserial8 的工作方式相同,只是它們建立 bigint 列。如果您預計在表生命週期內使用超過 231 個識別符號,則應使用 bigserial。型別名稱 smallserialserial2 的工作方式相同,只是它們建立 smallint 列。

serial 列建立的序列在擁有它的列被刪除時會自動刪除。您可以刪除序列而不刪除列,但這將強制刪除列的預設表示式。

提交更正

如果您在文件中看到任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。