# 練習 39:SQL 創建
> 原文:[Exercise 39: Creating with SQL](https://learncodethehardway.org/more-python-book/ex39.html)
> 譯者:[飛龍](https://github.com/wizardforcel)
> 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻譯](https://translate.google.cn/)
當我們談論首字母縮寫“CRUD”時,“C”代表“創建”,它不僅僅意味著創建表。這也意味著將數據插入到表中,并使用表和插入來鏈接表。由于我們需要一些表和一些數據來完成其余的 CRUD(增刪改查),我們開始學習如何在 SQL 中執行最基本的創建操作。
## 表的創建
我在簡介中說,可以對表內的數據執行“增刪改查”操作。你如何把表放在首要位置?通過對數據庫綱要(Schema)執行 CRUD ,第一個要學習的 SQL 語句是`CREATE`:
```sql
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
```
你可以將其放在一行中,但是我打算討論每一行,所以寫成了多行。這里是每行所做的事情:
`ex1.sql:1`
`CREATE TABLE`的起始,它提供了表的名稱`person`。這個部分之后,之后將你想要的字段放到括號里。
`ex1.sql:2`
`id`列,它用于準確確定每一行。列的格式是`NAME TYPE`,并且這里我假設,我需要一個`INTEGER`也是`PRIMARY KEY`。這樣做告訴 SQLite3 來將其特殊對待。
`ex1.sql:3~4`
`first_name`和`last_name`列。它們都是`TEXT`。
`ex1.sql:5`
`age`列,只是一個`INTEGER`。
`ex1.sql:6`
使用圓括號結束列的列表,之后是一個分號(`;`)。
## 創建多表的數據庫
創建一個表不是特別實用。我希望你現在創建三個表,你可以在里面儲存數據。
```sql
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
CREATE TABLE pet (
id INTEGER PRIMARY KEY,
name TEXT,
breed TEXT,
age INTEGER,
dead INTEGER
);
CREATE TABLE person_pet (
person_id INTEGER,
pet_id INTEGER
);
```
在此文件中,你正在為兩種數據類型制作表,然后將它們與第三個表“鏈接”在一起。人們稱這些“鏈接”表為“關系”,但沒有生命的非常愚蠢的人把所有表都成為“關系”,并且熱衷于使那些想要完成工作的人困惑。在我的書中,具有數據的表是“表”,將表連接在一起的表稱為“關系”。
這里沒有任何新東西,除非你看到`person_pet`,你會看到我已經寫了兩列:`person_id`和`pet_id`。將兩個表鏈接在一起,只是向`person_pet`插入一行。它擁有兩行的 ID 列的值,你想要鏈接它們。例如,如果`person `包含一行`id=20`,`pet`有一行`id=98`,然后假設這個人擁有這個寵物,你會將`person_id=20, pet_id=98`插入到`person_pet`關系(表)中。
在接下來的幾個練習中,我們將實際插入這樣的數據。
## 插入數據
你有了要處理的幾個表,所以現在我讓你使用`INSERT`命令,放進去一些數據:
```sql
INSERT INTO person (id, first_name, last_name, age)
VALUES (0, "Zed", "Shaw", 37);
INSERT INTO pet (id, name, breed, age, dead)
VALUES (0, "Fluffy", "Unicorn", 1000, 0);
INSERT INTO pet VALUES (1, "Gigantor", "Robot", 1, 1);
```
在這個文件中,我使用兩種不同形式的`INSERT`命令。第一種形式是更明確的風格,最有可能是你應該使用的東西。它指定要插入的列,后跟`VALUES`,然后要包括的數據。這兩個列表(列名和值)都在括號內,并以逗號分隔。
第七行的第二個版本是一個縮寫版本,它不指定列,而是依賴于表中的隱式順序。這種形式是危險的,因為你不知道你的語句實際訪問哪一列,并且某些數據庫對列沒有可靠的排序。當你真的很懶惰時,最好只用這種形式。
## 插入引用數據
在最后一節,你會在表中放滿人和寵物。唯一缺少的東西是,誰擁有什么寵物,這個數據存入`person_pet`表,如下所示:
```sql
INSERT INTO person_pet (person_id, pet_id) VALUES (0, 0);
INSERT INTO person_pet VALUES (0, 1);
```
我再次使用顯式格式,然后使用隱式格式。我使用我想要的`person`表的行`id`(這里是`0`),和我想要的`pet`表的行`id`(同樣,`0`是獨角獸,`1`是死去的機器人)。然后,我們向`person_pet`關系表中插入一行,用于人與寵物之間的每個“連接”。
## 挑戰練習
+ 創建另一個數據庫,但為其它東西創建其他`INTEGER`和`TEXT`字段,`person`可能擁有它們。
+ 在這些表中,我創建了第三個關系表來鏈接它們。你如何擺脫這個關系表`person_pet`,并將這些信息優雅放在`person`里面?這個變化暗示了什么?
+ 如果你可以把一行放入`person_pet`,你是否可以放多行?你如何記錄一個瘋狂的貓女士與 50 只貓?
+ 為人們可能擁有的汽車創建另一個表,并創建其對應的關系表。
+ 在你喜歡的搜索引擎中搜索“sqlite3 數據類型”,然后閱讀 [SQLite3 文檔中的數據類型](https://sqlite.org/datatype3.html)。記錄你可以使用什么類型,以及其他看起來很重要的東西。我們稍后會介紹。
+ 插入你自己和你的寵物(或像我這樣的虛擬寵物)。
+ 如果將上一個練習中的數據庫更改為沒有`person_pet`表,則使用該模式創建一個新數據庫,并將相同的信息插入到該數據庫中。
+ 回顧數據類型列表,并記錄不同類型所需的格式。例如,請注意你有多少種方式來寫入`TEXT`數據。
+ 為你和你的寵物添加關系。
+ 使用這張表,一只寵物可以被多于一個人擁有嗎?這在邏輯上是可能的嗎?家養的狗如何呢?嚴格來說,家庭中的每個人不是擁有它嗎?
+ 考慮上面的東西,并且考慮到你有一個替代設計,將`pet_id`放在`pearon`表中,哪種設計更適合這種情況?
## 深入學習
請閱讀 [SQLite3 `CREATE`命令的文檔](https://sqlite.org/lang_createtable.html),然后查看盡可能多的其他`CREATE`語句。你還應該閱讀 <https://sqlite.org/lang_insert.html> 上的`INSERT`文檔,這應該會引導你閱讀許多其他頁面。
- 笨辦法學 Python · 續 中文版
- 引言
- 第一部分:預備知識
- 練習 0:起步
- 練習 1:流程
- 練習 2:創造力
- 練習 3:質量
- 第二部分:簡單的黑魔法
- 練習 4:處理命令行參數
- 練習 5:cat
- 練習 6:find
- 練習 7:grep
- 練習 8:cut
- 練習 9:sed
- 練習 10:sort
- 練習 11:uniq
- 練習 12:復習
- 第三部分:數據結構
- 練習 13:單鏈表
- 練習 14:雙鏈表
- 練習 15:棧和隊列
- 練習 16:冒泡、快速和歸并排序
- 練習 17:字典
- 練習 18:性能測量
- 練習 19:改善性能
- 練習 20:二叉搜索樹
- 練習 21:二分搜索
- 練習 22:后綴數組
- 練習 23:三叉搜索樹
- 練習 24:URL 快速路由
- 第四部分:進階項目
- 練習 25:xargs
- 練習 26:hexdump
- 練習 27:tr
- 練習 28:sh
- 練習 29:diff和patch
- 第五部分:文本解析
- 練習 30:有限狀態機
- 練習 31:正則表達式
- 練習 32:掃描器
- 練習 33:解析器
- 練習 34:分析器
- 練習 35:解釋器
- 練習 36:簡單的計算器
- 練習 37:小型 BASIC
- 第六部分:SQL 和對象關系映射
- 練習 38:SQL 簡介
- 練習 39:SQL 創建
- 練習 40:SQL 讀取
- 練習 41:SQL 更新
- 練習 42:SQL 刪除
- 練習 43:SQL 管理
- 練習 44:使用 Python 的數據庫 API
- 練習 45:創建 ORM
- 第七部分:大作業
- 練習 46:blog
- 練習 47:bc
- 練習 48:ed
- 練習 49:sed
- 練習 50:vi
- 練習 51:lessweb
- 練習 52:moreweb