PostgreSQL 數(shù)據(jù)類型

2020-04-22 18:04 更新

本章節(jié),我們將討論 PostgreSQL 的數(shù)據(jù)類型,數(shù)據(jù)類型是我們再創(chuàng)建表的時候為每個字段設(shè)置的。

設(shè)置數(shù)據(jù)類型的好處:

PostgreSQL提 供了豐富的數(shù)據(jù)類型。用戶可以使用 CREATE TYPE 命令在數(shù)據(jù)庫中創(chuàng)建新的數(shù)據(jù)類型。PostgreSQL 的數(shù)據(jù)類型有很多種,下面我們具體來說明。

數(shù)值類型

數(shù)值類型由 2 字節(jié)、4 字節(jié)或 8 字節(jié)的整數(shù)以及 4 字節(jié)或 8 字節(jié)的浮點數(shù)和可選精度的十進制數(shù)組成。

下表列出了可用的數(shù)值類型。

名字存儲長度描述范圍
smallint2 字節(jié)小范圍整數(shù)-32768 到 +32767
integer4 字節(jié)常用的整數(shù)-2147483648 到 +2147483647
bigint8 字節(jié)大范圍整數(shù)-9223372036854775808 到 +9223372036854775807
decimal可變長用戶指定的精度,精確小數(shù)點前 131072 位;小數(shù)點后 16383 位
numeric可變長用戶指定的精度,精確小數(shù)點前 131072 位;小數(shù)點后 16383 位
real4 字節(jié)可變精度,不精確6 位十進制數(shù)字精度
double precision8 字節(jié)可變精度,不精確15 位十進制數(shù)字精度
smallserial2 字節(jié)自增的小范圍整數(shù)1 到 32767
serial4 字節(jié)自增整數(shù)1 到 2147483647
bigserial8 字節(jié)自增的大范圍整數(shù)1 到 9223372036854775807

貨幣類型

money 類型存儲帶有固定小數(shù)精度的貨幣金額。

numeric、int 和 bigint 類型的值可以轉(zhuǎn)換為 money,不建議使用浮點數(shù)來處理處理貨幣類型,因為存在舍入錯誤的可能性。

名字存儲容量描述范圍
money8 字節(jié)貨幣金額-92233720368547758.08 到 +92233720368547758.07

字符類型

下表列出了 PostgreSQL 所支持的字符類型:

序號名字 & 描述
1

character varying(n), varchar(n)

變長,有長度限制

2

character(n), char(n)

f定長,不足補空白

3

text

變長,無長度限制

日期/時間類型

下表列出了 PostgreSQL 支持的日期和時間類型。

名字存儲空間描述最低值最高值分辨率
timestamp [ (p) ] [ without time zone ]8 字節(jié)日期和時間(無時區(qū))4713 BC294276 AD1 毫秒 / 14 位
timestamp [ (p) ] with time zone8 字節(jié)日期和時間,有時區(qū)4713 BC294276 AD1 毫秒 / 14 位
date4 字節(jié)只用于日期4713 BC5874897 AD1 天
time [ (p) ] [ without time zone ]8 字節(jié)只用于一日內(nèi)時間00:00:0024:00:001 毫秒 / 14 位
time [ (p) ] with time zone12 字節(jié)只用于一日內(nèi)時間,帶時區(qū)00:00:00+145924:00:00-14591 毫秒 / 14 位
interval [ fields ] [ (p) ]12 字節(jié)時間間隔-178000000 年178000000 年1 毫秒 / 14 位

布爾類型

PostgreSQL 支持標(biāo)準(zhǔn)的 boolean 數(shù)據(jù)類型。

boolean 有"true"(真)或"false"(假)兩個狀態(tài), 第三種"unknown"(未知)狀態(tài),用 NULL 表示。

名稱存儲格式描述
boolean1 字節(jié)true/false

枚舉類型

枚舉類型是一個包含靜態(tài)和值的有序集合的數(shù)據(jù)類型。

PostgtesSQL中的枚舉類型類似于 C 語言中的 enum 類型。

