LOAD DATA INFILE語法

13.2.5. LOAD DATA INFILE語法

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name

.txt'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name


    [FIELDS
        [TERMINATED BY 'string

']
        [[OPTIONALLY] ENCLOSED BY 'char

']
        [ESCAPED BY 'char

' ]
    ]
    [LINES
        [STARTING BY 'string

']
        [TERMINATED BY 'string

']
    ]
    [IGNORE number

 LINES]
    [(col_name_or_user_var

,...)]
    [SET col_name

 = expr

,...)]

LOAD DATA INFILE 語句用於高速地從一個文本文件中讀取行,並裝入一個表中。文件名稱必須爲一個文字字符串。

要了解有關INSERTLOAD DATA INFILE 的效率的對比和有關LOAD DATA INFILE 加速的更多信息,請參見7.2.16節,“INSERT語句的速度”

character_set_database 系統變量指示的字符集被用於解釋文件中的信息。SET NAMEScharacter_set_client 的設置不會影響對輸入的解釋。

注意,目前不能載入UCS2 數據文件。

您也可以通過使用mysqlimport 應用程序載入數據文件;通過向服務器發送一個LOAD DATA INFILE 語句實現此功能。--local 選項用於使mysqlimport 從客戶主機中讀取數據文件。如果客戶端和服務器支持壓縮協議,則您可以指定—compress 選項提高在慢速網絡中的性能。請參見8.10節,“mysqlimport:數據導入程序

如果您使用LOW_PRIORITY ,則LOAD DATA 語句的執行被延遲,直到沒有其它的客戶端從表中讀取爲止。

如果一個MyISAM 表滿足同時插入的條件(即該表在中間有空閒塊),並且您對這個MyISAM 表指定了CONCURRENT ,則當LOAD DATA 正在執行時,其它線程會從表中重新獲取數據。即使沒有其它線程在同時使用本表格,使用本選項也會略微影響LOAD DATA 的性能。

如果指定了LOCAL ,則被認爲與連接的客戶端有關:

·         如果指定了LOCAL ,則文件會被客戶主機上的客戶端讀取,並被髮送到服務器。文件會被給予一個完整的路徑名稱,以指定確切的位置。如果給定的是一個相對的路徑名稱,則此名稱會被理解爲相對於啓動客戶端時所在的目錄。

·         如果LOCAL 沒有被指定,則文件必須位於服務器主機上,並且被服務器直接讀取。

當在服務器主機上爲文件定位時,服務器使用以下規則:

·         如果給定了一個絕對的路徑名稱,則服務器使用此路徑名稱。

·         如果給定了帶有一個或多個引導組件的相對路徑名稱,則服務器會搜索相對於服務器數據目錄的文件。

·         如果給定了一個不帶引導組件的文件名稱,則服務器會在默認數據庫的數據庫目錄中尋找文件。

注意,這些規則意味着名爲./myfile.txt 的文件會從服務器數據目錄中被讀取,而名爲myfile.txt 的同樣的文件會從默認數據庫的數據庫目錄中讀取。例如,下面的LOAD DATA 語句會從db1 數據庫目錄中讀取文件data.txt ,因爲db1 是當前數據庫。即使語句明確把文件載入到db2 數據庫中的表裏,也會從db1 目錄中讀取。

mysql> USE db1;


mysql> LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;


注意,使用正斜槓指定Windows 路徑名稱,而不是使用反斜槓。如果您使用反斜槓,您必須使用兩個。

出於安全原因,當讀取位於服務器中的文本文件時,文件必須位於數據庫目錄中,或者是全體可讀的。另外,要對服務器文件使用LOAD DATA INFILE ,您必須擁有FILE 權限。

5.7.3節,“MySQL提供的權限”

與讓服務器直接讀取文件相比,使用LOCAL 速度略慢,這是因爲文件的內容必須通過客戶端發送到服務器上。不過,您不需要FILE 權限來載入本地文件。

只有當您的服務器和您的客戶端都許可時,LOCAL 纔可運行。例如,如果使用—local-infile=0 啓動mysqld ,則LOCAL 不運行。請參見5.6.4節,“LOAD DATA LOCAL安全問題”

如果您需要LOAD DATA 來從一個管道中讀取,您可以使用以下方法(此處我們把/ 目錄清單載入一個表格):

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
find / -ls > /mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

有些輸入記錄把原有的記錄複製到唯一關鍵字值上。REPLACEIGNORE 關鍵字用於控制這些輸入記錄的操作。

如果您指定了REPLACE ,則輸入行會替換原有行(換句話說,與原有行一樣,對一個主索引或唯一索引具有相同值的行)。請參見13.2.6節,“REPLACE語法”

如果您指定IGNORE ,則把原有行復制到唯一關鍵字值的輸入行被跳過。如果您這兩個選項都不指定,則運行情況根據LOCAL 關鍵詞是否被指定而定。不使用LOCAL 時,當出現重複關鍵字值時,會發生錯誤,並且剩下的文本文件被忽略。使用LOCAL 時,默認的運行情況和IGNORE 被指定時的情況相同;這是因爲在運行中間,服務器沒有辦法中止文件的傳輸。

如果您希望在載入運行過程中忽略外鍵的限制,您可以在執行LOAD DATA 前發送一個SET FOREIGN_KEY_CHECKS=0 語句。

如果您對一個空的MyISAM 表使用LOAD DATA INFILE ,則所有的非唯一索引會被創建在一個獨立批中(對於REPAIR TABLE )。當您有許多索引時,這通常會使LOAD DATA INFILE 大大加快。通常,LOAD DATA INFILE 的速度會非常快,但是在某些極端情況下,您可以在把文件載入到表中之前使用ALTER TABLE...DISABLE KEYS 關閉LOAD DATA INFILE ,或者在載入文件之後使用ALTER TABLE...ENABLE KEYS 再次創建索引,使創建索引的速度更快。請參見7.2.16節,“INSERT語句的速度”

LOAD DATA INFILESELECT...INTO OUTFILE 的補語。(見13.2.7節,“SELECT語法” 。)要從一個表中把數據寫入一個文件中,應使用SELECT...INTO OUTFILE 。要讀取文件,放回到表中,應使用LOAD DATA INFILEFIELDSLINES 子句的語法對於兩個語句是一樣的。兩個子句都是自選的,但是如果兩個都被指定了,FIELDS 必須位於LINES 的前面。

如果您指定了一個FIELDS 子句,則每個亞子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BYESCAPED BY )也是自選的。不過,您必須指定其中至少一個。

如果您不指定FIELDS 子句,則默認值爲假設您寫下如下語句時的值:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

如果您不指定LINES 子句,則默認值爲假設您寫下如下語句時的值:

LINES TERMINATED BY '\n' STARTING BY ''

換句話說,當讀取輸入值時,默認值會使LOAD DATA INFILE 按如下方式運行:

·         在新行處尋找行的邊界。

·         不會跳過任何行前綴。

·         在製表符處把行分解爲字段。

·         不希望字段被包含在任何引號字符之中。

·         出現製表符、新行、或在‘\ ’前有‘\ ’時,理解爲作爲字段值一部分的文字字符。

相反的,當編寫輸出值時,默認值會使SELECT...INTO OUTFILE 按如下方式運行:

·         在字段之間寫入製表符。

·         不把字段包含在任何引號字符中。

·         當字段值中出現製表符、新行或‘\ ’時,使用‘\ ’進行轉義。

·         在行的末端寫入新行。

注意,要寫入FIELDS ESCAPED BY \\ ’,您必須爲待讀取的值指定兩個反斜槓,作爲一個單反斜槓使用。

註釋:如果您已經在Windows 系統中生成了文本文件,您可能必須使用LINES TERMINATED BY \r\n ’來正確地讀取文件,因爲Windows 程序通常使用兩個字符作爲一個行終止符。部分程序,比如WordPad ,當編寫文件時,可能會使用\r 作爲行終止符。要讀取這樣的文件,應使用LINES TERMINATED BY \r ’。

如果所有您希望讀入的行都含有一個您希望忽略的共用前綴,則您可以使用'prefix_string ' 來跳過前綴(和前綴前的字符)。如果某行不包括前綴,則整個行被跳過。註釋:prefix_string 會出現在一行的中間。

示例:

mysql> LOAD DATA INFILE '/tmp/test.txt'


    -> INTO TABLE test LINES STARTING BY "xxx";


使用此語句,您可以讀入包含有如下內容的文件:

xxx"row",1
something xxx"row",2

並只得到數據("row",1)("row",2)

IGNORE number LINES 選項可以被用於在文件的開始處忽略行。例如,您可以使用IGNORE 1 LINES 來跳過一個包含列名稱的起始標題行:

mysql> LOAD DATA INFILE '/tmp/test.txt'


    -> INTO TABLE test IGNORE 1 LINES;


當您聯合使用SELECT...INTO OUTFILELOAD DATA INFILE 來從一個數據庫中把數據寫入一個文件中,然後再讀取文件,返回到數據庫中時,用於兩個語句的field-line-handling 選項必須匹配。否則,LOAD DATA INFILE 不會正確地理解文件的內容。假設您使用SELECT...INTO OUTFILE 來編寫一個的文件,字段由逗號分隔:

mysql> SELECT * INTO OUTFILE 'data.txt'


    ->          FIELDS TERMINATED BY ','


    ->          FROM table2;


要讀取由逗號分隔的文件並返回,則正確的語句應該是:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2


    ->           FIELDS TERMINATED BY ',';


如果您嘗試使用以下所示的語句讀入文件,則不會運行,因爲該語句命令LOAD DATA INFILE 尋找位於字段之間的製表符:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2


    ->           FIELDS TERMINATED BY '\t';


結果很可能是,每個輸入行被理解爲一個單一字段。

LOAD DATA INFILE 也可以被用於讀取從外源中獲取的文件。例如,一個dBASE 格式的文件具有以逗號分隔並且包含在雙引號中的字段。如果文件中的各行以新行爲結尾,則此處所示的語句描述了您可以用於載入文件的field-line-handling 選項:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name



    ->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'


    ->           LINES TERMINATED BY '\n';


所有field-line-handling 選項都可以指定一個空字符串('' ) 。如果字符串不是空的,則FIELDS [OPTIONALLY] ENCLOSED BYFIELDS ESCAPED BY 值必須爲單一字符。FIELDS TERMINATED BY, LINES STARTING BYLINES TERMINATED BY 值可以超過一個字符。例如,要編寫由回車/ 換行成對字符作爲結尾的行,或讀取包含這類行的文件,則應指定一個LINES TERMINATED BY \r\n ’子句。

如果jokes 被由%% 組成的行分隔,要讀取包含jokes 的文件,您可以這麼操作:

mysql> CREATE TABLE jokes


    ->     (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,


    ->     joke TEXT NOT NULL);


mysql> LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes


    ->     FIELDS TERMINATED BY ''


    ->     LINES TERMINATED BY '\n%%\n' (joke);


FIELDS [OPTIONALLY] ENCLOSED BY 用於控制字段的引號。對於(SELECT...INTO OUTFILE ),如果您忽略了詞語OPTIONALLY ,則所有的字段都被包含在ENCLOSED BY 字符串中。此處展示了此類輸出的一個示例(使用逗號作爲字段分隔符):

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

如果您指定了OPTINALLY ,則ENCLOSED BY 字符只被用於包含具有字符串數據類型(比如CHAR, BINARY, TEXTENUM )的列中的值:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

注意,如果在字段值內出現ENCLOSED BY 字符,則通過使用ESCAPED BY 字符作爲前綴,對ENCLOSED BY 字符進行轉義。另外,要注意,如果您指定了一個空的ESCAPED BY 值,則可能會生成不能被LOAD DATA INFILE 正確讀取的輸出值。例如,如果轉義符爲空字符,則剛顯示的先前輸出值應顯示如下。請觀察,第四行中的第二個字段在引號後面包含一個逗號,該引號(錯誤地)顯示出來,作爲字段的結尾:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

對於輸入值,ENCLOSED BY 字符被從字段字的末尾剝離。(不論OPTIONALLY 是否被指定都會剝離;OPTIONALLY 對輸入值的解釋沒有影響。)如果ENCLOSED BY 字符前面帶有ESCAPED BY 字符,則被理解爲當前字段值的一部分。

如果字段以ENCLOSED BY 字符爲開始,當出現這類字符時,只有後面接着字段或行TERMINATED BY 序列時,這類字符被認爲是一個字段值的結尾。爲了避免意思不明確,當在一個字段值中出現ENCLOSED BY 字符時,此字符可以重複書寫,並被理解爲單一的字符。例如,如果指定了ENCLOSED BY '"' ,則按照以下方法操作引號:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY 用於控制如何寫入或讀取特殊字符。如果FIELDS ESCAPED BY 字符不是空字符,則可以在輸出中用於對以下字符加前綴:

·         FIELDS ESCAPED BY 字符

·         FIELDS [OPTIONALLY] ENCLOSED BY 字符

·         FIELDS TERMINATED BYLINES TERMINATED BY 值的第一個字符

·         ASCII 0 (在轉義符之後編寫的字符實際上是ASCII0 ’,而不是一個值爲0 的字節)

如果FIELDS ESCAPED BY 字符爲空字符,則沒有字符被轉義,並且NULL 被作爲NULL 輸出,而不是\N 。去指定一個空的轉義符不是一個好辦法,特別是如果數據的字段值包含任何剛給定的清單中的字符時,更不能這麼做。

對於輸入值,如果FIELDS ESCAPED BY 字符不是空字符,則出現這種字符時會被剝離,然後以下字符被作爲字段值的一部分。例外情況是,被轉義的‘0 ’或‘N ’(例如,\0\N ,此時轉義符爲‘\ ’)。這些序列被理解爲ASCII NUL (一個零值字節)和NULL 。用於NULL 處理的規則在本節的後部進行說明。

要了解有關‘\-escape 語法的更多信息,請參見9.1節,“文字值”

在特定情況下,field-line-handling 選項相互影響:

·         如果LINES TERMINATED BY 是空字符串,並且FIELDS TERMINATED BY 不是空字符串,則各行以FIELDS TERMINATED BY 作爲結尾。

·         如果FIELDS TERMINATED BYFIELDS ENCLOSED BY 值均爲空值('' ) ,則使用固定行(無分隔)格式。使用固定行格式時,在字段之間不使用分隔符(但是您仍然可以有行終止符)。列值使用列的顯示寬度進行寫入和讀取。例如,如果某列被定義爲INT(7) ,則使用7 字符字段寫入列值。輸出時,通過讀取7 個字符獲取列值。

LINES TERMINATED BY 仍然用於分隔行。如果某行不包含所有字段,則其餘的各列被設置到默認值。如果您沒有行終止符,您應該把終止符設置爲'' 。在此情況下,文本文件必須包含每行的所有字段。

固定行格式也會影響NULL 值的操作,這將在以後進行介紹。注意,如果您正在使用一個多字節字符集,則固定規格格式不會運行。

根據正在使用中的FIELDSLINES 選項的不同,NULL 值的操作有所變化:

·         對於默認的FIELDSLINES 值,NULL 被作爲\N 的字段值編寫,用於輸出;\N 字段值被作爲NULL 讀取,用於輸入(假設ESCAPED BY 字符爲‘\ ’)。

·         如果FIELDS ENCLOSED BY 不是空值,則包含以文字詞語NULL 爲值的字段被作爲NULL 值讀取。這與被FIELDS ENCLOSED BY 字符包圍的詞語NULL 不同。該詞語被作爲字符串'NULL' 讀取。

·         如果FIELDS ESCAPED BY 是空值,則NULL 被作爲詞語NULL 寫入。

·         採用固定行格式時(當FIELDS TERMINATED BYFIELDS ENCLOSED BY 均爲空值時採用),NULL 被作爲一個空字符串寫入。注意,這會導致在被寫入文件時,表中的NULL 值和空字符串均無法辨別,這是因爲兩者都被作爲空字符串寫入。如果您需要在讀取文件並返回時能夠分辨兩者,則您不應使用固定行格式。

LOAD DATA INFILE 不支持有些情況:

·         固定規格行(FIELDS TERMINATED BYFIELDS ENCLOSED BY 均爲空值)和BLOBTEXT 列。

·         如果您指定了一個分隔符,並且該分隔符與其它的前綴一樣,則LOAD DATA INFILE 不能正確地理解輸入值。例如,下面的FIELDS 子句會導致問題:

·                

FIELDS TERMINATED BY '"' ENCLOSED BY '"'

·         如果FIELDS ESCAPED BY 爲空值,則包含FIELDS ENCLOSED BYLINES TERMINATED BY 的字段值後面再接FIELDS TERMINATED BY 值會導致LOAD DATA INFILE 過早地停止讀取一個字段或行。出現這種情況的原因是LOAD DATA INFILE 不能正確地決定字段或行值在哪裏結束。

以下的例子載入了persondata 表中的所有列:

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;


默認情況下,如果在LOAD DATA INFILE 語句的末尾處沒有設列清單時,則輸入行預計會包含一個字段,用於表中的每個列。如果您只想載入一個表的部分列,則應指定一個列清單:

mysql> LOAD DATA INFILE 'persondata.txt'


    ->           INTO TABLE persondata (col1,col2,...);


如果輸入文件中各字段的順序與表中各列的順序不同,您也必須指定一個列清單。否則,MySQL 不能把輸入字段和表中的列匹配起來。

列清單可以包含列名稱或用戶變量。支持SET 子句。這使您可以把輸入值賦予用戶變量,然後在把結果賦予列之前,對這些值進行變換。

SET 子句中的用戶變量可以採用多種方式使用。以下例子使用數據文件中的第一列,直接用於t1.column1 的值。在用戶變量被用於t2.column2 值之前,把第二列賦予用戶變量。該變量從屬於一個分割運行。

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @var1)
  SET column2 = @var1/100;

SET 子句可以被用於提供不是來源於輸入文件的值。以下語句把column3 設置爲當前的日期和時間:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, column2)
  SET column3 = CURRENT_TIMESTAMP;

您也可以通過把輸入值賦予一個用戶變量,同時不把變量賦予表中的列,來丟棄此輸入值:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @dummy, column2, @dummy, column3);

