練習(xí) 39:SQL 創(chuàng)建
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
當(dāng)我們談?wù)撌鬃帜缚s寫“CRUD”時(shí),“C”代表“創(chuàng)建”,它不僅僅意味著創(chuàng)建表。這也意味著將數(shù)據(jù)插入到表中,并使用表和插入來鏈接表。由于我們需要一些表和一些數(shù)據(jù)來完成其余的 CRUD(增刪改查),我們開始學(xué)習(xí)如何在 SQL 中執(zhí)行最基本的創(chuàng)建操作。
表的創(chuàng)建
我在簡(jiǎn)介中說,可以對(duì)表內(nèi)的數(shù)據(jù)執(zhí)行“增刪改查”操作。你如何把表放在首要位置?通過對(duì)數(shù)據(jù)庫綱要(Schema)執(zhí)行 CRUD ,第一個(gè)要學(xué)習(xí)的 SQL 語句是CREATE:
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
你可以將其放在一行中,但是我打算討論每一行,所以寫成了多行。這里是每行所做的事情:
ex1.sql:1
CREATE TABLE的起始,它提供了表的名稱person。這個(gè)部分之后,之后將你想要的字段放到括號(hào)里。
ex1.sql:2
id列,它用于準(zhǔn)確確定每一行。列的格式是NAME TYPE,并且這里我假設(shè),我需要一個(gè)INTEGER也是PRIMARY KEY。這樣做告訴 SQLite3 來將其特殊對(duì)待。
ex1.sql:3~4
first_name和last_name列。它們都是TEXT。
ex1.sql:5
age列,只是一個(gè)INTEGER。
ex1.sql:6
使用圓括號(hào)結(jié)束列的列表,之后是一個(gè)分號(hào)(;)。
創(chuàng)建多表的數(shù)據(jù)庫
創(chuàng)建一個(gè)表不是特別實(shí)用。我希望你現(xiàn)在創(chuàng)建三個(gè)表,你可以在里面儲(chǔ)存數(shù)據(jù)。
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
);
在此文件中,你正在為兩種數(shù)據(jù)類型制作表,然后將它們與第三個(gè)表“鏈接”在一起。人們稱這些“鏈接”表為“關(guān)系”,但沒有生命的非常愚蠢的人把所有表都成為“關(guān)系”,并且熱衷于使那些想要完成工作的人困惑。在我的書中,具有數(shù)據(jù)的表是“表”,將表連接在一起的表稱為“關(guān)系”。
這里沒有任何新東西,除非你看到person_pet,你會(huì)看到我已經(jīng)寫了兩列:person_id和pet_id。將兩個(gè)表鏈接在一起,只是向person_pet插入一行。它擁有兩行的 ID 列的值,你想要鏈接它們。例如,如果person包含一行id=20,pet有一行id=98,然后假設(shè)這個(gè)人擁有這個(gè)寵物,你會(huì)將person_id=20, pet_id=98插入到person_pet關(guān)系(表)中。
在接下來的幾個(gè)練習(xí)中,我們將實(shí)際插入這樣的數(shù)據(jù)。
插入數(shù)據(jù)
你有了要處理的幾個(gè)表,所以現(xiàn)在我讓你使用INSERT命令,放進(jìn)去一些數(shù)據(jù):
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);
在這個(gè)文件中,我使用兩種不同形式的INSERT命令。第一種形式是更明確的風(fēng)格,最有可能是你應(yīng)該使用的東西。它指定要插入的列,后跟VALUES,然后要包括的數(shù)據(jù)。這兩個(gè)列表(列名和值)都在括號(hào)內(nèi),并以逗號(hào)分隔。
第七行的第二個(gè)版本是一個(gè)縮寫版本,它不指定列,而是依賴于表中的隱式順序。這種形式是危險(xiǎn)的,因?yàn)槟悴恢滥愕恼Z句實(shí)際訪問哪一列,并且某些數(shù)據(jù)庫對(duì)列沒有可靠的排序。當(dāng)你真的很懶惰時(shí),最好只用這種形式。
插入引用數(shù)據(jù)
在最后一節(jié),你會(huì)在表中放滿人和寵物。唯一缺少的東西是,誰擁有什么寵物,這個(gè)數(shù)據(jù)存入person_pet表,如下所示:
INSERT INTO person_pet (person_id, pet_id) VALUES (0, 0);
INSERT INTO person_pet VALUES (0, 1);
我再次使用顯式格式,然后使用隱式格式。我使用我想要的person表的行id(這里是0),和我想要的pet表的行id(同樣,0是獨(dú)角獸,1是死去的機(jī)器人)。然后,我們向person_pet關(guān)系表中插入一行,用于人與寵物之間的每個(gè)“連接”。
挑戰(zhàn)練習(xí)
- 創(chuàng)建另一個(gè)數(shù)據(jù)庫,但為其它東西創(chuàng)建其他
INTEGER和TEXT字段,person可能擁有它們。 - 在這些表中,我創(chuàng)建了第三個(gè)關(guān)系表來鏈接它們。你如何擺脫這個(gè)關(guān)系表
person_pet,并將這些信息優(yōu)雅放在person里面?這個(gè)變化暗示了什么? - 如果你可以把一行放入
person_pet,你是否可以放多行?你如何記錄一個(gè)瘋狂的貓女士與 50 只貓? - 為人們可能擁有的汽車創(chuàng)建另一個(gè)表,并創(chuàng)建其對(duì)應(yīng)的關(guān)系表。
- 在你喜歡的搜索引擎中搜索“sqlite3 數(shù)據(jù)類型”,然后閱讀 SQLite3 文檔中的數(shù)據(jù)類型。記錄你可以使用什么類型,以及其他看起來很重要的東西。我們稍后會(huì)介紹。
- 插入你自己和你的寵物(或像我這樣的虛擬寵物)。
- 如果將上一個(gè)練習(xí)中的數(shù)據(jù)庫更改為沒有
person_pet表,則使用該模式創(chuàng)建一個(gè)新數(shù)據(jù)庫,并將相同的信息插入到該數(shù)據(jù)庫中。 - 回顧數(shù)據(jù)類型列表,并記錄不同類型所需的格式。例如,請(qǐng)注意你有多少種方式來寫入
TEXT數(shù)據(jù)。 - 為你和你的寵物添加關(guān)系。
- 使用這張表,一只寵物可以被多于一個(gè)人擁有嗎?這在邏輯上是可能的嗎?家養(yǎng)的狗如何呢?嚴(yán)格來說,家庭中的每個(gè)人不是擁有它嗎?
- 考慮上面的東西,并且考慮到你有一個(gè)替代設(shè)計(jì),將
pet_id放在pearon表中,哪種設(shè)計(jì)更適合這種情況?
深入學(xué)習(xí)
請(qǐng)閱讀 SQLite3 CREATE命令的文檔,然后查看盡可能多的其他CREATE語句。你還應(yīng)該閱讀 https://sqlite.org/lang_insert.html 上的INSERT文檔,這應(yīng)該會(huì)引導(dǎo)你閱讀許多其他頁面。