與其他類型不同的是枚舉類型需要使用 CREATE TYPE 命令創(chuàng)建。

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

創(chuàng)建一周中的幾天,如下所示:

CREATE TYPE week AS ENUM ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');

就像其他類型一樣,一旦創(chuàng)建,枚舉類型可以用于表和函數(shù)定義。

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
CREATE TABLE person (
    name text,
    current_mood mood
);
INSERT INTO person VALUES ('Moe', 'happy');
SELECT * FROM person WHERE current_mood = 'happy';
 name | current_mood 
------+--------------
 Moe  | happy
(1 row)

幾何類型

幾何數(shù)據(jù)類型表示二維的平面物體。

下表列出了 PostgreSQL 支持的幾何類型。

最基本的類型:點。它是其它類型的基礎(chǔ)。

名字存儲空間說明表現(xiàn)形式
point16 字節(jié)平面中的點(x,y)
line32 字節(jié)(無窮)直線(未完全實現(xiàn))((x1,y1),(x2,y2))
lseg32 字節(jié)(有限)線段((x1,y1),(x2,y2))
box32 字節(jié)矩形((x1,y1),(x2,y2))
path16+16n 字節(jié)閉合路徑(與多邊形類似)((x1,y1),...)
path16+16n 字節(jié)開放路徑[(x1,y1),...]
polygon40+16n 字節(jié)多邊形(與閉合路徑相似)((x1,y1),...)
circle24 字節(jié)<(x,y),r> (圓心和半徑)

網(wǎng)絡(luò)地址類型

PostgreSQL 提供用于存儲 IPv4 、IPv6 、MAC 地址的數(shù)據(jù)類型。

用這些數(shù)據(jù)類型存儲網(wǎng)絡(luò)地址比用純文本類型好, 因為這些類型提供輸入錯誤檢查和特殊的操作和功能。

名字存儲空間描述
cidr7 或 19 字節(jié)IPv4 或 IPv6 網(wǎng)絡(luò)
inet7 或 19 字節(jié)IPv4 或 IPv6 主機和網(wǎng)絡(luò)
macaddr6 字節(jié)MAC 地址

在對 inet 或 cidr 數(shù)據(jù)類型進行排序的時候, IPv4 地址總是排在 IPv6 地址前面,包括那些封裝或者是映射在 IPv6 地址里的 IPv4 地址, 比如 ::10.2.3.4 或 ::ffff:10.4.3.2。

位串類型

位串就是一串 1 和 0 的字符串。它們可以用于存儲和直觀化位掩碼。 我們有兩種 SQL 位類型:bit(n) 和bit varying(n), 這里的n是一個正整數(shù)。

bit 類型的數(shù)據(jù)必須準(zhǔn)確匹配長度 n, 試圖存儲短些或者長一些的數(shù)據(jù)都是錯誤的。bit varying 類型數(shù)據(jù)是最長 n 的變長類型;更長的串會被拒絕。 寫一個沒有長度的bit 等效于 bit(1), 沒有長度的 bit varying 意思是沒有長度限制。

文本搜索類型

全文檢索即通過自然語言文檔的集合來找到那些匹配一個查詢的檢索。

PostgreSQL 提供了兩種數(shù)據(jù)類型用于支持全文檢索:

序號名字 & 描述
1

tsvector

tsvector 的值是一個無重復(fù)值的 lexemes 排序列表, 即一些同一個詞的不同變種的標(biāo)準(zhǔn)化。

2

tsquery

tsquery 存儲用于檢索的詞匯,并且使用布爾操作符 &(AND),|(OR)和!(NOT) 來組合它們,括號用來強調(diào)操作符的分組。

UUID 類型

