PostgreSQL 約束用于規(guī)定表中的數據規(guī)則。
如果存在違反約束的數據行為,行為會被約束終止。
約束可以在創(chuàng)建表時規(guī)定(通過 CREATE TABLE 語句),或者在表創(chuàng)建之后規(guī)定(通過 ALTER TABLE 語句)。
約束確保了數據庫中數據的準確性和可靠性。
約束可以是列級或表級。列級約束僅適用于列,表級約束被應用到整個表。
以下是在 PostgreSQL 中常用的約束。
默認情況下,列可以保存為 NULL 值。如果您不想某列有 NULL 值,那么需要在該列上定義此約束,指定在該列上不允許 NULL 值。
NULL 與沒有數據是不一樣的,它代表著未知的數據。
實例
下面實例創(chuàng)建了一張新表叫 COMPANY1,添加了 5 個字段,其中三個 ID,NAME,AGE 設置不接受空置:
CREATE TABLE COMPANY1( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL );
UNIQUE 約束可以設置列是唯一的,避免同一列出現重復值。
實例
下面實例創(chuàng)建了一張新表叫 COMPANY3,添加了 5 個字段,其中 AGE 設置為 UNIQUE,因此你不能添加兩條有相同年齡的記錄:
CREATE TABLE COMPANY3( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL UNIQUE, ADDRESS CHAR(50), SALARY REAL DEFAULT 50000.00 );
在設計數據庫時,PRIMARY KEY 非常重要。
PRIMARY KEY 稱為主鍵,是數據表中每一條記錄的唯一標識。
設置 UNIQUE 的列可能有多個,但是一張表只有一列可以設置 PRIMARY KEY。
我們可以使用主鍵來引用表中的行,也可以通過把主鍵設置為其他表的外鍵,來創(chuàng)建表之間的關系。
主鍵是非空約束和唯一約束的組合。
一個表只能有一個主鍵,它可以由一個或多個字段組成,當多個字段作為主鍵,它們被稱為復合鍵。
如果一個表在任何字段上定義了一個主鍵,那么在這些字段上不能有兩個記錄具有相同的值。
實例
下面我們創(chuàng)建 COMAPNY4 表,其中 ID 作為主鍵:
CREATE TABLE COMPANY4( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL );
FOREIGN KEY 即外鍵約束,指定列(或一組列)中的值必須匹配另一個表的某一行中出現的值。
通常一個表中的 FOREIGN KEY 指向另一個表中的 UNIQUE KEY(唯一約束的鍵),即維護了兩個相關表之間的引用完整性。
實例
下面實例創(chuàng)建了一張 COMPANY6 表,并添加了5個字段:
CREATE TABLE COMPANY6( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL );
下面實例創(chuàng)建一張 DEPARTMENT1 表,并添加 3 個字段,EMP_ID 就是外鍵,參照 COMPANY6 的 ID:
CREATE TABLE DEPARTMENT1( ID INT PRIMARY KEY NOT NULL, DEPT CHAR(50) NOT NULL, EMP_ID INT references COMPANY6(ID) );
CHECK 約束保證列中的所有值滿足某一條件,即對輸入一條記錄要進行檢查。如果條件值為 false,則記錄違反了約束,且不能輸入到表。
實例
例如,下面實例建一個新的表 COMPANY5,增加了五列。在這里,我們?yōu)?SALARY 列添加 CHECK,所以工資不能為零:
CREATE TABLE COMPANY5( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL CHECK(SALARY > 0) );
EXCLUSION 約束確保如果使用指定的運算符在指定列或表達式上比較任意兩行,至少其中一個運算符比較將返回 false 或 null。
實例
下面實例創(chuàng)建了一張 COMPANY7 表,添加 5 個字段,并且使用了 EXCLUDE 約束。
CREATE TABLE COMPANY7( ID INT PRIMARY KEY NOT NULL, NAME TEXT, AGE INT , ADDRESS CHAR(50), SALARY REAL, EXCLUDE USING gist (NAME WITH =, -- 如果滿足 NAME 相同,AGE 不相同則不允許插入,否則允許插入 AGE WITH <>) -- 其比較的結果是如果整個表邊式返回 true,則不允許插入,否則允許 );
這里,USING gist 是用于構建和執(zhí)行的索引一種類型。
您需要為每個數據庫執(zhí)行一次 CREATE EXTENSION btree_gist 命令,這將安裝 btree_gist 擴展,它定義了對純標量數據類型的 EXCLUDE 約束。
由于我們已經強制執(zhí)行了年齡必須相同,讓我們通過向表插入記錄來查看這一點:
INSERT INTO COMPANY7 VALUES(1, 'Paul', 32, 'California', 20000.00 ); INSERT INTO COMPANY7 VALUES(2, 'Paul', 32, 'Texas', 20000.00 ); -- 此條數據的 NAME 與第一條相同,且 AGE 與第一條也相同,故滿足插入條件 INSERT INTO COMPANY7 VALUES(3, 'Allen', 42, 'California', 20000.00 ); -- 此數據與上面數據的 NAME 相同,但 AGE 不相同,故不允許插入
前面兩條順利添加的 COMPANY7 表中,但是第三條則會報錯:
ERROR: duplicate key value violates unique constraint "company7_pkey" DETAIL: Key (id)=(3) already exists.
刪除約束必須知道約束名稱,已經知道名稱來刪除約束很簡單,如果不知道名稱,則需要找到系統(tǒng)生成的名稱,使用 \d 表名 可以找到這些信息。
通用語法如下:
ALTER TABLE table_name DROP CONSTRAINT some_name;
更多建議: