Re: [請益] 資料庫的參考完整性限制

看板Soft_Job作者 (astt88)時間13年前 (2013/02/09 09:21), 編輯推噓3(3058)
留言61則, 5人參與, 最新討論串5/7 (看更多)
※ 引述《chucheng (時間太少事情太多)》之銘言: : ※ 引述《idforyou (ted)》之銘言: : : 定義一: : : 外來鍵必須為空值(NULL) : : 或是一個相匹配(Match)於其它關聯之主鍵的值。 : : 外來鍵有參考到某關聯的候選鍵(主鍵) 時,此候選鍵(主鍵) 必須存在。 : : 定義二: : : 外來鍵必須為全部空值或全部非空. : : 若全部非空,則必須在其他關聯中之主鍵存在相對應值 : : 定義一是某學校投影片 : : 定義二是某補習班講師講義所寫 : : 矛盾的是根據一的定義 好像外來鍵欄位 : : 有些值可以是NULL 有些值不用 : : 這樣好像跟二的定義衝突(必須全部空或全部非空) : : 不知道有沒有資料庫的高手大大 : : 可以提示小弟一下 : : 那個定義才是對的 感恩 : PK = Primary Key (主鍵) : FK = Foreign Key (外來鍵) : 情境一: PK 是"simple key" (單一欄位的key) : PK不可為Null,FK 可以是Null,或指向任一PK : 情境二:PK 是"compound Key" (由多欄位組成的key) : PK一樣不可Null,FK指向PK,要就有值,要就全設為Null : 不可以有部份Null 部份非Null 的情況(這不是廢話嗎…) : 簡單的講,Compound key是一個整體,Part of compound key 不是PK : 二個定義都是對的,一個講simple key,一個講compound key 一個資料表中,PK是讓你找到其中一筆資料的方法之一 PK的定義與設限,就是確保你用同樣的PK欄位值, 只要資料表的定義沒有改變,不論找多少次,都可以有效的找到其中一筆資料 所以PK不能有Null,也必須唯一, 這樣才能幫助找到資料表中其中一筆資料,而不是另一筆資料 若PK欄位有多個,也就是說,需要這麼多的欄位, 我才可以找到資料表中特定的一筆資料 FK主要的作用是讓你可以找到在另一個資料表中對應的某筆資料 所以FK要不就是Null,現在沒要對應另一個資料表的某筆資料 或是,必須可以完整有效的幫你找到另一個資料表的某筆資料 同理, 一個資料表A的PK有多個欄位時, 當資料表B有需要對應資料表A的某筆資料時, 就必需要儲存資料表A的PK欄位資料值,以便有效找到資料表A的某筆資料 若資料表B只儲存資料表A的眾多PK欄位之一或不全時, 可能在資料表A中找到多筆資料,當然就無法有效找到資料表A的某筆資料 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.105.83.207

02/09 11:55, , 1F
舉例: 身分證字號是我們的PK, (單一欄位 PK)
02/09 11:55, 1F

02/09 12:24, , 2F
在我實務的經驗,不推薦用身份證字號做人的PK
02/09 12:24, 2F

02/09 12:25, , 3F
因為遇到外國人怎麼辦?
02/09 12:25, 3F

02/09 12:26, , 4F
故意用錯的身份證字號,一堆人都用A123456789
02/09 12:26, 4F

02/09 12:27, , 5F
實務上,我比較傾向用流水號或GUID當PK
02/09 12:27, 5F

02/09 12:28, , 6F
多欄主鍵會讓程式複雜化,且查詢速度慢
02/09 12:28, 6F

02/09 12:30, , 7F
也不推薦用多欄主欄組成一個欄位做PK
02/09 12:30, 7F

02/09 12:33, , 8F
因為需要確保此主鍵與組成欄位的一致性
02/09 12:33, 8F

02/09 12:34, , 9F
且一般來說,用文字型態的PK欄位查詢速度比用數字型態的
02/09 12:34, 9F

02/09 12:34, , 10F
PK欄位速度還慢
02/09 12:34, 10F

02/09 12:39, , 11F
而且用多欄位組成一個欄位做PK,當組成欄位的資料有異動時
02/09 12:39, 11F

02/09 12:39, , 12F
除了要更新PK欄位、PK組成欄位、所有的FK也必需要變更
02/09 12:39, 12F

02/09 12:41, , 13F
請不要說,即然當成PK欄位,應該是不會被改變的資料
02/09 12:41, 13F

02/09 12:44, , 14F
以我的經驗來說,發生過很多次這種情況,而且還滿常見的
02/09 12:44, 14F

02/09 12:48, , 15F
客戶說要改這個資料,你說因為這是PK欄位所以不能改
02/09 12:48, 15F

02/09 12:50, , 16F
一定會被客戶抱怨,要改也要花很多功夫
02/09 12:50, 16F

02/09 12:50, , 17F
改一堆地方,還要確保無誤,工程滿浩大的
02/09 12:50, 17F

02/09 13:10, , 18F
有些候選鍵會因為需求的變更,變得無法唯一識別該筆資料
02/09 13:10, 18F

02/09 13:12, , 19F
這種PK失格,候選鍵失格的情況也是滿常見的
02/09 13:12, 19F

