## 課堂筆記 一個表格只能有一個主鍵(PK),但可以有多個外來鍵(FK)。 口訣:多的要設計成外來鍵,例如:一個部門會有多個員工。 主鍵(PK): ➊ 必須是唯一值,不能重複。 ➋ 不能是Null值,但外來鍵可以。 ➌ 設定後不應再更動。 外來鍵(FK): ➊ 當資料需要關聯到其他表格時才會用到。 ➋ 必須對應到被參考資料表的主鍵。 ➌ 命名通常會用'參考資料表_id'的格式。 [Postgres SQL指令](https://hackmd.io/@HCZvma86RdqPySqRGogXRA/ryZHj-v-yl) <br> ## 作業一:拯救明華國小的資料庫,哪個欄位適合變成外來鍵? ![image](https://hackmd.io/_uploads/S1l6uz8-yx.png) >[!TIP]思考方式 >[miro資料庫關聯圖](https://miro.com/app/board/uXjVLJydqsQ=/?share_link_id=240893456501) >因為一個班級有多個學生、一個性別有多個學生,所以「班級」、「性別」是外來鍵。建立students、class、genders資料表,最後再合併顯示資料。 ### 建立class資料表,新增資料 ``` --製作資料表 CREATE TABLE class( c_id SERIAL PRIMARY KEY, c_name VARCHAR(50) ); --新增資料 INSERT INTO class(c_name)VALUES ('三年一班'), ('三年二班'); ``` ### 顯示class資料表 ``` SELECT c_id AS 班級編號, c_name AS 班級 FROM class; ``` ![image](https://hackmd.io/_uploads/Sk6sr9XZ1l.png) ### 建立genders資料表,新增資料 ``` --製作資料表 CREATE TABLE genders( g_id SERIAL PRIMARY KEY, gender VARCHAR(50) ); --新增資料 INSERT INTO genders(gender)VALUES ('女'), ('男'); ``` ### 顯示genders資料表 ``` SELECT g_id AS 性別編號, gender AS 性別 FROM genders; ``` ![image](https://hackmd.io/_uploads/BknZPc7Zkl.png) ### 建立students資料表,新增資料 ``` --製作資料表 CREATE TABLE students( st_id SERIAL PRIMARY KEY, st_name VARCHAR(50), class_id INTEGER, --因為要顯示class資料表的PK,所以資料類型是INTEGER gender_id INTEGER, --因為要顯示genders資料表的PK,所以資料類型是INTEGER age INTEGER, FOREIGN KEY(class_id)REFERENCES class(c_id), --外來鍵 FOREIGN KEY(gender_id)REFERENCES genders(g_id) --外來鍵 ); --新增資料 INSERT INTO students(st_name,class_id,gender_id,age)VALUES ('小明',1,2,8), ('小華',2,1,9), ('小美',1,2,8), ('小強',1,1,8), ('小智',2,2,9); ``` ![image](https://hackmd.io/_uploads/SyNAmf8Z1l.png) ### 顯示students資料表 ``` SELECT students.st_id AS 學生編號, --資料表.欄位名稱 students.st_name AS 姓名, class.c_name AS 班級, genders.gender AS 性別, students.age AS 年齡 FROM students --只寫主表 INNER JOIN class ON students.class_id=class.c_id --不用加逗號或分號 INNER JOIN genders ON students.gender_id=genders.g_id; ``` ![image](https://hackmd.io/_uploads/rJqs7fIb1g.png) <br> ## 作業二:第一題的延伸,多了一個班級老師 ![image](https://hackmd.io/_uploads/rk1PYM8Z1l.png) >[!TIP]思考方式 >students資料表要建立一欄「班級老師」,然後更新students資料表每一筆資料的老師名字。最後再合併顯示students、class、genders資料表。 ### students資料表新增teacher_name欄位(欄位內的資料是Null) ``` ALTER TABLE students --不用加逗號或分號 要新增欄位的資料表 ADD COLUMN teacher_name VARCHAR(50); --欄位名稱 資料類型 ``` ### 更新students資料表teacher_name欄位資料 ``` UPDATE students SET teacher_name='廖淯杰' WHERE st_name='小明'; UPDATE students SET teacher_name='卡斯伯' WHERE st_name='小華'; UPDATE students SET teacher_name='查理' WHERE st_name='小美'; UPDATE students SET teacher_name='麥可' WHERE st_name='小強'; UPDATE students SET teacher_name='李燕容' WHERE st_name='小智'; ``` ### 顯示資料(合併students、class、genders資料表) ``` SELECT students.st_id AS 學生編號, students.st_name AS 姓名, class.c_name AS 班級, students.teacher_name AS 班級老師, genders.gender AS 性別, students.age AS 年齡 FROM students INNER JOIN class ON students.class_id=class.c_id INNER JOIN genders ON students.gender_id=genders.g_id; ``` ![image](https://hackmd.io/_uploads/B1ekpG7L-kl.png) <br> ## 作業三:小孩的家庭歸類資料庫,父母資料一值重複實在討厭! ![image](https://hackmd.io/_uploads/HyQXXX8Zkx.png) >[!TIP]思考方式 >[miro資料庫關聯圖](https://miro.com/app/board/uXjVLJydqsQ=/?share_link_id=240893456501) >建立parents資料表,然後students資料表新增一欄「家長編號 p_id(foreign key)」,再更新students資料表每一筆資料的家長編號資料。最後合併顯示students和parents資料表。 ### 建立parents資料表,新增資料 ``` CREATE TABLE parents( p_id SERIAL PRIMARY KEY, p_name VARCHAR(50), p_phone INTEGER, p_gender VARCHAR(50) ); INSERT INTO parents(p_name,p_phone,p_gender)VALUES ('王大祥',0973254254,'男'), ('王曉如',0955717855,'女'); ``` ### students資料表新增p_id欄位,設為FK ``` ALTER TABLE students --要新增欄位的資料表 ADD COLUMN p_id INTEGER, --欄位名稱 資料類型 ADD FOREIGN KEY(p_id) REFERENCES parents(p_id); --外來鍵 ``` ### 更新students資料表p_id欄位資料 ``` UPDATE students SET p_id=1 WHERE st_id IN(1,3,5); UPDATE students SET p_id=2 WHERE st_id IN(2,4); ``` ### 顯示資料(合併students、parents資料表) ``` SELECT students.st_id AS 小孩編號, students.st_name AS 姓名, parents.p_name AS 父母名稱, parents.p_phone AS 父母電話, parents.p_gender AS 父母性別 FROM students INNER JOIN parents ON students.p_id=parents.p_id; ``` ![image](https://hackmd.io/_uploads/HJt1QVL-kl.png) <br> ## 延伸作業:學校新開設了音樂班,聘請了一位美女老師擔任班導,王大祥家長的小孩都想轉到音樂班就讀。 >[!TIP]思考方式 >class資料表先新增音樂班,然後students資料表篩選王大祥後,更新class_id、teacher_name欄位資料,最後合併顯示資料。 ### class資料表新增音樂班 ``` INSERT INTO class(c_name)VALUES ('音樂班'); ``` ### 更新王大祥的老師和班級資料 ``` UPDATE students SET teacher_name='美女老師' WHERE p_id=1; UPDATE students SET class_id=3 WHERE p_id=1; ``` ### 顯示資料(合併students、class、genders、parents資料表) ``` SELECT students.st_id AS 學生編號, students.st_name AS 姓名, class.c_name AS 班級, students.teacher_name AS 班級老師, genders.gender AS 性別, students.age AS 年齡, parents.p_name AS 父母名稱 FROM students INNER JOIN class ON students.class_id=class.c_id INNER JOIN genders ON students.gender_id=genders.g_id INNER JOIN parents ON students.p_id=parents.p_id; ``` ![image](https://hackmd.io/_uploads/HyeV1rU-ke.png)