PostgreSQL 表中可以新增哪些約束?


一般來說,PostgreSQL 表可以使用 6 種類型的約束。它們列出如下並進行了解釋:

NOT NULL 約束

這是一個非常常見的約束。如果某個特定列不能包含空值,則在建立表時新增此約束。例如,如果我們建立一個成績表,該表不允許“姓名”列為空值,則建立表的命令如下所示:

CREATE TABLE marks(
   name VARCHAR NOT NULL,
   roll_no INTEGER,
   marks_obtained INTEGER
);

現在,如果我們嘗試在不提供“姓名”列值的情況下向此表中插入一行,將會看到錯誤。讓我們嘗試一下:

INSERT INTO marks(roll_no, marks_obtained)
VALUES(25,56)

您將看到的錯誤類似於以下內容:

ERROR: null value in column "name" violates not-null constraint DETAIL: Failing row
contains (null, 25, 56). SQL state: 23502

UNIQUE 約束

顧名思義,此約束表示相關列不能包含重複值。這同樣也是一個非常常見的約束。如果我們現在建立成績表並希望在“學號”列上設定 UNIQUE 約束,則可以透過以下方式完成:

CREATE TABLE marks(
   name VARCHAR,
   roll_no INTEGER UNIQUE,
   marks_obtained INTEGER
);

現在,如果我們嘗試插入重複的學號值,PostgreSQL 將丟擲錯誤。讓我們嘗試一下:

INSERT INTO marks(name, roll_no, marks_obtained)
VALUES('Yash',25,56),
('Isha',25,64)

您將看到的錯誤類似於以下內容:

ERROR: duplicate key value violates unique constraint "marks_roll_no_key" DETAIL: Key
(roll_no)=(25) already exists. SQL state: 23505

PRIMARY KEY 約束

這是 NOT NULL 和 UNIQUE 約束的組合。它可以應用於單個列或多個列。如果 PRIMARY KEY 應用於多個列,則這些列的組合應具有唯一值,而各個列可以有重複的值。

讓我們看看在單列和多列上應用 PRIMARY KEY 約束的示例:

單列

CREATE TABLE marks(
   name VARCHAR,
   roll_no INTEGER PRIMARY KEY,
   marks_obtained INTEGER
);

多列

CREATE TABLE marks(
   name VARCHAR,
   roll_no INTEGER,
   marks_obtained INTEGER,
   PRIMARY KEY (name, roll_no)
);

對於 Primary Key 約束,新增空值或重複值都會導致 PostgreSQL 丟擲錯誤。檢查此錯誤留作讀者的練習。

FOREIGN KEY 約束

此約束有助於維護多個表之間的一致性。假設您已經在前面的示例中建立了一個成績表,其中“學號”是 PRIMARY KEY。現在,如果您要建立另一個名為 student_info 的表,該表也具有“學號”列,並且您希望確保 student_info 表中只允許存在於成績表中的“學號”值,則您將在 student_info 表的“學號”列上新增 FOREIGN KEY 約束。您可以這樣做:

CREATE TABLE student_info(
   name VARCHAR,
   roll_no INTEGER REFERENCES marks (roll_no),
   age INTEGER,
   gender VARCHAR
);

現在,student_info 表的“學號”列引用了成績表的“學號”列。因此,您將無法在 student_info 中新增任何“學號”不在成績表中的值。

如果我的成績表如下所示:

姓名學號百分比成績
Siddhi4565
Yash2642
Isha5687

那麼,我嘗試在 student_info 表中新增學號為 45 的值。

INSERT INTO student_info(name, roll_no, age, gender)
VALUES ('Siddhi',45,23,'F');

此查詢成功,因為學號 45 存在於成績表中。現在,讓我們嘗試在 student_info 表中新增學號 12。

INSERT INTO student_info(name, roll_no, age, gender)
VALUES ('Aniket',12,26,'M');

