1. 程式人生 > >關於資料庫的外來鍵和主鍵

關於資料庫的外來鍵和主鍵

轉自:http://blog.csdn.net/championhengyi/article/details/78559789

什麼是主鍵、外來鍵

關係型資料庫中的一條記錄中有若干個屬性,若其中某一個屬性組(注意是組)能唯一標識一條記錄,該屬性組就可以成為一個主鍵。

比如:

學生表(學號,姓名,性別,班級) 
其中每個學生的學號是唯一的,學號就是一個主鍵

課程表(課程編號,課程名,學分) 
其中課程編號是唯一的,課程編號就是一個主鍵

成績表(學號,課程號,成績) 
成績表中單一一個屬性無法唯一標識一條記錄,學號和課程號的組合才可以唯一標識一條記錄,所以學號和課程號的屬性組是一個主鍵

成績表中的學號不是成績表的主鍵,但它和學生表中的學號相對應,並且學生表中的學號是學生表的主鍵,則稱成績表中的學號是學生表的外來鍵。

同理:成績表中的課程號是課程表的外來鍵。

定義主鍵和外來鍵主要是為了維護關係資料庫的完整性,總結一下:

1.主鍵是能確定一條記錄的唯一標識,比如,一條記錄包括身份正號,姓名,年齡。身份證號是唯一能確定你這個人的,其他都可能有重複,所以,身份證號是主鍵。

2.外來鍵用於與另一張表的關聯。是能確定另一張表記錄的欄位,用於保持資料的一致性。比如,A表中的一個欄位,是B表的主鍵,那他就可以是A表的外來鍵。

主鍵、外來鍵和索引的區別

主鍵外來鍵索引
定義唯一標識一條記錄,不能有重複的,不允許為NULL表的外來鍵是另一表的主鍵, 外來鍵可以有重複的, 可以是NULL沒有重複值,可以為NULL(會使索引無效)
作用用來保證資料完整性用來和其他表建立聯絡用的提高查詢排序的速度
個數主鍵只能有一個一個表可以有多個外來鍵一個表可以有多個惟一索引

外來鍵約束

在上面“什麼是主鍵、外來鍵” 一小節中,我給大家灌輸的思維是,學生表使用學號作為主鍵,課程表使用課程ID作為主鍵,成績表使用學號、課程ID作為聯合主鍵(聯合主鍵(使用組合索引進行替代)以後壓根就別用,主鍵的設計原則就是欄位數目越少越好),這樣就產成了一個問題,外來鍵的參考鍵必須是另一個表的主鍵嗎?

答案當然不是,但是參考鍵必須是唯一性索引。主鍵約束和唯一性約束都是唯一性索引。

錯誤的設計方式—[1215] Cannot add foreign key constraint

出現這種問題的原因一般有兩個:

1.兩張表裡要設主鍵和外來鍵的欄位的資料型別或者資料長度不一樣。 
2.某個表裡已經有記錄了。

我當時屬於第一個。

如何設計良好的資料庫主鍵

摘抄一位知乎使用者的回答:知乎連結—紀路

主鍵的話我的建議是自增整形,不要使用與業務相關的名字,僅用id即可,而效率問題都可以用索引來解決。因為主鍵的不可變的特性,如果選擇不慎,會在未來產生難以預期的問題。比如你用int型做文章的id,但是如果在未來某一天文章數超過了無符號整形的最大值,你將沒法將主鍵修改成bigint。或者為了給使用者起一個唯一id用了自增主鍵,但是如果未來有其他的專案使用者要合併進來,他也是這麼做的。這時候為了區分不同的專案可能要在這個使用者id前加一個字首,這時候也沒法修改主鍵的值。主鍵之所以叫做主鍵就是到什麼時候都不能改,所以最好的方案就是使用自增數字id做主鍵,並且不要給這個主鍵賦予一個業務相關的意義。

總結上面前輩的一句話就是,不要將表中與業務相關的欄位設定為主鍵,即使它可以唯一標識這一行,比如身份證號,學號等等,主鍵越沒有意義,說明主鍵設定的越好

主鍵、外來鍵的使用

建立表

就按照我們上面的例子來建立三張表吧:student、course、score表。

建立student表:

create table student
(
    pk_id bigint unsigned not null auto_increment primary key,
    uk_sno int(10) unsigned not null,
    name char(60) not null,
    sex char(10) not null,
    class char(60) not null,
    constraint uk_sno unique (sno)
)enige = InnoDB, charset = utf8
;

建立course表:

create table course
(
    pk_id bigint unsigned not null auto_increment primary key,
    uk_course_id int(10) unsigned not null,
    course_name char(30) not null,
    credit int not null,
    constraint uk_course_id unique (course_id)
)enige = InnoDB, charset=utf8
;

建立score表:

