由於自己的孤陋寡聞, 也由於之前的項目中, 很少參與過數據庫模塊的開發, 以至於前幾天才知道Sqlite數據庫也支持replace語句。 本文主要講解在Sqlite中replace語句的行爲,也算是學習筆記。此外, replace語句和update語句有相似的地方, 但是也有很多不同之處。 本文還要對比一下Sqlite中的 replace語句和update語句 。
在本例中使用如下數據庫表:
(圖 1)
該表的表名爲student, 存儲學生信息。 所有字段的數據類型都是TEXT 。 其中id和name作爲複合主鍵。 email字段加上了唯一約束。建表語句如下:
1
2
3
4
5
6
7
8
9
10
|
CREATE
TABLE
IF NOT
EXISTS student ( "id"
TEXT, "name"
TEXT NOT
NULL , "sex"
TEXT, "email"
TEXT UNIQUE , "fenshu"
TEXT CHECK (fenshu
> 0), "tecid"
TEXT REFERENCES
teacher(id), "class"
TEXT, PRIMARY
KEY (id,
name )
) |
replace語句的行爲
1 replace語句會刪除原有的一條記錄, 並且插入一條新的記錄來替換原記錄。
爲了驗證這個結論, 下面打開Sqlite命令行, 執行以下語句來替換id爲2的記錄。
1
2
|
sqlite>
replace
into
student (id, name ,
sex, email, fenshu, tecid, class) values |
(圖 2)
對比圖1和圖2 , 可以發現: 在圖1中, id爲2 的記錄是表中的第一條記錄, 當執行完上述的replace語句之後, id爲2的記錄位於整張表的最後。 這就說明, 這條replace語句刪除了原有的id爲2的記錄, 有插入了一條新的id爲2的記錄。
2 一般用replace語句替換一條記錄的所有列, 如果在replace語句中沒有指定某列, 在replace之後這列的值被置空 。
下面我們還是以id爲2 的記錄做實驗, 執行如下語句:
1
2
|
sqlite>
replace
into
student (id, name ,
sex, email, fenshu, tecid) values
( '2' , |
(圖 3)
對比圖2和圖3 , 可以看到, id爲2, name爲lisi的記錄的class字段沒有值。
3 replace根據主鍵確定被替換的是哪一條記錄
在該表中, 把id和name指定爲複合主鍵。 在上面兩條語句執行的時候, 都在values中指定了id爲2, name爲lisi 。 執行之後看到的結果也是id爲2, name爲lisi的記錄被替換。 這就說明了replace語句根據主鍵的值確定被替換的是哪一條記錄。
4 replace語句不能根據where子句來定位要被替換的記錄
執行以下語句:
1
2
|
sqlite>
replace
into
student (id, name ,
sex, email, fenshu, tecid) values
( '2' , |
1
|
Error:
near "where" :
syntax error |
5 如果執行replace語句時, 不存在要替換的記錄, 那麼就會插入一條新的記錄。
在student表中, 我們讓id和name成爲複合主鍵。 下面我們使用replace語句替換id爲100, name爲a 的記錄。 從圖3中可以看到, 表中存在name爲a的記錄, 但是這條記錄的id爲7, 而不是100 。也就是說 id爲100, name爲a 的記錄不存在。
執行如下語句:
1
2
|
sqlite>
replace
into
student (id, name ,
sex, email, fenshu, tecid, class) values |
(圖 4)
可以看到, 在表中插入了一條新的記錄。
6 如果新插入的或替換的記錄中, 有字段和表中的其他記錄衝突, 那麼會刪除那條其他記錄。
上面的第5步同時也說明了這個問題。 對比圖4 和圖5 , 發現在插入一條新的id爲100, name爲a的記錄之後, 還刪除了id爲2, name爲lisi的記錄。 爲什麼會這樣呢? 我們在開始的時候說過, 表中的email字段加上了唯一約束。 id爲2的記錄的email和新插入的id爲100的記錄中的email相同, 都是[email protected] 。 這就導致違反唯一約束, 所以在插入id爲100的記錄之前, 刪除了id爲2的記錄。
下面再次驗證一下。 現在我們替換id爲5, name爲lisi3 的記錄, 將它的email替換爲[email protected] 。 表中的id爲5的記錄的email字段也是[email protected] , 所以會導致違反唯一約束。
執行下面的語句:
1
2
|
sqlite>
replace
into
student (id, name ,
sex, email, fenshu, tecid, class) values |
(圖 5)
對比圖4 和 圖5 , 發現id爲5的記錄被替換掉, 並且把這條記錄的email設置爲[email protected], 這和圖4中原有的id爲6的記錄衝突, 所以導致id爲6的記錄被刪除, 在圖5 中已經沒有id爲6的那條記錄了。
replace語句和update語句的對比
對於update語句, 因爲經常使用到,應該算比較熟悉。 下面對比一下update和replace語句的行爲, 只是簡單陳述, 不再以具體實例說明。
update語句使用where子句定位被更新的記錄;
update語句可以一次更新一條記錄, 也可以更新多條記錄, 只要這多條記錄都複合where子句的要求;
update只會在原記錄上更新字段的值, 不會刪除原有記錄, 然後再插入新紀錄;
如果在update語句中沒有指定一些字段, 那麼這些字段維持原有的值, 而不會被置空;