本文介紹了數字類型的定義及相關文法。
數字類型
名字 | 儲存尺寸 | 說明 | 範圍 |
| 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。可以認為整數的刻度為零。
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-InfinityNaN
這些分別代表 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約束以確保空值不會被插入(在大多數情況下你可能還希望附加一個UNIQUE或者PRIMARY KEY約束避免意外地插入重複的值,但這個不是自動發生的)。最後,該序列被標記為“屬於”該列,這樣當列或表被刪除時該序列也會被刪除。
因為smallserial、serial和bigserial是用序列實現的,所以即使沒有刪除過行,在出現在列中的序列值可能有“空洞”或者間隙。如果一個從序列中分配的值被用在一行中,即使該行最終沒有被成功地插入到表中,該值也被“用掉”了。例如,當插入交易回復時就會發生這種情況。
要使用serial列插入序列的下一個數值到表中, 請指定serial列應該被賦予其預設值。我們可以通過在INSERT語句中把該列排除在列列表之外來實現,也可以通過使用DEFAULT關鍵字來實現。
類型名serial和serial4是等效的: 兩個都建立integer列。類型名bigserial和serial8也一樣,只不過它們建立一個 bigint列。如果你預計在表的生存期中使用的標識符數目超過 231 個,那麼你應該使用bigserial。類型名smallserial和serial2也以相同方式工作,只不過它們建立一個smallint列。
為一個serial列建立的序列在所屬的列被刪除的時候自動刪除。你可以在不刪除列的情況下刪除序列,但是這會強制移除該列的預設值運算式。