1. 資料插入
顧名思義,INSERT是用來插入(或新增)行到資料庫表的。插入可以用幾種方式使用:
-
插入完整的行;
-
插入行的一部分;
-
插入多行;
-
插入某些查詢的結果。
補充:
插入及系統安全:
可針對每個表或每個使用者,利用MySQL的安全機制禁止使用INSERT語句,這將在第28章介紹
2. 插入完整的行
把資料插入表中的最簡單的方法是使用基本的INSERT語法,它要求指定表名和被插入到新行中的值。
-
比如:
insert into customers values(null, 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', null, null);
補充:
-
沒有輸出:
INSERT語句一般不會產生輸出。
此例子插入一個新客戶到customers表。
儲存到每個表列中的資料在VALUES子句中給出,對每個列必須提供一個值。如果某個列沒有值(如上面的cust_contact和cust_email列),應該使用NULL值(假定表允許對該列指定空值)。
各個列必須以它們在表定義中出現的次序填充。
第一列cust_id也為NULL。這是因為每次插入一個新行時,該列由MySQL自動增量。你不想給出一個值(這是MySQL的工作),又不能省略此列(如前所述,必須給出每個列),所以指定一個NULL值(它被MySQL忽略,MySQL在這裡插入下一個可用的cust_id值)。
雖然這種語法很簡單,但並不安全,應該儘量避免使用。
上面的SQL語句高度依賴於表中列的定義次序,並且還依賴於其次序容易獲得的資訊。即使可得到這種次序資訊,也不能保證下一次表結構變動後各個列保持完全相同的次序。
因此,編寫依賴於特定列次序的SQL語句是很不安全的。如果這樣做,有時難免會出問題。
-
-
編寫INSERT語句的更安全(不過更煩瑣)的方法如下:
insert into customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) values('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', null, null);
此例子完成與前一個INSERT語句完全相同的工作,但在表名後的括號裡明確地給出了列名。
在插入行時,MySQL將用VALUES列表中的相應值填入列表中的對應項。VALUES中的第一個值對應於第一個指定的列名。第二個值對應於第二個列名,如此等等。
因為提供了列名,VALUES必須以其指定的次序匹配指定的列名,不一定按各個列出現在實際表中的次序。
其優點是,即使表的結構改變,此INSERT語句仍然能正確工作。
會發現cust_id的NULL值是不必要的,cust_id列並沒有出現在列表中,所以不需要任何值。
-
下面的INSERT語句填充所有列(與前面的一樣),但以一種不同的次序填充。因為給出了列名,所以插入結果仍然正確:
insert into customers(cust_name, cust_contact, cust_email, cust_address, cust_city, cust_state, cust_zip, cust_country) values('Pep E. LaPew', null, null, '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA');
-
使用這種語法,還可以省略列。這表示可以只給某些列提供值,給其他列不提供值。(事實上你已經看到過這樣的例子:當列名被明確列出時,cust_id可以省略。)
補充:
-
總是使用列的列表:
一般不要使用沒有明確給出列的列表的INSERT語句。使用列的列表能使SQL程式碼繼續發揮作用,即使表結構發生了變化。
-
仔細地給出值:
不管使用哪種INSERT語法,都必須給出VALUES的正確數目。如果不提供列名,則必須給每個表列提供一個值。如果提供列名,則必須對每個列出的列給出一個值。如果不這樣,將產生一條錯誤訊息,相應的行插入不成功。
-
省略列:
如果表的定義允許,則可以在INSERT操作中省略某些列。省略的列必須滿足以下某個條件。
-
該列定義為允許NULL值(無值或空值)。
-
在表定義中給出預設值。這表示如果不給出值,將使用預設值。如果對錶中不允許NULL值且沒有預設值的列不給出值,則MySQL將產生一條錯誤訊息,並且相應的行插入不成功。
-
-
提高整體效能:
資料庫經常被多個客戶訪問,對處理什麼請求以及用什麼次序處理進行管理是MySQL的任務。INSERT操作可能很耗時(特別是有很多索引需要更新時),而且它可能降低等待處理的SELECT語句的效能。
如果資料檢索是最重要的(通常是這樣),則可以透過在INSERT和INTO之間新增關鍵字
LOW_PRIORITY
,指示MySQL降低INSERT語句的優先順序,如下所示:insert low_priority into
順便說一下,這也適用於下一章介紹的UPDATE和DELETE語句。
3. 插入多個行
INSERT可以插入一行到一個表中。但如果你想插入多個行怎麼辦?
-
可以使用多條INSERT語句,甚至一次提交它們,每條語句用一個分號結束。
比如:
insert into customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) values('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA'); insert into customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) values('M. Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA');
-
或者,只要每條INSERT語句中的列名(和次序)相同,可以如下組合各語句:
insert into customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) values('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA'), ('M. Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA');
其中單條INSERT語句有多組值,每組值用一對圓括號括起來,用逗號分隔。
4. 插入檢索出的資料
INSERT一般用來給表插入一個指定列值的行。
但是,INSERT還存在另一種形式,可以利用它將一條SELECT語句的結果插入表中。這就是所謂的INSERT SELECT,顧名思義,它是由一條INSERT語句和一條SELECT語句組成的。
假如你想從另一表中合併客戶列表到你的customers表。不需要每次讀取一行,然後再將它用INSERT插入,可以如下進行:
注意:
-
新例子的說明:
這個例子把一個名為custnew的表中的資料匯入customers表中。為了試驗這個例子,應該首先建立和填充custnew表。custnew表的結構與customers表的相同。在填充custnew時,不應該使用已經在customers中使用過的cust_id值(如果主鍵值重複,後續的INSERT操作將會失敗)或僅省略這列值讓MySQL在匯入資料的過程中產生新值。
首先利用describe customers
命令得出customers表的結構,便於後續建立custnew表。
然後建立custnew表:
create table custnew
(
cust_name char(50) not null,
cust_address char(50) null,
cust_city char(50) null,
cust_state char(5) null,
cust_zip char(10) null,
cust_country char(50) null,
cust_contact char(50) null,
cust_email char(255) null
);
custnew表結構如下:
再向custnew表中插入資料:
insert into custnew(cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
values('whq',
'jiangnan university',
'wuxi',
'AS',
'12345',
'China'),
('hisun',
'poyang',
'jiangxi',
'AS',
'23456',
'China');
最後,利用INSERT SELECT語句將custnew表中的資料匯入customers表:
insert into customers(cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
select cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
from custnew;
看下customers表,確實成功插入:
這個例子使用INSERT SELECT從custnew中將所有資料匯入customers。SELECT語句從custnew檢索出要插入的值,而不是列出它們。SELECT中列出的每個列對應於customers表名後所跟的列表中的每個列。這條語句將插入多少行有賴於custnew表中有多少行。如果這個表為空,則沒有行被插入(也不產生錯誤,因為操作仍然是合法的)。如果這個表確實含有資料,則所有資料將被插入到customers。
補充:
-
INSERT SELECT中的列名:
為簡單起見,這個例子在INSERT和SELECT語句中使用了相同的列名。但是,不一定要求列名匹配。事實上,MySQL甚至不關心SELECT返回的列名。它使用的是列的位置,因此SELECT中的第一列(不管其列名)將用來填充表列中指定的第一個列,第二列將用來填充表列中指定的第二個列,如此等等。這對於從使用不同列名的表中匯入資料是非常有用的。
INSERT SELECT中SELECT語句可包含WHERE子句以過濾插入的資料。