LOAD DATA [LOW_PRIORITY] [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語句從一個(gè)文本文件中以很高的速度讀入一個(gè)表中。如果指定LOCAL關(guān)鍵詞,從客戶主機(jī)讀文件。如果LOCAL沒指定,文件必須位于服務(wù)器上。(LOCAL在MySQL3.22.6或以后版本中可用。)
為了安全原因,當(dāng)讀取位于服務(wù)器上的文本文件時(shí),文件必須處于數(shù)據(jù)庫目錄或可被所有人讀取。另外,為了對服務(wù)器上文件使用LOAD DATA INFILE,在服務(wù)器主機(jī)上你必須有file的權(quán)限。見6.5 由MySQL提供的權(quán)限。
如果你指定關(guān)鍵詞LOW_PRIORITY,LOAD DATA語句的執(zhí)行被推遲到?jīng)]有其他客戶讀取表后。
使用LOCAL將比讓服務(wù)器直接存取文件慢些,因?yàn)槲募膬?nèi)容必須從客戶主機(jī)傳送到服務(wù)器主機(jī)。在另一方面,你不需要file權(quán)限裝載本地文件。
你也可以使用mysqlimport實(shí)用程序裝載數(shù)據(jù)文件;它由發(fā)送一個(gè)LOAD DATA INFILE命令到服務(wù)器來運(yùn)作。 --local選項(xiàng)使得mysqlimport從客戶主機(jī)上讀取數(shù)據(jù)。如果客戶和服務(wù)器支持壓縮協(xié)議,你能指定--compress在較慢的網(wǎng)絡(luò)上獲得更好的性能。
當(dāng)在服務(wù)器主機(jī)上尋找文件時(shí),服務(wù)器使用下列規(guī)則:
如果給出一個(gè)絕對路徑名,服務(wù)器使用該路徑名。
如果給出一個(gè)有一個(gè)或多個(gè)前置部件的相對路徑名,服務(wù)器相對服務(wù)器的數(shù)據(jù)目錄搜索文件。
如果給出一個(gè)沒有前置部件的一個(gè)文件名,服務(wù)器在當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)庫目錄尋找文件。
注意這些規(guī)則意味著一個(gè)像“./myfile.txt”給出的文件是從服務(wù)器的數(shù)據(jù)目錄讀取,而作為“myfile.txt”給出的一個(gè)文件是從當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)庫目錄下讀取。也要注意,對于下列哪些語句,對db1文件從數(shù)據(jù)庫目錄讀取,而不是db2:
mysql> USE db1;
mysql> LOAD DATA INFILE "./data.txt" INTO TABLE db2.my_table;
REPLACE和IGNORE關(guān)鍵詞控制對現(xiàn)有的唯一鍵記錄的重復(fù)的處理。如果你指定REPLACE,新行將代替有相同的唯一鍵值的現(xiàn)有行。如果你指定IGNORE,跳過有唯一鍵的現(xiàn)有行的重復(fù)行的輸入。如果你不指定任何一個(gè)選項(xiàng),當(dāng)找到重復(fù)鍵鍵時(shí),出現(xiàn)一個(gè)錯(cuò)誤,并且文本文件的余下部分被忽略時(shí)。
如果你使用LOCAL關(guān)鍵詞從一個(gè)本地文件裝載數(shù)據(jù),服務(wù)器沒有辦法在操作的當(dāng)中停止文件的傳輸,因此缺省的行為好像IGNORE被指定一樣。
LOAD DATA INFILE是SELECT ... INTO OUTFILE的逆操作,
SELECT句法。為了將一個(gè)數(shù)據(jù)庫的數(shù)據(jù)寫入一個(gè)文件,使用SELECT ... INTO OUTFILE,為了將文件讀回?cái)?shù)據(jù)庫,使用LOAD DATA INFILE。兩個(gè)命令的FIELDS和LINES子句的語法是相同的。兩個(gè)子句是可選的,但是如果指定兩個(gè),F(xiàn)IELDS必須在LINES之前。
如果你指定一個(gè)FIELDS子句,它的每一個(gè)子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BY和ESCAPED BY)也是可選的,除了你必須至少指定他們之一。
如果你不指定一個(gè)FIELDS子句,缺省值與如果你這樣寫的相同:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
如果你不指定一個(gè)LINES子句,缺省值與如果你這樣寫的相同:
LINES TERMINATED BY '\n'
換句話說,缺省值導(dǎo)致讀取輸入時(shí),LOAD DATA INFILE表現(xiàn)如下:
在換行符處尋找行邊界
在定位符處將行分進(jìn)字段
不要期望字段由任何引號字符封裝
將由“\”開頭的定位符、換行符或“\”解釋是字段值的部分字面字符
相反,缺省值導(dǎo)致在寫入輸出時(shí),SELECT ... INTO OUTFILE表現(xiàn)如下:
在字段之間寫定位符
不用任何引號字符封裝字段
使用“\”轉(zhuǎn)義出現(xiàn)在字段中的定位符、換行符或“\”字符
在行尾處寫換行符
注意,為了寫入FIELDS ESCAPED BY '\\',對作為一條單個(gè)的反斜線被讀取的值,你必須指定2條反斜線值。
IGNORE number LINES選項(xiàng)可被用來忽略在文件開始的一個(gè)列名字的頭:
mysql> LOAD DATA INFILE "/tmp/file_name" into table test IGNORE 1 LINES;
當(dāng)你與LOAD DATA INFILE一起使用SELECT ... INTO OUTFILE將一個(gè)數(shù)據(jù)庫的數(shù)據(jù)寫進(jìn)一個(gè)文件并且隨后馬上將文件讀回?cái)?shù)據(jù)庫時(shí),兩個(gè)命令的字段和處理選項(xiàng)必須匹配,否則,LOAD DATA INFILE將不能正確解釋文件的內(nèi)容。假定你使用SELECT ... INTO OUTFILE將由逗號分隔的字段寫入一個(gè)文件:
mysql> SELECT * FROM table1 INTO OUTFILE 'data.txt'
FIELDS TERMINATED BY ','
FROM ...
為了將由逗號分隔的文件讀回來,正確的語句將是:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
FIELDS TERMINATED BY ',';
相反,如果你試圖用下面顯示的語句讀取文件,它不會工作,因?yàn)樗頛OAD DATA INFILE在字段之間尋找定位符:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
FIELDS TERMINATED BY '\t';
可能的結(jié)果是每個(gè)輸入行將被解釋為單個(gè)的字段。
LOAD DATA INFILE能被用來讀取從外部來源獲得的文件。例如,以dBASE格式的文件將有由逗號分隔并用雙引號包圍的字段。如果文件中的行由換行符終止,下面顯示的命令說明你將用來裝載文件的字段和行處理選項(xiàng):
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';
任何字段或行處理選項(xiàng)可以指定一個(gè)空字符串('')。如果不是空,F(xiàn)IELDS [OPTIONALLY] ENCLOSED BY和FIELDS ESCAPED BY值必須是一個(gè)單個(gè)字符。FIELDS TERMINATED BY和LINES TERMINATED BY值可以是超過一個(gè)字符。例如,寫入由回車換行符對(CR+LF)終止的行,或讀取包含這樣行的一個(gè)文件,指定一個(gè)LINES TERMINATED BY '\r\n'子句。
FIELDS [OPTIONALLY] ENCLOSED BY控制字段的包圍字符。對于輸出(SELECT ... INTO OUTFILE),如果你省略O(shè)PTIONALLY,所有的字段由ENCLOSED BY字符包圍。對于這樣的輸出的一個(gè)例子(使用一個(gè)逗號作為字段分隔符)顯示在下面:
"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
注意,一個(gè)字段值中的ENCLOSED BY字符的出現(xiàn)通過用ESCAPED BY字符作為其前綴來轉(zhuǎn)義。也要注意,如果你指定一個(gè)空ESCAPED BY值,可能產(chǎn)生不能被LOAD DATA INFILE正確讀出的輸出。例如,如果轉(zhuǎn)義字符為空,上面顯示的輸出顯示如下。注意到在第四行的第二個(gè)字段包含跟隨引號的一個(gè)逗號,它(錯(cuò)誤地)好象要終止字段:
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字符如果存在,它從字段值的尾部被剝?nèi)ァ#ú还苁欠裰付∣PTIONALLY都是這樣;OPTIONALLY對于輸入解釋不起作用)由ENCLOSED BY字符領(lǐng)先的ESCAPED BY字符出現(xiàn)被解釋為當(dāng)前字段值的一部分。另外,出現(xiàn)在字段中重復(fù)的ENCLOSED BY被解釋為單個(gè)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值的第一個(gè)字符
ASCII 0(實(shí)際上將后續(xù)轉(zhuǎn)義字符寫成 ASCII'0',而不是一個(gè)零值字節(jié))
如果FIELDS ESCAPED BY字符是空的,沒有字符被轉(zhuǎn)義。指定一個(gè)空轉(zhuǎn)義字符可能不是一個(gè)好主意,特別是如果在你數(shù)據(jù)中的字段值包含剛才給出的表中的任何字符。
對于輸入,如果FIELDS ESCAPED BY字符不是空的,該字符的出現(xiàn)被剝?nèi)ゲ⑶液罄m(xù)字符在字面上作為字段值的一個(gè)部分。例外是一個(gè)轉(zhuǎn)義的“0”或“N”(即,\0或\N,如果轉(zhuǎn)義字符是“\”)。這些序列被解釋為ASCII 0(一個(gè)零值字節(jié))和NULL。見下面關(guān)于NULL處理的規(guī)則。
對于更多關(guān)于“\”- 轉(zhuǎn)義句法的信息,在某些情況下,字段和行處理選項(xiàng)相互作用:
如果LINES TERMINATED BY是一個(gè)空字符串并且FIELDS TERMINATED BY是非空的,行也用FIELDS TERMINATED BY終止。
如果FIELDS TERMINATED BY和FIELDS ENCLOSED BY值都是空的(''),一個(gè)固定行(非限定的)格式被使用。用固定行格式,在字段之間不使用分隔符。相反,列值只用列的“顯示”寬度被寫入和讀出。例如,如果列被聲明為INT(7),列的值使用7個(gè)字符的字段被寫入。對于輸入,列值通過讀取7個(gè)字符獲得。固定行格式也影響NULL值的處理;見下面。注意如果你正在使用一個(gè)多字節(jié)字符集,固定長度格式將不工作。
NULL值的處理有多種,取決于你使用的FIELDS和LINES選項(xiàng):
對于缺省FIELDS和LINES值,對輸出,NULL被寫成\N,對輸入,\N被作為NULL讀入(假定ESCAPED BY字符是“\”)。
如果FIELDS ENCLOSED BY不是空的,包含以文字詞的NULL作為它的值的字段作為一個(gè)NULL值被讀入(這不同于包圍在FIELDS ENCLOSED BY字符中的字NULL,它作為字符串'NULL'讀入)。
如果FIELDS ESCAPED BY是空的,NULL作為字NULL被寫入。
用固定行格式(它發(fā)生在FIELDS TERMINATED BY和FIELDS ENCLOSED BY都是空的時(shí)候),NULL作為一個(gè)空字符串被寫入。注意,在寫入文件時(shí),這導(dǎo)致NULL和空字符串在表中不能區(qū)分,因?yàn)樗麄兌甲鳛榭兆址粚懭搿H绻谧x回文件時(shí)需要能區(qū)分這兩者,你應(yīng)該不使用固定行格式。
一些不被LOAD DATA INFILE支持的情況:
固定長度的行(FIELDS TERMINATED BY和FIELDS ENCLOSED BY都為空)和BLOB或TEXT列。
如果你指定一個(gè)分隔符與另一個(gè)相同,或是另一個(gè)的前綴,LOAD DATA INFILE不能正確地解釋輸入。例如,下列FIELDS子句將導(dǎo)致問題:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
如果FIELDS ESCAPED BY是空的,一個(gè)包含跟隨FIELDS TERMINATED BY值之后的FIELDS ENCLOSED BY或LINES TERMINATED BY的字段值將使得LOAD DATA INFILE過早地終止讀取一個(gè)字段或行。這是因?yàn)長OAD DATA INFILE不能正確地決定字段或行值在哪兒結(jié)束。
下列例子裝載所有persondata表的行:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
沒有指定字段表,所以LOAD DATA INFILE期望輸入行對每個(gè)表列包含一個(gè)字段。使用缺省FIELDS和LINES值。
如果你希望僅僅裝載一張表的某些列,指定一個(gè)字段表:
mysql> LOAD DATA INFILE 'persondata.txt'
INTO TABLE persondata (col1,col2,...);
如果在輸入文件中的字段順序不同于表中列的順序,你也必須指定一個(gè)字段表。否則,MySQL不能知道如何匹配輸入字段和表中的列。
如果一個(gè)行有很少的字段,對于不存在輸入字段的列被設(shè)置為缺省值。
如果字段值缺省,空字段值有不同的解釋:
對于字符串類型,列被設(shè)置為空字符串。
對于數(shù)字類型,列被設(shè)置為0。
對于日期和時(shí)間類型,列被設(shè)置為該類型的適當(dāng)“零”值。
如果列有一個(gè)NULL,或(只對第一個(gè)TIMESTAMP列)在指定一個(gè)字段表時(shí),如果TIMESTAMP列從字段表省掉,TIMESTAMP列只被設(shè)置為當(dāng)前的日期和時(shí)間。
如果輸入行有太多的字段,多余的字段被忽略并且警告數(shù)字加1。
LOAD DATA INFILE認(rèn)為所有的輸入是字符串,因此你不能像你能用INSERT語句的ENUM或SET列的方式使用數(shù)字值。所有的ENUM和SET值必須作為字符串被指定!
如果你正在使用C API,當(dāng)LOAD DATA INFILE查詢完成時(shí),你可通過調(diào)用API函數(shù)mysql_info()得到有關(guān)查詢的信息。信息字符串的格式顯示在下面:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
當(dāng)值通過INSERT語句插入時(shí),在某些情況下出現(xiàn)警告,除了在輸入行中有太少或太多的字段時(shí),LOAD DATA INFILE也產(chǎn)生警告。警告沒被存儲在任何地方;警告數(shù)字僅能用于表明一切是否順利。如果你得到警告并且想要確切知道你為什么得到他們,一個(gè)方法是使用SELECT ... INTO OUTFILE到另外一個(gè)文件并且把它與你的原版輸入文件比較。