動機
突然想起來 有這種東西 就來重看一下
相依(叫參照或許比較好)
可以把table想成某種dict, 而這個dict的key是一種pair, 而pair丟到dict中,如果拿到只有一筆資料就是一種鍵 也就是相依
像是用學號去找就只會找到一個學生
一般來說會有許多種pair都可以拿到只有一筆資料,這個叫超鍵 把超鍵的項目去掉,去到不能再去掉就是候選鍵(對,這也可能有許多組合,學號、身分證) 從候選鍵選一種喜歡的就是主鍵
大概寫成code(pseudo-python)
table = {...}
superKey = [tup for tup in all_combination(table.keys()) if len(table[tup]) == 1].sort(key=lambda tup: len(tup))
def candicateKey():
keysIter = iter(superKey)
yield next(keysIter)
keys = candicateKey()
for tup in keys:
yielded = False
for possible_key in keysIter:
if tup.is_subset(possible_key):
continue
else:
yield possible_key
yielded = True
if not yielded:
raise StopIteration()
1NF
就是為了因應row不能放可變長度的array所以要把Item轉90度,也因為這樣我們有了後面的種種NF
至於那些新增、刪除與修改異常都是因為當初存可變長度的array的row不是struct 所以不可以用pointer直接改,要轉90度重複寫下原本struct的其他資料
2NF
其實接下去的NF都是把可以推導出來(或是叫找出)的item抽出去
- 看主鍵外的資料與主鍵的關係
- 部分相依
- 只有與主鍵的單個項目相依
- 完全相依
- 與主鍵的所有項目相依
- 部分相依
2NF就是把(針對主鍵的)部分相依抽出去,像A,B是主鍵
{A,B} -> {D, E, F} {B} -> {D, F}
D,F就是對B部分相依
像是有一個成績table
student ID, course ID, name, 總排名, grade
name與總排名很明顯只與student ID有關,所以可以抽出去
3NF
現在可依透過所有主鍵去filter出所有資料 3NF要看其他欄位能不能filter出其他資料
換言之,就是看主鍵外的資料有沒有與主鍵外的資料相依
這是在公三小?
像B是主鍵 {B} -> {D, F} {D} -> {F} 這樣可以把F抽出去,這就是3NF想做的
前面分出來的table
student ID,name, 總排名
在此name可以filter出總排名
所以還要再把name割出來
遞移相依: 像上面F就是透過D相依B,這就是遞移相依
2NF與3NF差在?
2NF是處理部分主鍵的相依 3NF是處理非主鍵的相依
但一般處理相依,或者應該說是分類cloumn,都是直接把有關的放在一起 所以,2NF與3NF看起來很像,因為都是處理重複的相依,但是兩者的範疇不同 同時順序也不一定或是先2NF再3NF
BCNF
看有沒有不為主鍵的項目可以相依到主鍵的某個項目? 有的話就抽出去把cycle打斷
假設 {A,B}是主鍵 但 {A, B} -> {C} {C} -> {B} 這樣就是一個cycle的fu
所以可以拆掉,有不同的拆法
- {A,C} 為主鍵,把{B,C}拉到另一張表
- {A,B} 為主鍵,把{B,C}拉到另一張表