uuid 數(shù)據(jù)類型用來存儲 RFC 4122,ISO/IEF 9834-8:2005 以及相關(guān)標(biāo)準(zhǔn)定義的通用唯一標(biāo)識符(UUID)。 (一些系統(tǒng)認為這個數(shù)據(jù)類型為全球唯一標(biāo)識符,或GUID。) 這個標(biāo)識符是一個由算法產(chǎn)生的 128 位標(biāo)識符,使它不可能在已知使用相同算法的模塊中和其他方式產(chǎn)生的標(biāo)識符相同。 因此,對分布式系統(tǒng)而言,這種標(biāo)識符比序列能更好的提供唯一性保證,因為序列只能在單一數(shù)據(jù)庫中保證唯一。

UUID 被寫成一個小寫十六進制數(shù)字的序列,由分字符分成幾組, 特別是一組8位數(shù)字+3組4位數(shù)字+一組12位數(shù)字,總共 32 個數(shù)字代表 128 位, 一個這種標(biāo)準(zhǔn)的 UUID 例子如下:

a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

XML 類型

xml 數(shù)據(jù)類型可以用于存儲XML數(shù)據(jù)。 將 XML 數(shù)據(jù)存到 text 類型中的優(yōu)勢在于它能夠為結(jié)構(gòu)良好性來檢查輸入值, 并且還支持函數(shù)對其進行類型安全性檢查。 要使用這個數(shù)據(jù)類型,編譯時必須使用 configure --with-libxml。

xml 可以存儲由XML標(biāo)準(zhǔn)定義的格式良好的"文檔", 以及由 XML 標(biāo)準(zhǔn)中的 XMLDecl? content 定義的"內(nèi)容"片段, 大致上,這意味著內(nèi)容片段可以有多個頂級元素或字符節(jié)點。 xmlvalue IS DOCUMENT 表達式可以用來判斷一個特定的 xml 值是一個完整的文件還是內(nèi)容片段。

創(chuàng)建XML值

使用函數(shù) xmlparse: 來從字符數(shù)據(jù)產(chǎn)生 xml 類型的值:

XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter></book>')
XMLPARSE (CONTENT 'abc<foo>bar</foo><bar>foo</bar>')

JSON 類型

json 數(shù)據(jù)類型可以用來存儲 JSON(JavaScript Object Notation)數(shù)據(jù), 這樣的數(shù)據(jù)也可以存儲為 text,但是 json 數(shù)據(jù)類型更有利于檢查每個存儲的數(shù)值是可用的 JSON 值。

此外還有相關(guān)的函數(shù)來處理 json 數(shù)據(jù):

實例實例結(jié)果
array_to_json('{{1,5},{99,100}}'::int[])[[1,5],[99,100]]
row_to_json(row(1,'foo')){"f1":1,"f2":"foo"}

數(shù)組類型

PostgreSQL 允許將字段定義成變長的多維數(shù)組。

數(shù)組類型可以是任何基本類型或用戶定義類型,枚舉類型或復(fù)合類型。

聲明數(shù)組

創(chuàng)建表的時候,我們可以聲明數(shù)組,方式如下:

CREATE TABLE sal_emp (
    name            text,
    pay_by_quarter  integer[],
    schedule        text[][]
);

pay_by_quarter 為一位整型數(shù)組、schedule 為二維文本類型數(shù)組。

我們也可以使用 "ARRAY" 關(guān)鍵字,如下所示:

CREATE TABLE sal_emp (
   name text,
   pay_by_quarter integer ARRAY[4],
   schedule text[][]
);

插入值

插入值使用花括號 {},元素在 {} 使用逗號隔開:

INSERT INTO sal_emp
    VALUES ('Bill',
    '{10000, 10000, 10000, 10000}',
    '{{"meeting", "lunch"}, {"training", "presentation"}}');

INSERT INTO sal_emp
    VALUES ('Carol',
    '{20000, 25000, 25000, 25000}',
    '{{"breakfast", "consulting"}, {"meeting", "lunch"}}');

訪問數(shù)組

現(xiàn)在我們可以在這個表上運行一些查詢。

首先,我們演示如何訪問數(shù)組的一個元素。 這個查詢檢索在第二季度薪水變化的雇員名:

SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];

 name
-------
 Carol
(1 row)