create table score
(
    pk_id bigint not null auto_increment primary key,
    fk_sno int(10) unsigned not null,
    fk_course_id int(10) unsigned not null,
    result int not null,
    constraint fk_sno foreign key (fk_sno) references <databasename>.student (sno),
    constraint fk_course_id foreign key (fk_course_id) references <databasename>.course (course_id)
)enige = InnoDB, charset=utf8
;

值得一說的是,建立外來鍵的時候也會自動建立普通索引,所以fk_sno、fk_course_id其實是兩個普通索引的名稱。

對於使用IDEA的同學,我們會發現在設定外來鍵的時候還有Update rule 和 Delete rule規則,對於這兩個選項的解釋,我們下面再說。

這裡寫圖片描述

外來鍵的使用–更新與刪除

表已經建立成功,現在我們插入資料: 
student表:

INSERT INTO student(uk_sno, name, sex, class) VALUES(123456, "spider_hgyi", "male", "cs");

crouse表:

INSERT INTO course(uk_course_id, course_name, credit) VALUES(1, "csapp", 10);

score表:

INSERT INTO score(fk_sno, fk_course_id, result) VALUES(123456, 1, 100);

好了,現在三個表裡都已經有了資料,現在我們嘗試更新學生表中學號的資訊:

UPDATE student SET uk_sno=12345678 WHERE uk_sno=123456;

MySQL報錯:

(1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`bookmanager`.`score`, CONSTRAINT `fk_sno` FOREIGN KEY (`fk_sno`) REFERENCES `student` (`uk_sno`))')

看看錯誤告訴我們什麼:不能刪除或更新這一行,存在外來鍵約束,score表中的fk_sno列是當前要更新的uk_sno的外來鍵,也就是說,你要更新學生表中的學號,但是成績表中的學號是你的外來鍵,你不能不管它呀,刪除也是同理。

要怎麼解決?

還記得剛才我貼的那張IDEA的圖片嗎?那兩個規則就可以幫助我們解決這個問題。

級聯刪除與更新

我們在更新與刪除時遇到的外來鍵約束解決方案分別對應設定Update rule與Delete rule。有如下四個選項:

1.CASCADE:從父表刪除或更新且自動刪除或更新子表中匹配的行。 
2.SET NULL:從父表刪除或更新行,並設定子表中的外來鍵列為NULL。如果使用該選項,必須保證子表列沒有指定NOT NULL。 
3.RESTRICT:拒絕對父表的刪除或更新操作。 
4.NO ACTION:標準SQL的關鍵字,在MySQL中與RESTRICT相同。

可以看到我在建立外來鍵的時候選擇的是NO ACTION,也就是第三個選項。我們只需要選擇CASCADE就可以啦。具體效果就不進行演示了。

如果你不用IDEA也沒關係,接下來我給出SQL語句的實現(重新建立score表):

create table score
(
    pk_id bigint not null auto_increment primary key,
    fk_sno int(10) unsigned not null,
    fk_course_id int(10) unsigned not null,
    result int not null,
    constraint fk_sno foreign key (fk_sno) references <databasename>.student (sno) on update cascade on delete cascade,
    constraint fk_course_id foreign key (fk_course_id) references <databasename>.course (course_id) on update cascade on delete cascade
)enige = InnoDB, charset=utf8
;

相關推薦

關於資料庫外來

轉自:http://blog.csdn.net/championhengyi/article/details/78559789什麼是主鍵、外來鍵關係型資料庫中的一條記錄中有若干個屬性,若其中某一個屬性組(注意是組)能唯一標識一條記錄,該屬性組就可以成為一個主鍵。比如:學生表(

Oracle中如何建立約束,查詢約束刪除約束(check約束,外來約束)

Oracle  建立主鍵,外來鍵, check約束的幾種方法:(write by RFH) 1. 在建立表時建立約束: //新增主鍵約束 Create table userinfo (userid number(20)constraint  pk_user  primary

資料庫之SQL的外來的作用

SQL的主鍵和外來鍵約束 SQL的主鍵和外來鍵的作用: 外來鍵取值規則:空值或參照的主鍵值。 (1)插入非空值時,如果主鍵表中沒有這個值,則不能插入。 (2)更新時,不能改為主鍵表中沒有的值。 (3)刪除主鍵表記錄時,你可以在建外來鍵時選定外來鍵記錄一起級聯

資料庫——超、候選外來

