SQLite | 数据库设计与 Creat Table 语句
文章目錄
- 1. The SurgeTech Conference
- 1.1 Attendee
- 1.2 Company
- 1.3 Presentation
- 1.4 Room
- 1.5 Presentation Attendance
- 2. 主鍵與外鍵
- 2.1 主鍵
- 2.2 外鍵
- 3. The Schema
- 4. 創建數據庫
- 4.1 創建表格
- 4.2 設置外鍵約束
- 參考資料
我們在上一篇中介紹了 Join,接下來我們將介紹數據庫設計。
1. The SurgeTech Conference
假如你是一個名為 SurgeTech 會議的管理人員,今天老大叫你創建一個數據庫來管理參會人員(attendees),公司(companies),演講(presentations),會議室(rooms)以及演講者(oresentation attendance),你該怎么來設計呢?
首先,想一下這些不同的對象,應該如何轉換為結構化的數據,這看起來很麻煩,但再麻煩的問題都可以化成許許多多的小問題。
1.1 Attendee
參會人員指的就是那些需要來簽到的人員(包含了部分的 VIPs),需要登記到每個參會人員的 ID、姓名、手機號、郵箱以及是否 VIP:
圖1 Attendee 表1.2 Company
參會的公司也需要記錄,包含公司的 ID、公司名、公司簡介以及聯系人(聯系人也應該包含在上方的參會人員):
圖2 Company 表1.3 Presentation
一些公司會在特定的時間進行演講(包含了演講開始時間和結束時間),因此需要記錄每場演講的公司 ID 以及會議室 ID:
圖3 Presentation 表1.4 Room
會議室的編號、樓層以及座位數需要記錄:
圖4 Room 表1.5 Presentation Attendance
如果參會者對某個公司的演講感興趣,他們可以申請一張入場券。為了實現這個功能,就需要制作一張聽眾表,來記錄入場券編號、演講編號以及聽眾編號:
圖5 Presentation Attendance 表2. 主鍵與外鍵
2.1 主鍵
對于一個表,主鍵(Primary Key) 是必不可少的。主鍵能夠一一對應到每一行數據,通常是某一列不重復的數據(或者某幾列)。比如 ATTENDEE_ID 就是在表 ATTENDEE 的主鍵,而 COMPANY_ID 是表 COMPANY 的主鍵。
由于主鍵中的不允許有重復,因此也起到著確保數據完整性的約束作用。不可重復意味著在表 ATTENDEE 中不能出現兩個 ATTEND_ID 為 2 的數據,否則將會導致錯誤。
如果某幾列數據作為一個整體充當表的主鍵,那么就要求這幾列數據的組合不能夠重復。舉個例子,如果你將 REPORT_ID 和 APPROVER_ID 設為主鍵,那么就不能出現有相同 REPORT_ID 和 APPROVER_ID 的記錄
2.2 外鍵
主鍵(Primary Key)出現在父表(Parent Table)中,而外鍵(Foreign Key)則出現在子表(Child Table)中。子表中的外鍵指向父表中的主鍵,舉個例子。ATTENDEE_ID 是 ATTENDEE 表的主鍵,但在 PRESENTATION_ATTENDANCE 表中 ATTENDEE_ID 則是一個外鍵。這兩個聯合在一起就成為了一個一對多的關系,而不像主鍵,外鍵并不要求唯一性,因為它就是一對多關系中的多。
主鍵和外鍵并不需要有相同的列名,如子表 PRESENTATION 中的外鍵 BOOKED_COMPANY_ID 指向父表 COMPANY 中的主鍵 COMPANY_ID。
3. The Schema
在了解了主鍵和外鍵后,我們可以將這五個表畫成一個 Database Schema,如下圖所示。一個 Database Schema 展示了所有的表、列以及以及它們的關系。所有的主鍵和外鍵都用箭頭連接起來了,這些箭頭展示了父表與子表之間的聯系。
在數據庫中,schema(模式)是數據庫的組織和結構[1]
圖6 The SurgeTech Conference Database Schema如果你直接看這個圖的話可能會有點暈,但再復雜的結構都可以分成幾個簡單的部分。當你用 SELECT 寫查詢時,最多也就用到兩三個表,所以你可以先看一部分,這樣會容易一點:
圖7 父表 ATTENDEE 與子表 COMPANY 的關系圖4. 創建數據庫
-
使用Jupyter Notebook 運行 SQL 語句需安裝 ipython-sql
-
%sql 以及 %%sql 為在 Notebook 中運行 SQL 語句,在 SQLite 命令行或 SQLite Stiduo 中不需要 %sql 或 %%sql
載入 SQL 以及連接 SQLite:
%load_ext sql我們已經設計好整個數據庫的結構了,現在就可以看是創建數據庫了,運行下面的代碼,你就可以在你的當前路徑的 DataBase 文件夾中產生一個名為 surgetech_conference2.db 的數據庫文件:
%sql sqlite:///DataBase/surgetech_conference2.db 'Connected: @DataBase/surgetech_conference2.db'4.1 創建表格
圖8 Attendee 表以剛才的 Company 表為例,我們希望:
- ATTENDEE_ID 是一個整形(INTERGER)數據,并且將其設為主鍵(PRIMARY KEY),同時能夠自動標號(AUTOINCREMENT),即第一個 ATTENDEE_ID 為 1 ,第二個 ATTENDEE_ID 為 2,以此類推;
- FIRST_NAME 是長度不超過 30 的字符數據(VARCHAR)并且不能為缺失值(NOT NULL);
- LAST_NAME 是長度不超過 30 的字符數據(VARCHAR)并且不能為缺失值(NOT NULL);
- PHONE 為整形(INTERGER)數據
- EMAIL 是長度不超過 30 的字符數據(VARCHAR);
- VIP 為布爾型數據(BOOLEAN)并且默認值為 0
4.2 設置外鍵約束
我們剛剛創建的表格其實還是不夠安全的,因為并沒有設置外鍵約束,要記得子表的外鍵與父表的主鍵連接在一起。因此邏輯上,對于主鍵中沒有出現過的數值,就不應該出現在子鍵中。
舉個例子,如果父表 COMPANY 的主鍵 COMPANY_ID 中沒有 5 這個數值,則子表 PRESENTATION 的外鍵 BOOKED_COMPANY_ID 中就不應該出現 5,否則就是一個孤兒數據(Orphaned record),我們可以通過設置外間約束來避免這種情況。
從 SQLite 3.6.19 開始支持 外鍵約束
SQLite 默認沒有打開外鍵約束,若需要使用外鍵約束,需要設置 'PRAGMA foreign_keys = ON;
%%sql PRAGMA foreign_keys = ON; * sqlite:///DataBase/surgetech_conference2.db Done.現在我們可以利用圖 6 來創建其他的表并設置外鍵約束了:
%%sql CREATE TABLE company (company_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(30) NOT NULL,description VARCHAR(60),primary_contact_id INTEGER NOT NULL REFERENCES attendee(attendee_id) );CREATE TABLE room (room_id INTEGER PRIMARY KEY AUTOINCREMENT, floor_number INTEGER NOT NULL,seat_capacity INTEGER NOT NULL );CREATE TABLE presentation (presentation_id INTEGER PRIMARY KEY AUTOINCREMENT, booked_company_id INTEGER NOT NULL REFERENCES company(compangy_id),booked_room_id INTEGER NOT NULL REFERENCES room(room_id),start_time TIME,end_time TIME );CREATE TABLE presentation_attendance (ticket_id INTEGER PRIMARY KEY AUTOINCREMENT, presentation_id INTEGER REFERENCES presentation(presentation_id),attendee_id INTEGER REFERENCES attendee(attendee_id) ); * sqlite:///DataBase/surgetech_conference2.db Done. Done. Done. Done.你可以查看下是否創建成功:
%%sql select * from sqlite_master where type = "table"; * sqlite:///DataBase/surgetech_conference2.db Done.| table | attendee | attendee | 2 | CREATE TABLE attendee ( attendee_id INTEGER PRIMARY KEY AUTOINCREMENT, first_name VARCHAR (30) NOT NULL, last_name VARCHAR (30) NOT NULL, phone INTEGER, email VARCHAR (30), vip BOOLEAN DEFAULT (0) ) |
| table | sqlite_sequence | sqlite_sequence | 3 | CREATE TABLE sqlite_sequence(name,seq) |
| table | company | company | 4 | CREATE TABLE company ( company_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(30) NOT NULL, description VARCHAR(60), primary_contact_id INTEGER NOT NULL REFERENCES attendee(attendee_id) ) |
| table | room | room | 5 | CREATE TABLE room ( room_id INTEGER PRIMARY KEY AUTOINCREMENT, floor_number INTEGER NOT NULL, seat_capacity INTEGER NOT NULL ) |
| table | presentation | presentation | 6 | CREATE TABLE presentation ( presentation_id INTEGER PRIMARY KEY AUTOINCREMENT, booked_company_id INTEGER NOT NULL REFERENCES company(compangy_id), booked_room_id INTEGER NOT NULL REFERENCES room(room_id), start_time TIME, end_time TIME ) |
| table | presentation_attendance | presentation_attendance | 7 | CREATE TABLE presentation_attendance ( ticket_id INTEGER PRIMARY KEY AUTOINCREMENT, presentation_id INTEGER REFERENCES presentation(presentation_id), attendee_id INTEGER REFERENCES attendee(attendee_id) ) |
參考資料
[1] 我是康小小.數據庫中的Schema是什么?[EB/OL].https://blog.csdn.net/u010429286/article/details/79022484, 2018-01-10.
[2] Thomas Nield.Getting Started with SQL[M].US: O’Reilly, 2016: 67-89
相關文章:
SQL | 目錄
SQLite | Select
SQLite | Where
SQLite | Group by and Order by
SQLite | CASE Statements
SQLite | Join
SQLite | SQLite 與 Pandas 比較篇之一
總結
以上是生活随笔為你收集整理的SQLite | 数据库设计与 Creat Table 语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在CentOS 5/6上安装EPEL
- 下一篇: SQLite | Join 语句