數(shù)組的下標(biāo)數(shù)字是寫在方括弧內(nèi)的。

修改數(shù)組

我們可以對數(shù)組的值進行修改:

UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
    WHERE name = 'Carol';

或者使用 ARRAY 構(gòu)造器語法:

UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000]
    WHERE name = 'Carol';

數(shù)組中檢索

要搜索一個數(shù)組中的數(shù)值,你必須檢查該數(shù)組的每一個值。

比如:

SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
                            pay_by_quarter[2] = 10000 OR
                            pay_by_quarter[3] = 10000 OR
                            pay_by_quarter[4] = 10000;

另外,你可以用下面的語句找出數(shù)組中所有元素值都等于 10000 的行:

SELECT * FROM sal_emp WHERE 10000 = ALL (pay_by_quarter);

或者,可以使用 generate_subscripts 函數(shù)。例如:

SELECT * FROM
   (SELECT pay_by_quarter,
           generate_subscripts(pay_by_quarter, 1) AS s
      FROM sal_emp) AS foo
 WHERE pay_by_quarter[s] = 10000;

復(fù)合類型

復(fù)合類型表示一行或者一條記錄的結(jié)構(gòu); 它實際上只是一個字段名和它們的數(shù)據(jù)類型的列表。PostgreSQL 允許像簡單數(shù)據(jù)類型那樣使用復(fù)合類型。比如,一個表的某個字段可以聲明為一個復(fù)合類型。

聲明復(fù)合類型

下面是兩個定義復(fù)合類型的簡單例子:

CREATE TYPE complex AS (
    r       double precision,
    i       double precision
);

CREATE TYPE inventory_item AS (
    name            text,
    supplier_id     integer,
    price           numeric
);

語法類似于 CREATE TABLE,只是這里只可以聲明字段名字和類型。

定義了類型,我們就可以用它創(chuàng)建表:

CREATE TABLE on_hand (
    item      inventory_item,
    count     integer
);

INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);

復(fù)合類型值輸入

要以文本常量書寫復(fù)合類型值,在圓括弧里包圍字段值并且用逗號分隔他們。 你可以在任何字段值周圍放上雙引號,如果值本身包含逗號或者圓括弧, 你必須用雙引號括起。

復(fù)合類型常量的一般格式如下:

'( val1 , val2 , ... )'

一個例子是:

'("fuzzy dice",42,1.99)'

訪問復(fù)合類型

要訪問復(fù)合類型字段的一個域,我們寫出一個點以及域的名字, 非常類似從一個表名字里選出一個字段。實際上,因為實在太像從表名字中選取字段, 所以我們經(jīng)常需要用圓括弧來避免分析器混淆。比如,你可能需要從on_hand 例子表中選取一些子域,像下面這樣:

SELECT item.name FROM on_hand WHERE item.price > 9.99;

這樣將不能工作,因為根據(jù) SQL 語法,item是從一個表名字選取的, 而不是一個字段名字。你必須像下面這樣寫:

SELECT (item).name FROM on_hand WHERE (item).price > 9.99;

或者如果你也需要使用表名字(比如,在一個多表查詢里),那么這么寫:

SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;

現(xiàn)在圓括弧對象正確地解析為一個指向item字段的引用,然后就可以從中選取子域。

范圍類型

范圍數(shù)據(jù)類型代表著某一元素類型在一定范圍內(nèi)的值。

例如,timestamp 范圍可能被用于代表一間會議室被預(yù)定的時間范圍。

PostgreSQL 內(nèi)置的范圍類型有:

  • int4range — integer的范圍
  • int8range —bigint的范圍
  • numrange —numeric的范圍
  • tsrange —timestamp without time zone的范圍
  • tstzrange —timestamp with time zone的范圍
  • daterange —date的范圍

此外,你可以定義你自己的范圍類型。

CREATE TABLE reservation (room int, during tsrange);
INSERT INTO reservation VALUES
    (1108, '[2010-01-01 14:30, 2010-01-01 15:30)');

