昨天介紹的是欄位的約束,現在要來介紹關聯式資料表的約束
之前有提到 主鍵以及外鍵
主鍵就是資料表中,唯一、不能為空值的欄位,
之前的文章有提到關聯的方法,可以參考 整理資料表(一) 什麼是關聯式資料表?
今天更深入的了解,主鍵的常見型態,以及外見約束。
可以選擇自動遞增型的方式,也有人偏好用UUID(通用唯一識別碼)的格式,以前的購買單機版軟體的時候會有一組序號,讓你可以啟用你購買的軟體,就是類似這樣的ID(不知道會不會現在已經不知道有這種東西了! 哈哈哈xD)
自動遞增型的欄位之前有介紹到,可以不用寫入值,資料表會依照目前的序列自動+1
CREATE TABLE users (
id bigserial,
name varchar(255) NOT NULL,
email varchar(255),
permission varchar(50),
created_at timestamp,
updated_at timestamp,
CONSTRAINT email_unique UNIQUE (email),
CONSTRAINT check_permission_in_list CHECK (permission IN ('admin', 'member')),
CONSTRAINT users_pkey PRIMARY KEY (id)
);
如上方 SQL最後一行,設定 主鍵名稱 users_pkey 指向欄位 id,表示把 id 這個欄位設定為主鍵,必須唯一值且不能為null。
用特別的一段字串或數字來識別這筆資料,稱之為代理的主鍵,就像每個人有身分證,但是身分證只能表示這個人,並無法直接知道這個人的內容,如果全台灣名字不能重複,那也是可以用名字當主鍵,就不用身分證了! 哈哈哈 這舉例有點奇怪應該不太可能發生這樣的設計。
也可以結兩個以上的欄位當作主鍵
CREATE TABLE users (
name varchar(255) NOT NULL,
email varchar(255),
address varchar(255),
permission varchar(50),
created_at timestamp,
updated_at timestamp,
CONSTRAINT email_unique UNIQUE (email),
CONSTRAINT check_permission_in_list CHECK (permission IN ('admin', 'member')),
CONSTRAINT users_pkey PRIMARY KEY (name, address)
);
如上方 SQL 假設這個 users 資料表沒有 ID 欄位(我是沒有這樣應用在實際案子中,都會有一個代理鍵 id 來辨識),為了展示複合鍵,不建置 id欄位用 name, address 當複合建,就像最後一行一樣,表示這張資料表中,name 以及 address 的組合只會出現一次,不會有重複。
假設資料表中已經有 王小明,台北市信義區...,如果這時再插入一筆 王小明,台北市信義區... 資料庫就會顯示 users_pkey
已存在的錯誤訊息。
以上是主鍵,外鍵就是可以在另外一張表紀錄跟另外一張表的關聯,這系列一開始的文章有建立 animals 的資料表,表示紀錄動物的資料,每一筆資料如果加上一個欄位 users_id
就可以輕易的對應到 users 資料表中的一個使用者資料,表示使用者的名下有幾隻寵物。
之前有介紹過,當時沒有介紹到外鍵約束,因為想把文章用簡單一點,每一篇不要打太多,不然會懶得看,哈哈哈xD 這也是我最近的體悟,等等題外話的單元再來跟大家說。
先設想一個情況,假設這個使用者不想使用這個平台了!所以提出了刪除個資的要求,這時候刪除掉 users 這張資料表中的該名使用者,例如 id:王小明,這時候管理資料庫的,因為資料庫複雜,忘記動物的資料,可能有他新建的動物,沒有去刪除,那麼在應用程式讀取資料時,可能會造成,無法去比對動物是哪一位飼主飼養的(莫名其妙變流浪犬!)
所以這時候就要靠外鍵約束的功能了!刪除使用者資料時(刪除使用者 ID:1),顯示錯誤訊息,禁止刪除該使用者,因為他有關聯 animals 的動物資料未刪除,要先刪除動物資料才能刪除該使用者確保資料正確性!
另外示範一下,如果 animals 資料表,插入user_id 不存在於 users 資料表會發生錯誤的範例!
CREATE TABLE users (
id bigserial,
name varchar(255),
CONSTRAINT users_pkey PRIMARY KEY (id)
);
CREATE TABLE animals (
id bigserial PRIMARY KEY, --建立主鍵也可以這樣寫
name varchar(255),
user_id bigint REFERENCES users (id)
);
-- 新增一個使用者名稱為 Victor,若是第一次新建表,應該是會自動寫上 id:1
INSERT INTO users (name)
VALUES ('Victor');
-- 新增一筆動物資料
INSERT INTO animals (name, user_id)
VALUES ('黏黏', 1);
-- 新增一筆動物資料,user_id 不存在於 user 資料表中 將會顯示錯誤!
INSERT INTO animals (name, user_id)
VALUES ('大黑', 2);