# 練習 40:SQL 讀取
> 原文:[Exercise 40: Reading with SQL](https://learncodethehardway.org/more-python-book/ex40.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 矩陣中,你只知道“創建”。你可以創建表,你可以在這些表中創建行。現在我將告訴你如何“讀取”,或者在 SQL 中是`SELECT`:
```sql
SELECT * FROM person;
SELECT name, age FROM pet;
SELECT name, age FROM pet WHERE dead = 0;
SELECT * FROM person WHERE first_name != "Zed";
```
這里是每一行做的事情:
`ex5.sql:1`
這表示“從`person`中選擇所有列并返回所有行”。`SELECT`的格式是`SELECT what FROM tables(s) WHERE (tests)`,`WHERE`子句是可選的。`*`(星號)字符是你想要的所有列。
`ex5.sql:3`
這里我只要從`pet`表請求兩列,`name`和`age`。它將返回所有行。
`ex5.sql:5`
現在我正在從`pet`尋找相同的列,但是我只請求`dead = 0`的行。這會給我所有的活著的寵物。
`ex5.sql:7`
最后,我從`person`選擇所有列,就像在第一行,但我現在指明,它們不等于`"Zed"`。`WHERE`子句決定哪一行返回,哪一行不返回。
## 選擇多表
希望你現在專注于選擇數據。永遠記住這一點:SQL 只知道表。SQL 喜歡表。SQL 僅返回表。表,表,表,表! 我以這種非常瘋狂的方式重復一遍,以便你將開始意識到,你在編程中知道的東西不會有幫助。你在編程中處理圖,在 SQL 中處理表。他們是相關的概念,但心智模型是不同的。
這里是一個例子,它們哪里不一樣。假設你想知道 Zed 擁有什么寵物。你需要寫一個`SELECT`,在`person`中查找,然后“以某種方式”找到我的寵物。為此,你必須查詢`person_pet`表來獲取所需的`id`列。以下是我的做事方式:
```sql
SELECT pet.id, pet.name, pet.age, pet.dead
FROM pet, person_pet, person
WHERE
pet.id = person_pet.pet_id AND
person_pet.person_id = person.id AND
person.first_name = "Zed";
```
現在它看起來很龐大,但我會把它拆解,所以你可以看到,他只是簡單構造新的表,基于三個表中的數據,和`WHERE`子句。
`ex6.sql:1`
我僅僅想要`pet`中的一些列,所以我在選擇中指定它們。在上一個練習中,你使用`*`來表示“每一列”,但它在這里是一個壞主意。相反,你想要明確地指定你想要的每個表中的哪個列,你可以使用`table.column`實現它,就像`pet.name`。
`ex6.sql:2`
為了將`pet`連接到`person`,我需要遍歷`person_pet`關系表。在 SQL 中,這意味著我需要在`FROM`之后列出所有三個表。
`ex6.sql:3`
`WHERE`子句的開始。
`ex6.sql:4`
首先,我將`pet`連接到`person_pet`,通過相關 ID 列`pet.id`和`person_pet.id`。
`ex6.sql:5`
并且我需要以相同的方式,將人`person`連接到`person_pet`。現在,數據庫可以僅僅搜索 id 列全部匹配的行,這些就是連接的行。
`ex6.sql:6`
我最后僅僅請求自己擁有的寵物,通過為我的名稱添加`person.first_name`測試。
## 挑戰練習
+ 寫一個查詢,查找所有超過 10 年的寵物。
+ 寫一個查詢,查找所有比你年輕的人。然后查找比你年長的人。
+ 編寫一個查詢,`WHERE`子句中使用多于一個測試,使用`AND`來編寫它。例如`WHERE first_name = "Zed" AND age > 30`。
+ 執行另一個查詢,使用三個條件,并使用`AND`和`OR`運算符來搜索行。
+ 如果你已經知道像 Python 或 Ruby 這樣的語言,這可能是一個查看數據的令人驚奇的方式。花時間使用類和對象來構建相同的關系,然后將其映射到此配置。
+ 執行一個查詢,查找你到目前為止添加的寵物。
+ 更改查詢來使用你的`person.id`而不是`person.name`,像我一樣。
+ 瀏覽運行的輸出,并確保你知道哪些 SQL 命令生成了哪個表,以及如何生成該輸出。
## 深入學習
通過閱讀[`SELECT`命令的文檔](https://sqlite.org/lang_select.html),繼續深入了解 SQLite3,同時閱讀[`EXPLAIN QUERY PLAN`功能的文檔](https://sqlite.org/eqp.html)。如果你不知道為什么 SQLite3 做了一些事情,`EXPLAIN`是你的答案。
- 笨辦法學 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