-- 包含
SELECT int4range(10, 20) @> 3;

-- 重疊
SELECT numrange(11.1, 22.2) && numrange(20.0, 30.0);

-- 提取上邊界
SELECT upper(int8range(15, 25));

-- 計算交叉
SELECT int4range(10, 20) * int4range(15, 25);

-- 范圍是否為空
SELECT isempty(numrange(1, 5));

范圍值的輸入必須遵循下面的格式:

(下邊界,上邊界)
(下邊界,上邊界]
[下邊界,上邊界)
[下邊界,上邊界]
空

圓括號或者方括號顯示下邊界和上邊界是不包含的還是包含的。注意最后的格式是 空,代表著一個空的范圍(一個不含有值的范圍)。

-- 包括3,不包括7,并且包括二者之間的所有點
SELECT '[3,7)'::int4range;

-- 不包括3和7,但是包括二者之間所有點
SELECT '(3,7)'::int4range;

-- 只包括單一值4
SELECT '[4,4]'::int4range;

-- 不包括點(被標(biāo)準(zhǔn)化為‘空’)
SELECT '[4,4)'::int4range;

對象標(biāo)識符類型

PostgreSQL 在內(nèi)部使用對象標(biāo)識符(OID)作為各種系統(tǒng)表的主鍵。

同時,系統(tǒng)不會給用戶創(chuàng)建的表增加一個 OID 系統(tǒng)字段(除非在建表時聲明了WITH OIDS 或者配置參數(shù)default_with_oids設(shè)置為開啟)。oid 類型代表一個對象標(biāo)識符。除此以外 oid 還有幾個別名:regproc, regprocedure, regoper, regoperator, regclass, regtype, regconfig, 和regdictionary。

名字引用描述數(shù)值例子
oid任意數(shù)字化的對象標(biāo)識符564182
regprocpg_proc函數(shù)名字sum
regprocedurepg_proc帶參數(shù)類型的函數(shù)sum(int4)
regoperpg_operator操作符名+
regoperatorpg_operator帶參數(shù)類型的操作符*(integer,integer) 或 -(NONE,integer)
regclasspg_class關(guān)系名pg_type
regtypepg_type數(shù)據(jù)類型名integer
regconfigpg_ts_config文本搜索配置english
regdictionarypg_ts_dict文本搜索字典simple

偽類型

PostgreSQL類型系統(tǒng)包含一系列特殊用途的條目, 它們按照類別來說叫做偽類型。偽類型不能作為字段的數(shù)據(jù)類型, 但是它可以用于聲明一個函數(shù)的參數(shù)或者結(jié)果類型。 偽類型在一個函數(shù)不只是簡單地接受并返回某種SQL 數(shù)據(jù)類型的情況下很有用。

下表列出了所有的偽類型:

名字描述
any表示一個函數(shù)接受任何輸入數(shù)據(jù)類型。
anyelement表示一個函數(shù)接受任何數(shù)據(jù)類型。
anyarray表示一個函數(shù)接受任意數(shù)組數(shù)據(jù)類型。
anynonarray表示一個函數(shù)接受任意非數(shù)組數(shù)據(jù)類型。
anyenum表示一個函數(shù)接受任意枚舉數(shù)據(jù)類型。
anyrange表示一個函數(shù)接受任意范圍數(shù)據(jù)類型。
cstring表示一個函數(shù)接受或者返回一個空結(jié)尾的 C 字符串。
internal表示一個函數(shù)接受或者返回一種服務(wù)器內(nèi)部的數(shù)據(jù)類型。
language_handler一個過程語言調(diào)用處理器聲明為返回language_handler。
fdw_handler一個外部數(shù)據(jù)封裝器聲明為返回fdw_handler。
record標(biāo)識一個函數(shù)返回一個未聲明的行類型。
trigger一個觸發(fā)器函數(shù)聲明為返回trigger。
void表示一個函數(shù)不返回數(shù)值。
opaque一個已經(jīng)過時的類型,以前用于所有上面這些用途。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號