第八章、PG數據類型(數字類型、貨幣類型、字符串類型)【一】


數值類型由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

 

8.1.1. 整型

與MySQ類似PG中整型也是smallint,integer(int)和bigint類型,並且與MySQL一樣基於范圍,存儲大小和性能之間實現最佳平衡考慮通常使用int(integer)整數類型,MySQL中往往自增主鍵用bigint,pg中當int類型取值不夠時,也會用bigint代替。

如下integer類型插入1.1可以插入進去,但是存的值是整數1,四舍五入精度確實

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 |           |          | 

8.1.2. 精確浮點型

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)

8.1.3. 浮點類型

real 和double precision類型是不精確的,實際上,這些類型通常是二進制浮點算術的IEEE標准754的實現(分別為單精度和雙精度),只要底層處理器,操作系統和編譯器支持它即可。存儲錢之類的要求精度高的數據再次強調一定要用numeric,real和double 類型可以指定負無窮大,正無窮大值。

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”列。刪除列時,將自動刪除列上對應的序列。 您可以刪除序列而不刪除列,但是這將強制刪除列默認表達式。

8.2. Monetary Types貨幣類型

 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)
Name 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;

將“貨幣”值除以整數值的過程是將小數部分截斷為零。 要獲得四舍五入的結果,請除以浮點值,或將“ money”值轉換為“ numeric”,然后除以,然后再返回至“ money”。 (最好避免使用后者,以免損失精度。)將“貨幣”值除以另一個“貨幣”值時,結果是“雙精度”(即純數字,而不是貨幣);

8.3.字符串類型

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM