LOAD DATA INFILE 句法詳解

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

[REPLACE | IGNORE]


INTO TABLE tbl_name


[FIELDS


[TERMINATED BY ''''/t'''']


[[OPTIONALLY] ENCLOSED BY '''''''']


[ESCAPED BY ''''//'''' ]


]


[LINES TERMINATED BY ''''/n'''']


[IGNORE number LINES]


[(col_name,...)]

LOAD DATA INFILE 語句以非常高的速度從一個文本文件中讀取記錄行並插入到一個表中。如果 LOCAL 關鍵詞被指定,文件從客戶端主機讀取。如果 LOCAL 沒有被指定,文件必須位於服務器上。(LOCAL 在 MySQL 3.22.6 或更新的版本中被支持。)
由於安全性的原因,當讀取位於服務器端的文本文件時,文件必須處於數據庫目錄或可被所有人讀取的地方。同時,爲了對服務器端的文件使用 LOAD DATA INFILE,你必須在服務器主機上有 FILE 權限。在 MySQL 3.23.49 和 MySQL 4.0.2 中,只有當你沒有以 --local-infile=0 選項啓動 mysqld,或你沒有禁止你的客戶端程序支持 LOCAL的情況下,LOCAL 纔會工作。查看章節 4.2.4 LOAD DATA LOCAL 的安全性問題.
如果你指定關鍵詞 LOW_PRIORITY,LOAD DATA 語句的執行將會被延遲,直到沒有其它的客戶端正在讀取表。
如果你對一個 MyISAM 表指定關鍵詞 CONCURRENT,那麼當 LOAD DATA正在執行時,其它的線程仍可以從表中檢索數據。使用這個選項時,如果同時也有其它的線程正在使用表,這當然會有一點影響 LOAD DATA 的執行性能。
使用 LOCAL 將比讓服務器直接訪問文件要慢一些,因爲文件的內容必須從客戶端主機傳送到服務器主機。而在另一方面,你不再需要有 FILE 權限用於裝載本地文件。
如果你使用先於 MySQL 3.23.24 的版本,你不能夠以 LOAD DATA INFILE 讀取一個 FIFO 。如果你需要從一個 FIFO (例如,gunzip 的輸出文件) 中讀取,可以使用 LOAD DATA LOCAL INFILE 代替。
你也可以使用 mysqlimport 實用程序裝載數據文件;它通過發送一個 LOAD DATA INFILE 命令到服務器來動作。--local 選項使得 mysqlimport 從客戶端主機讀取數據文件。如果客戶端與服務器支持壓縮協議,你可以指定 --compress 選項,以在較慢的網絡中獲得更好的性能。
當從服務器主機定位文件時,服務器使用下列規則:
  • 如果給定一個完整的路徑,服務器使用該路徑名。
  • 如果給定一個有一個或多個前置構件的相對路徑,服務器以相對服務器的數據目錄搜索文件。
  • 如果給定一個沒有前置構件的文件名,服務器從當前數據庫的數據庫目錄搜尋文件。
注意,這些規則意味着,一個以 `./myfile.txt'''' 給出的文件是從服務器的數據目錄中讀取的,然而,以 `myfile.txt'''' 給出的一個文件是從當前數據庫的數據目錄下讀取的。舉例來說,下面的 LOAD DATA 語句從 db1 數據庫目錄下讀取文件 `data.txt'''',因爲 db1 是當前數據庫,即使該語句明確地指定讀取的文件被放入到 db2 數據庫中的一個表中:
mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;
REPLACE 和 IGNORE 關鍵詞控制對與現有的記錄在唯一鍵值上重複的記錄的處理。如果你指定 REPLACE,新的記錄行將替換有相同唯一鍵值的現有記錄行。如果你指定 IGNORE,將跳過與現有的記錄行在唯一鍵值上重複的輸入記錄行。如果你沒有指定任何一個選項,當重複鍵值出現時,將會發生一個錯誤,文本文件的剩餘部分也將被忽略。
如果你使用 LOCAL 關鍵詞從一個本地文件中讀取數據,在此操作過程中,服務器沒有辦法停止文件的傳送,因此缺省的處理方式就好像是 IGNORE 被指定一樣。
如果你在一個空的 MyISAM 表上使用 LOAD DATA INFILE,所有非唯一索引會以一個分批方式被創建(就像 REPAIR)。當有許多索引時,這通常可以使 LOAD DATA INFILE 更快一些。
LOAD DATA INFILE 的 SELECT ... INTO OUTFILE 的逆操作。使用 SELECT ... INTO OUTFILE 將數據從一個數據庫寫到一個文件中。使用 LOAD DATA INFILE 讀取文件到數據庫中。兩個命令的 FIELDS 和 LINES 子句的句法是一樣的。兩個子句都是可選的,但是如果兩個同時被指定,FIELDS 子句必須出現在 LINES 子句之前。
如果你指定一個 FIELDS 子句,它的子句 (TERMINATED BY、[OPTIONALLY] ENCLOSED BY 和 ESCAPED BY) 也是可選的,不過,你必須至少指定它們中的一個。
如果你沒有指定一個 FIELDS 子句,缺省的相同於如果你這樣寫:
FIELDS TERMINATED BY ''''/t'''' ENCLOSED BY '''''''' ESCAPED BY ''''//''''
如果你沒有指定一個 LINES 子句,缺省的相同於如果你這樣寫:
LINES TERMINATED BY ''''/n''''
換句話說,當讀取輸入時,缺省值導致 LOAD DATA INFILE 表現如下:
  • 在換行符處尋找行的邊界。
  • 在定位符處將行分開放到字段中。
  • 不認爲字段由任何引號字符封裝。
  • 將有 “/” 開頭的定位符、換行符或 `/'''' 解釋爲字段值的一個文字字符。
相反的,當寫入輸出時,缺省值導致 SELECT ... INTO OUTFILE 表現如下:
  • 在字段值間加上定位符。
  • 不用任何引號字符封裝字段。
  • 使用 “/” 轉義出現在字段值中的定位符、換行符或 `/'''' 字符實例。
  • 在行的結尾處加上換行符。
注意,爲了寫 FIELDS ESCAPED BY ''''//'''',你必須指定兩個反斜線,該值會作爲一個反斜線被讀入。
IGNORE number LINES 選項可被用於忽略文件開頭處的一個列名的頭:
mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;
當你一前一後地使用 SELECT ... INTO OUTFILE 和 LOAD DATA INFILE 將數據從一個數據庫寫到一個文件中,然後再從文件中將它讀入數據庫中時,兩個命令的字段和行處理選項必須匹配。否則,LOAD DATA INFILE 將不能正確地解釋文件內容。假設你使用 SELECT ... INTO OUTFILE 以逗號分隔字段的方式將數據寫入到一個文件中:
mysql> SELECT * INTO OUTFILE ''''data.txt''''

->
FIELDS TERMINATED BY '''',''''


->
FROM ...;

爲了將由逗號分隔的文件讀回時,正確的語句應該是:
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 格式的文件,字段以逗號分隔並以雙引號包圍着。如果文件中的行以一個換行符終止,那麼下面所示的可以說明你將用來裝載文件的字段和行處理選項:
mysql> LOAD DATA INFILE ''''data.txt'''' INTO TABLE tbl_name

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


->
LINES TERMINATED BY ''''/n'''';

任何字段和行處理選項都可以指定一個空字符串('''''''')。如果不是空的,FIELDS [OPTIONALLY] ENCLOSED BY 和 FIELDS ESCAPED BY 值必須是一個單個字符。FIELDS TERMINATED BY 和 LINES TERMINATED BY 值可以超過一個字符。例如,爲了寫入由回車換行符終止的行,或讀取包含這樣的行的文件,應該指定一個 LINES TERMINATED BY ''''/r/n'''' 子句。
舉例來說,爲了讀取一個文件到一個 SQL 表中,文件以一行 %% 分隔(開玩笑的),你可以這樣做:
CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT
NOT NULL);
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"
如果你指定 OPTIONALLY,ENCLOSED BY 字符僅被作用於包圍 CHAR 和 VARCHAR 字段:
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 字符作爲其前綴對其轉義。同時也要注意,如果你指定一個空的 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 不會影響它。) 由ESCAPED BY 字符領先於 ENCLOSED BY 字符的出現,將被解釋爲當前字段值的一部分。另外,在字段中出現的重複的 ENCLOSED 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 BY 和 LINES TERMINATED BY 值的第一個字符。
  • ASCII 0 (實際上在轉義字符後寫上 ASCII ''''0'''',而不是一個零值字節)
如果 FIELDS ESCAPED BY 字符爲空,沒有字符被轉義。指定一個空的轉義字符可能不是一個好的主意,特別是如果你的數據字段值中包含剛纔列表中的任何字符時。
對於輸入,如果 FIELDS ESCAPED BY 字符不爲空,該字符的出現將會被剝離,後續的字符在字面上做爲字段值的一部分。除了一個轉義的 “0” 或 “N” (即,/0 或/N,如果轉義字符爲 `/'''')。這些序列被解釋爲 ASCII 0 (一個零值字節) 和 NULL。查看下面的有關 NULL 處理的規則。

在某些情況下,字段與行處理相互作用:
  • 如果 LINES TERMINATED BY 是一個空字符串,FIELDS TERMINATED BY 是非空的,行也用 FIELDS TERMINATED BY 終止。
  • 如果 FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 值都是空的 (''''''''),一個固定行(無定界符) 格式被使用。用固定行格式時,在字段之間不使用分隔符。代替的,列值的寫入和讀取使用列的“顯示”寬度。例如,如果一個列被定義爲 INT(7),列的值將使用 7 個字符的字段被寫入。對於輸入,列值通過讀取 7 個字符來獲得。固定行格式也影響對 NULL 值的處理;見下面。注意,如果你正在使用一個多字節的字符集,固定長度格式將不能工作。
NULL 值的處理有很多,取決於你所使用的 FIELDS 和 LINES 選項:
  • 對於缺省的 FIELDS 和 LINES 值,輸出時,NULL 被寫成 /N,當讀入時,/N 被作爲 NULL 讀入(假設 ESCAPED BY 字符爲 “/”)。
  • 如果 FIELDS ENCLOSED BY 是非空的,一個字段包含文字詞 NULL 的,它的值做爲一個 NULL 值被讀入 (這不同於被 FIELDS ENCLOSED BY 包圍的詞 NULL,它是被作爲 ''''NULL'''' 讀入的)。
  • 如果 FIELDS ESCAPED BY 是空的,NULL 值被寫爲詞 NULL。
  • 用固定行格式時 (它發生於 FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 兩者均爲空),NULL 被寫爲一個空的字符串。注意,當將表中的 NULL 值和空字符串一起寫到文件中時,它們將被混淆,因爲它們都是作爲空字符串被寫入的。如果你在文件時,需要對他們兩個進行區分,你不應該使用固定行格式。
一些不能被 LOAD DATA INFILE 支持的情況:
  • 固定尺寸的記錄行 (FIELDS TERMINATED BY 和 FIELDS ENCLOSED BY 均爲空) 和 BLOB 或 TEXT 列。
  • 如果你指定一個分隔符與另一個相同,或是另一個的前綴,LOAD DATA INFILE 可能會不能正確地解釋輸入。例如,下列的 FIELDS 子句將會產生問題:
  • FIELDS TERMINATED BY ''''"'''' ENCLOSED BY ''''"''''
  • 如果 FIELDS ESCAPED BY 爲空,一個字段值中包含有 FIELDS ENCLOSED BY 或 LINES TERMINATED BY 被 FIELDS TERMINATED BY 跟隨的值時,將會引起 LOAD DATA INFILE 過早地停止讀取一個字段或一行。這是因爲 LOAD DATA INFILE 不能夠正確地決定字段或行值在哪裏結果。
下面的例子將裝載 persondata 表的所有列:
mysql> LOAD DATA INFILE ''''persondata.txt'''' INTO TABLE persondata;
沒有字段列被指定,因而 LOAD DATA INFILE 認爲輸入行包含表列中所有的字段。使用缺省的 FIELDS 和 LINES 值。
如果你希望裝載表中的某些列,那指定一個字段列表:
mysql> LOAD DATA INFILE ''''persondata.txt''''

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

如果輸入文件的字段次序不同於表中列的順序,你也必須指定一個字段列表。否則 MySQL 不知道如何將輸入字段與表中的列匹配。
如果一個行有很少的字段,沒有輸入字段的列將被設置爲缺省值。
一個空的字段值不同於字段值丟失的解釋:
  • 對於字符串類型,列被設置爲空字符串。
  • 對於數字類型,列被設置爲 0。
  • 對於日期和時間類型,列被設置爲適合列類型的“零”值。注意,如果在一個 INSERT 或 UPDATE 語句中明確地將一個空字符串賦給一個字符串、數字或日期或時間類型,你會得到與上面相同的結果。
如果對 TIMESTAMP 列指定一個 NULL 值,或者當字段列表被指定時, TIMESTAMP 在字段列表中被遺漏(僅僅第一個 TIMESTAMP 列被影響),TIMESTAMP 列會被設置爲當前的日期和時間。
如果輸入的記錄行有太多的字段,多餘的字段將被忽略,並增加警告的數目。
LOAD DATA INFILE 認爲所有的輸入均是字符串,因而,對於 ENUM 或 SET 列,你不能以 INSERT 語句的形式爲其設置數字值。所有的 ENUM 和 SET 必須以字符串指定!
如果你正在使用 C API,當 LOAD DATA INFILE 查詢結束時,你可以調用 API 函數 mysql_info() 獲得有關查詢的信息。信息串的格式如下:
Records: 1
Deleted: 0
Skipped: 0
Warnings: 0

警告會在某些情況下發生,這些情況與值通過 INSERT 語句插入時發生警告的情況一樣,但是 LOAD DATA INFILE 有一點與它不一樣,當在輸入行中有太多或過少的字段,它也會產生警告。警告不會被存儲在任何地主;警告的數目僅能表示一切是否順利。如果得到警告,並希望確切地知道爲什麼會得到它們,一個方法就是使用 SELECT ... INTO OUTFILE,將它保存到另外一個文件中,並與原先的輸入文件進行比較。
如果你需要 LOAD DATA 從一個管道中讀取,你可以使用下面的技巧:
mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE ''''x'''' INTO TABLE x" x
如果你使用的版本早於 MySQL 3.23.25,你只能通過 LOAD DATA LOCAL INFILE 來執行上面。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章