02/09 13:14, , 20F
外國人有護照號碼...
02/09 13:14, 20F

02/09 13:23, , 21F
每一國的護照號碼的編碼規格不一樣,也難保一定不會重覆
02/09 13:23, 21F

02/09 14:45, , 22F
就因為邊碼規格不一樣. 所以不會有重複...
02/09 14:45, 22F

02/09 14:47, , 23F
用流水號不好吧...
02/09 14:47, 23F

02/09 14:48, , 24F
因為像帳號的login,你不可能叫使用者死記自己的流水號吧
02/09 14:48, 24F

02/09 14:48, , 25F
或是像下單時, 若只提供客戶姓名時, 你能夠找出該使用
02/09 14:48, 25F

02/09 14:48, , 26F
者正確的流水號嗎?
02/09 14:48, 26F

02/09 14:48, , 27F
結果還是要靠使用者額外自訂一個不能重覆的id...
02/09 14:48, 27F

02/09 14:49, , 28F
且讓它們成為PK, 這樣比較好吧...
02/09 14:49, 28F

02/09 15:16, , 29F
姓名本來就會重覆,一堆菜市場名
02/09 15:16, 29F

02/09 15:17, , 30F
應該很少有系統在Login時,是用姓名login的
02/09 15:17, 30F

02/09 15:19, , 31F
通常會有另一個欄位存放使用者的登入帳號,
02/09 15:19, 31F

02/09 15:23, , 32F
通常登入帳號這欄位,我會加上UNIQUE INDEX
02/09 15:23, 32F

02/09 15:24, , 33F
流水號也是有分成給人看的,跟給系統看的
02/09 15:24, 33F

02/09 15:26, , 34F
登入帳號也不建議成為PK,因為使用者可能有種種理由要修改
02/09 15:26, 34F

02/09 15:29, , 35F
每個人有不同的設計理念,只是把我的經驗做分享
02/09 15:29, 35F

02/09 15:30, , 36F
有些來自血淋淋的經驗與教訓
02/09 15:30, 36F

02/09 17:47, , 37F
是可以這樣做沒錯...
02/09 17:47, 37F

02/09 17:48, , 38F
但當你任何想以id去做的查詢, 都要先query id, 或JOIN
02/09 17:48, 38F

02/09 17:48, , 39F
後才能查出的資料...
02/09 17:48, 39F

02/09 17:48, , 40F
以id去查詢的需求很少嗎?
02/09 17:48, 40F

02/09 17:49, , 41F
我想不見得, 尤其是後台的應用程式...
02/09 17:49, 41F

02/09 17:49, , 42F
而去改變id的需求很多嗎?
02/09 17:49, 42F

02/09 17:49, , 43F
我想也不見得, 因為放眼望去的網站, 允許你換id的也沒幾
02/09 17:49, 43F

02/09 17:49, , 44F
個...
02/09 17:49, 44F

02/09 19:22, , 45F
這要看需求,若你可以堅持登入帳號絕對不給換
02/09 19:22, 45F

02/09 19:24, , 46F
那麼其實用ID(登入帳號)當PK也可以
02/09 19:24, 46F

02/09 19:24, , 47F
其實ID也只有登入時需要而已,進入前後台後都可以不用ID
02/09 19:24, 47F

02/09 19:25, , 48F
而且改用PK欄位做查詢,只有部分需要輸入ID的查詢頁面
02/09 19:25, 48F

02/09 19:26, , 49F
才會查到ID (登入帳號)
02/09 19:26, 49F

02/09 19:29, , 50F
以我的經驗,需要用到登入帳號欄位的機會在登入、寄忘記密
02/09 19:29, 50F

02/09 19:30, , 51F
密碼函,查詢個人資料時
02/09 19:30, 51F

02/09 19:30, , 52F
其餘的情況,大都可以用PK查詢到需要的資料
02/09 19:30, 52F

02/09 20:33, , 53F
可能是我一直在專案型的公司上班
02/09 20:33, 53F

02/09 20:34, , 54F
當客戶變更需求說要某資料也要能修改,
02/09 20:34, 54F

02/09 20:34, , 55F
而這某資料剛好是資料表的PK欄位時,老闆也說OK時
02/09 20:34, 55F

02/09 20:34, , 56F
可能會改得非常辛苦,客戶可能不會知道這個資料就是PK
02/09 20:34, 56F

02/09 20:34, , 57F
你如何說服客戶說,某資料因為是PK,所以不能改?
02/09 20:34, 57F

02/09 20:35, , 58F
所以,我比較傾向任何使用者看得到的欄位都不能當做PK
02/09 20:35, 58F

02/09 20:35, , 59F
最多只能當候選鍵
02/09 20:35, 59F

02/09 20:35, , 60F
當然了,這些做法都是見人見智的,
02/09 20:35, 60F

02/09 20:36, , 61F
一切視需求跟情況而定,沒有什麼對錯
02/09 20:36, 61F
※ 編輯: astt88 來自: 59.105.83.207 (02/09 22:19)
文章代碼(AID): #1H5QIq5Y (Soft_Job)
討論串 (同標題文章)
文章代碼(AID): #1H5QIq5Y (Soft_Job)