/ 變量清單和SET 子句的使用受到以下限定:

·         SET 子句中的賦值應只含有位於賦值操作符的左側的列名稱。

·         您可以在SET 賦值的右側使用子查詢。如果子查詢可以返回一個值,並且此值將被賦予到一個列中,則此子查詢只能是標量子查詢。另外,您不能使用子查詢從一個正在被載入的表中選擇。

·         對於於列/ 變量清單或SET 子句,被IGNORE 子句忽略的行不被處理。

·         當載入採用固定行格式的數據時,不能使用用戶變量,因爲用戶變量沒有顯示寬度。

當處理一個輸入行時,LOAD DATA 會依據列/ 變量清單和SET 子句,把行拆分成字段,並使用值。然後,得到的行被插入表中。如果有用於表的BEFORE INSERTAFTER INSERT 觸發器,則在插入行之前和插入行之後分別啓動觸發器。

如果一個輸入行含有過多的字段,則多餘的字段被忽略,並且警告的數量增加。

如果一個輸入行含有的字段過少,則輸入字段缺失的表中的列被設置爲默認值。默認值賦值在13.1.5節,“CREATE TABLE語法” 中進行了說明。

如果字段值缺失,則對一個空字段值會被按不同方式理解:

·         對於字符串類型,列被設置爲空字符串。

