數值類型由2字節,4字節和8字節整數,4字節和8字節浮點數以及可變精度的小數組成。
Name | Storage Size | Description | Range |
---|---|---|---|
smallint |
2 bytes | small-range integer | -32768 to +32767 |
integer |
4 bytes | typical choice for integer | -2147483648 to +2147483647 |
bigint |
8 bytes | large-range integer | -9223372036854775808 to +9223372036854775807 |
decimal |
variable | user-specified precision, exact | up to 131072 digits before the decimal point; up to 16383 digits after the decimal point |
numeric |
variable | user-specified precision, exact | up to 131072 digits before the decimal point; up to 16383 digits after the decimal point |
real |
4 bytes | variable-precision, inexact | 6 decimal digits precision |
double precision |
8 bytes | variable-precision, inexact | 15 decimal digits precision |
smallserial |
2 bytes | small autoincrementing integer | 1 to 32767 |
serial |
4 bytes | autoincrementing integer | 1 to 2147483647 |
bigserial |
8 bytes | large autoincrementing integer | 1 to 9223372036854775807 |
postgres=# \d products; Table "public.products" Column | Type | Collation | Nullable | Default ------------+---------+-----------+----------+--------- product_no | integer | | | name | text | | | price | numeric | | | postgres=# insert into products values(1.1,'banana',1.2); INSERT 0 1 postgres=# select * from products; product_no | name | price ------------+--------+--------- 1 | Cheese | 1 | Cheese | 1 | Cheese | 1 | Cheese | 10.9890 1 | banana | 1.2
SQL僅指定整數類型integer(或int),smallint和bigint。 類型名稱int2,int4和int8是擴展名,有些SQL數據庫系統也使用這些擴展名,也就是說pg中int2是smallint的別名。
postgres=# create table test (int_c int2); CREATE TABLE postgres=# postgres=# \d test; Table "public.test" Column | Type | Collation | Nullable | Default --------+----------+-----------+----------+--------- int_c | smallint | | |
MySQL中稱為精確浮點型,PG中原英文是Arbitrary Precision Numbers,翻譯成中文是任意精度數,那么也好理解,decimal可以指定精確度,例如,數字23.5141的精度為6,小數位數為4。可以將整數視為小數位數為零,那么定義的時候即為decimal(6,4)或者NUMERIC(6,4)。實際存儲空間類似於varchar(n),兩個字節對於每組四個十進制數字,再加上三到八個字節的開銷。
postgres=# create table f (money decimal,a float); CREATE TABLE postgres=# insert into f select 1.214151515151321313123213,1.214151515151321313123213; INSERT 0 1 postgres=# select * from f; money | a ----------------------------+------------------ 1.214151515151321313123213 | 1.21415151515132 (1 row) postgres=# \d f; Table "public.f" Column | Type | Collation | Nullable | Default --------+------------------+-----------+----------+--------- money | numeric | | | a | double precision | | |
postgres=# create table a ( a decimal(10,2)); CREATE TABLE postgres=# \d a; Table "public.a" Column | Type | Collation | Nullable | Default --------+---------------+-----------+----------+--------- a | numeric(10,2) | | | postgres=# insert into a values(1.23); INSERT 0 1 postgres=# insert into a values(1.234); INSERT 0 1 postgres=# insert into a values(1.2345); INSERT 0 1 postgres=# insert into a values(1.2); INSERT 0 1 postgres=# select * from a; a ------ 1.23 1.23 1.23 1.20 (4 rows) postgres=# insert into a values(123456789.2); ERROR: numeric field overflow DETAIL: A field with precision 10, scale 2 must round to an absolute value less than 10^8. postgres=# insert into a values(12345678.2); INSERT 0 1 postgres=# select * from a; a ------------- 1.23 1.23 1.23 1.20 12345678.20 (5 rows)
postgres=# create table abc (abc real); CREATE TABLE postgres=# \d abc Table "public.abc" Column | Type | Collation | Nullable | Default --------+------+-----------+----------+--------- abc | real | | | postgres=# update abc set abc = '-Infinity'; UPDATE 0 postgres=# select * from abc; abc ----- (0 rows) postgres=# insert into abc values (-10); INSERT 0 1 postgres=# insert into abc values ('-Infinity'); INSERT 0 1 postgres=# insert into abc values ('-Infinity'); INSERT 0 1 postgres=# select * from abc; abc ----------- -10 -Infinity -Infinity (3 rows)
PostgreSQL還支持SQL標准float和float(p)來指定不精確的數字類型。在這里,“p”以二進制數指定最小可接受精度。 PostgreSQL以float(1)到float(24)來表示real類型,而float(25)
到float(53)
表示double precision
。
postgres=# create table float_test(a float(10),b float(30)); CREATE TABLE postgres=# \d float_test; Table "public.float_test" Column | Type | Collation | Nullable | Default --------+------------------+-----------+----------+--------- a | real | | | b | double precision | | |
8.1.4. Serial 類型
MySQL中自增可以指定auto increment關鍵字,Oracle可以使用序列,PG與Oracle有些類似,本節描述了PostgreSQL特定自增列的方法。
數據類型smallserial,serial和bigserial不是真實類型,而僅僅是創建唯一標識符列的符號方便(類似於某些其他數據庫支持的AUTO_INCREMENT屬性)。 在當前的實現中,指定:
postgres=# create table test (id serial, money decimal); CREATE TABLE --或者 postgres=# CREATE SEQUENCE product_id_seq AS integer; CREATE SEQUENCE postgres=# CREATE TABLE product (id integer NOT NULL DEFAULT nextval('product_id_seq') primary key,country varchar(20)); CREATE TABLE postgres=# ALTER SEQUENCE product_id_seq OWNED BY product.id; ALTER SEQUENCE postgres=# insert into product(country) values('China'); INSERT 0 1 postgres=# insert into product(country) values('Japan'); INSERT 0 1 postgres=# select * from product; id | country ----+--------- 1 | China 2 | Japan (2 rows) postgres=# select nextval('product_id_seq'); nextval --------- 3 (1 row) postgres=# select nextval('product_id_seq'); nextval --------- 4 (1 row) postgres=# insert into product(country) values('USA'); INSERT 0 1 postgres=# select * from product; id | country ----+--------- 1 | China 2 | Japan 5 | USA (3 rows) postgres=# \d product; Table "public.product" Column | Type | Collation | Nullable | Default ---------+-----------------------+-----------+----------+------------------------------------- id | integer | | not null | nextval('product_id_seq'::regclass) country | character varying(20) | | | Indexes: "product_pkey" PRIMARY KEY, btree (id)
類型名稱“ serial”和“ serial4”是等效的:都創建“ integer”類型的列。 類型名稱“ bigserial”和“ serial8”的工作方式相同,不同之處在於它們創建了“ bigint”列。 如果您預計在表的生命周期內使用超過231個標識符,則應使用“ bigserial”。 類型名稱“ smallserial”和“ serial2”的工作方式相同,只是它們創建了“ smallint”列。
money類型(貨幣類型)以固定的分數精度存儲貨幣金額,見下表。 小數精度由數據庫的lc_monetary設置確定。 表中顯示的范圍假設有兩個小數位。 接受的輸入格式有多種,包括整數和浮點文字,以及典型的貨幣格式,例如“ $ 1,000.00”。 輸出通常采用后一種形式,但取決於語言環境。
postgres=# create table money_test( id bigint primary key, money money); CREATE TABLE postgres=# \d money_test; Table "public.money_test" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+--------- id | bigint | | not null | money | money | | | Indexes: "money_test_pkey" PRIMARY KEY, btree (id) postgres=# insert into money_test values (1 ,20); INSERT 0 1 postgres=# select * from money_test; id | money ----+-------- 1 | $20.00 (1 row)
Storage Size | Description | Range | |
---|---|---|---|
money |
8 bytes | currency amount | -92233720368547758.08 to +92233720368547758.07 |
由於此數據類型的輸出對語言環境敏感,因此將“ money”數據加載到具有“ lc_monetary”不同設置的數據庫中可能不起作用。 為了避免出現問題,在將轉儲恢復到新數據庫之前,請確保“ lc_monetary”具有與轉儲數據庫中相同或相等的值。
set lc_monetary='zh_CN'; show lc_monetary;
可以將“ numeric”,“ int”和“ bigint”數據類型的值強制轉換為“ money”。 從“ real”和“ double precision”數據類型的轉換可以通過首先轉換為“ numeric”來完成,例如:
postgres=# SELECT '12.34'::float8::numeric::money; money -------- $12.34 (1 row)
但是,不建議這樣做。 由於可能會舍入錯誤,因此不應使用浮點數來處理資金。
可以將“ money”值轉換為“ numeric”而不會損失精度。 轉換為其他類型可能會失去精度,並且必須分兩個階段完成:
SELECT '52093.89'::money::numeric::float8;
Name | Description |
---|---|
character varying(n) , varchar(n) |
variable-length with limit |
character(n) , char(n) |
fixed-length, blank padded |
text |
variable unlimited length |
PostgreSQL提供了“text”文本類型,該類型存儲任何長度的字符串。
短字符串(最多126個字節)的存儲要求是1個字節加上實際字符串,如果是'character',則包括空格。較長的字符串的開銷為4個字節,而不是1個字節。較長的字符串由系統自動壓縮,因此對磁盤的物理需求可能會更少。非常長的值也存儲在后台表中,這樣它們就不會干擾對較短列值的快速訪問。在任何情況下,可以存儲的最長字符串約為1 GB。 (數據類型聲明中允許n 的最大值小於該值。更改此值無用,因為對於多字節字符編碼,字符和字節數可以如果您希望存儲沒有特定上限的長字符串,請使用不帶長度說明符的“文本”或“字符變化”,而不是設置任意長度限制。)
這三種類型之間沒有性能差異,除了使用空白填充類型時增加了存儲空間,只不過存在長度受限,盡管在其他一些數據庫系統中,“ char(n)”具有性能上的優勢,但在PostgreSQL中卻沒有這種優勢。實際上,“char(n)”通常是三個字符中最慢的一個,因為它會增加存儲成本。在大多數情況下,應改用“text”或“varchar”。
postgres=# CREATE TABLE test1 (a character(4)); CREATE TABLE postgres=# postgres=# INSERT INTO test1 VALUES ('ok'); INSERT 0 1 postgres=# SELECT a, char_length(a) FROM test1; -- (1) a | char_length ------+------------- ok | 2 (1 row) postgres=# CREATE TABLE test2 (b varchar(5)); CREATE TABLE postgres=# INSERT INTO test2 VALUES ('ok'); INSERT 0 1 postgres=# postgres=# INSERT INTO test2 VALUES ('good '); INSERT 0 1 postgres=# postgres=# INSERT INTO test2 VALUES ('too long'); ERROR: value too long for type character varying(5) INSERT INTO test2 VALUES ('too long'::varchar(5)); -- explicit truncation SELECT b, char_length(b) FROM test2; b | char_length -------+------------- ok | 2 good | 5 too l | 5
PostgreSQL中還有另外兩種定長字符類型。名稱類型僅存在於內部系統目錄中,用於存儲標識符,不適合普通用戶使用。 目前,它的長度定義為64個字節(63個可用字符加終止符),但應使用C源代碼中的常量“ NAMEDATALEN”來引用。 該長度是在編譯時設置的(因此對於特殊用途可以調整); 默認的最大長度可能會在將來的版本中更改。 “ char”類型(請注意引號)與“ char(1)”不同之處在於它僅使用一個字節的存儲空間。 在系統目錄中內部使用它作為一種簡單的枚舉類型。
Name | Storage Size | Description |
---|---|---|
"char" |
1 byte | single-byte internal type |
name |
64 bytes | internal type for object names |