19. 使用MySQL之插入資料

hisun9發表於2024-11-06

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表。

img

然後建立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表結構如下:

img

再向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');  

img

最後,利用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表,確實成功插入:

img

這個例子使用INSERT SELECT從custnew中將所有資料匯入customers。SELECT語句從custnew檢索出要插入的值,而不是列出它們。SELECT中列出的每個列對應於customers表名後所跟的列表中的每個列。這條語句將插入多少行有賴於custnew表中有多少行。如果這個表為空,則沒有行被插入(也不產生錯誤,因為操作仍然是合法的)。如果這個表確實含有資料,則所有資料將被插入到customers。

補充:

  • INSERT SELECT中的列名:

    為簡單起見,這個例子在INSERT和SELECT語句中使用了相同的列名。但是,不一定要求列名匹配。事實上,MySQL甚至不關心SELECT返回的列名。它使用的是列的位置,因此SELECT中的第一列(不管其列名)將用來填充表列中指定的第一個列,第二列將用來填充表列中指定的第二個列,如此等等。這對於從使用不同列名的表中匯入資料是非常有用的。

INSERT SELECT中SELECT語句可包含WHERE子句以過濾插入的資料。

相關文章