·         對於數字類型,列被設置爲0

·         對於日期和時間類型,列被設置爲該類型相應的“zero ”。請參見11.3節,“日期和時間類型”

如果您明確地把一個空字符串賦予一個INSERTUPDATE 語句中的字符串類型、數字類型或日期或時間類型,則產生的這些值相同。

只有在兩種情況下TIMESTAMP 列被設置爲當前日期和時間。一種情況時當列有一個NULL 值(也就是\N )時;另一種情況是(僅對於第一個TIMESTAMP 列),當一個字段清單被指定時,TIMESTAMP 列會從字段清單中被略去。

LOAD DATA INFILE 把所有的輸入值當作字符串,所以您不能按照使用INSERT 語句的方式使用ENUMSET 列的數字值。所有的ENUMSET 值必須被指定爲字符串。

LOAD DATA INFILE 語句結束時,會按以下格式返回一個信息字符串:

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

如果您正在使用C API ,您可以通過調用mysql_info() 函數獲取有關語句的信息。請參見25.2.3.34節,“mysql_info()”

當值通過INSERT 語句被插入時或出現相同情況時,會發生警告(見13.2.4節,“INSERT語法” )。例外情況是,當輸入行中字段過多或過少時,LOAD DATA INFILE 也生成警告。這些警告並不存儲;警告的數量只用於指示運行是否良好。

您可以使用SHOW WARNINGS 來得到第一批max_error_count 警告的清單,作爲有關運行錯誤的信息。請參見13.5.4.22節,“SHOW WARNINGS語法”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章