首先看看各種鍵的定義: 超鍵(super key):在關係中能唯一標識元組的屬性集稱為關係模式的超鍵 候選鍵(candidate key):不含有多餘屬性的超鍵稱為候選鍵 主鍵(primary key):使用者選作元組標識的一個候選鍵程式主鍵 外來鍵(foreig

MySQL中的查詢約束語句、聯合外來

查詢語句 過濾空值 過濾空值 如果該值是空的 就當做0來處理 SELECT IFNULL(欄位名,0) FROM 表名 聚合函式 排序 利用ORD

Hibernate實體類編寫規則策略

有時 由於 rem 數據 數據類型 空間 存在 配置 hyper 一、實體類的編寫規則   1、屬性要是私有的。        2、要有公開的setter和getter方法供外界訪問和修改。        3、每一個實體類要有一個屬性作為唯一值(一般都是使用對於數據表的

關於

主表 通過 更新 控制 數據緩沖 計算機 wid 但是 detail 數據庫主鍵和外鍵 1 什麽是主鍵 外鍵  學生表(學號,姓名,性別,班級)   學號是一個主鍵  課程表(課程號,課程名,學分)    課程號是一個主鍵  成績表(學號,課程號,成績)    

SQL server :

技術分享 div 標識 reference create reat 按鈕 sse 是的 1.定義 1.1 什麽是主鍵和外鍵 1.2 主鍵和外鍵的作用 1.3 主鍵、外鍵和索引的區別 2.主鍵(primary key) 2.1 通過SSMS設置主鍵 2.2 通過SQL語

關於

tick not null 規則 更新 主鍵 join table 插入 out SQL的主鍵和外鍵的作用: 外鍵取值規則:空值或參照的主鍵值。 (1)插入非空值時,如果主鍵表中沒有這個值,則不能插入。 (2)更新時,不能改為主鍵表中沒有的值。 (3)刪除主鍵表記錄時,你可

Hibernate工具類生成策略

建立hibernate的好處 1.方便獲取session繪畫,用來操作資料庫 2.用來檢測所有的對映檔案配置是否準確 package com.two.util; import org.hibernate.Session; import org.hibernate.SessionFact

MyBatis的sql對映檔案(CRUDid生成)

一個好的講解mybatis的部落格地址http://www.jianshu.com/nb/5226994 官方文件:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html Mapper XML 檔案 MyBatis 的真正強大在於它的對映語

Hibernate及MyBatis獲取資料庫新插入記錄id

記錄一下Hibernate以及MyBatis往資料庫插入一條新紀錄,獲取這條新紀錄的id的方法。 1.Hibernate HIbernate插入資料時執行save()方法,執行完該方法之後,實體類物件就已經有了在資料庫中的id值,呼叫getId方法就可以獲取id,簡單示例如下: Pers

資料庫】Mysql中的幾種表設計組合的實際應用效果

寫在前面         前前後後忙忙碌碌,度過了新工作的三個月。部落格許久未新,似乎對忙碌沒有一點點防備。總結下來三個月不斷的磨礪自己,努力從獨樂樂轉變到眾樂樂,體會到不一樣的是,連辦公室的新玩意都能引起莫名的興趣了,作為一隻忙碌的 “猿” 倒不知正常與否。         咳咳, 正題, 今天要寫一篇

快速理解資料庫,候選

先了解下對這三種關鍵碼的定義如下: 鍵名 定義 超鍵 (super key) 在關係中能唯一標識元組的屬性或屬性集稱為關鍵模式的超鍵 候選鍵 (candida

分散式資料庫當然也有的需求,但是為什麼不直接使用uuid作為主呢?

1. UUID生成速率低下 Java的UUID依賴於SecureRandom.nextBytes方法,而SecureRandom又依賴於作業系統提供的隨機數源,在Linux系統下,它的預設依賴是/dev/random,而這個源是阻塞的。最可怕的是,這個nextBytes方法

oracle 查詢索引

ORACLE: 1、查主鍵名稱: select * from user_constraints where table_name = 'AAA' and constraint_type ='P';  查主鍵對應的列: select * from u

、候選外來、聯合、複合

首先看看各種鍵的定義: 超鍵(super key):在關係中能唯一標識元組的屬性集稱為關係模式的超鍵(只要有一個鍵唯一,再隨便組其他的鍵,合起來叫主鍵) 候選鍵(candidatekey):不含有多餘屬性的超鍵稱為候選鍵(最小的超鍵,ID,身份證號) 主鍵(primary key):

資料庫:ORACLE設定自動遞增

建立表STUDENT   假設主鍵為ID一、先設定遞增:    設定遞增需要建立序列,在plsql找到sequence,右鍵點選新建                名稱隨便起一個  這裡為s_student. 其他的數字如圖二、建立觸發器        sql:       

mybatis+mysql/oracle 資料庫批量插入,自增長

1 mybatis+oracle <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc6 --> <dependency> <groupId>com.oracle&

SQL Server 向資料庫表中新增

        SQL Server 資料庫,向已設定主鍵的資料庫表中插入新一列,並設為主鍵。         首先從基礎知識開始看,         建表: create table 表名