PostgreSQL 將在此處丟擲錯誤:

ERROR: insert or update on table "student_info" violates foreign key constraint "student_info_roll_no_fkey" DETAIL: Key (roll_no)=(12) is not present in table "marks". SQL state: 23503

就像我們可以在多列上新增 PRIMARY KEY 約束一樣,我們也可以在多列上新增 FOREIGN KEY 約束。下面給出了一個示例:

CREATE TABLE student_info(
name VARCHAR,
roll_no INTEGER,
age INTEGER,
gender VARCHAR,
FOREIGN KEY (name, roll_no) REFERENCES marks (name, roll_no)
);

CHECK 約束

這是一個自定義約束。它允許我們強制列滿足布林表示式。例如,如果我們希望“學號”在成績表中大於 0,我們可以如下新增該約束:

CREATE TABLE marks(
   name VARCHAR,
   roll_no INTEGER CHECK (roll_no > 0),
   marks_obtained INTEGER
);

現在,如果我嘗試向此表中新增學號為 0 的條目,我將看到以下錯誤:

INSERT INTO marks(name, roll_no, marks_obtained)
VALUES('Yash',0,25)
ERROR: new row for relation "marks" violates check constraint "marks_roll_no_check"
DETAIL: Failing row contains (Yash, 0, 25). SQL state: 23514

EXCLUSION 約束

此約束的解釋由 Stack Overflow 的一個答案給出。您可以在此處檢視它:https://stackoverflow.com/a/51247705。現在,這是 UNIQUE 約束的更通用的擴充套件。UNIQUE 表示沒有兩行可以在相關列中具有相同的值。此約束更進一步。它表示,沒有兩行應該_______。您可以在空格中填寫任何內容。您可以說“沒有兩行可以不同”,或者“沒有兩行可以相交”,或者任何其他語句,具體取決於上下文和正在考慮的列。現在,UNIQUE 約束是 EXCLUSION 約束的一個特例。但 UNIQUE 很簡單。它只是說沒有兩行可以相同。因此,我們實際上檢查的是 = 運算子。而 = 檢查很容易執行。但並非所有運算子檢查都一樣容易。因此,EXCLUSION 約束要求您在應用約束的列上建立一個索引。這將確保比較速度很快。讓我們透過一個示例來理解這一點。

CREATE TABLE marks(
   name VARCHAR,
   roll_no INTEGER,
   marks_obtained INTEGER,
   EXCLUDE USING gist(roll_no WITH <>)
);

請注意,您必須在每個資料庫中執行一次 CREATE EXTENSION btree_gist,才能使上述命令正常工作。

現在,<> 是 PostgreSQL 中的不等於運算子。我們實際上告訴 PostgreSQL,對於新增到表的每一行,都使用 NOT EQUAL 運算子檢查“學號”與所有其他已存在的“學號”。僅當所有比較結果都為 FALSE 時才允許它。換句話說,只允許所有學號相同,不允許不同的學號。

現在,讓我們向上述表中新增一個值:

INSERT INTO marks8(name, roll_no, marks_obtained)
VALUES('Yash',26,55)

這將起作用。現在讓我們新增另一個具有不同學號的值。

INSERT INTO marks8(name, roll_no, marks_obtained)
VALUES('Isha',56,65)

這將丟擲一個錯誤:

ERROR: conflicting key value violates exclusion constraint "marks_roll_no_excl"
DETAIL: Key (roll_no)=(56) conflicts with existing key (roll_no)=(26). SQL state:
23P01

如果我想使用 EXCLUSION 強制執行 UNIQUE 約束,我會將 <> 替換為 =。

您也可以在多列上新增 EXCLUDE 約束。此處給出了一個示例:https://tutorialspoint.tw/postgresql/postgresql_constraints.htm#:~:text=EXCLUSION%20Constraint。

更新時間: 2021 年 2 月 2 日

178 次檢視

啟動您的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.