源自MySQL 5.7 官方手冊 SELECT...INTO Syntax
一、SELECT...INTO介紹
SELECT...INTO用來將查詢結果存儲在變量或者寫入文件中。
SELECT ... ... [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]]
通常有以下三種用法:
- SELECT...INTO var_list,將查詢結果存儲在變量中;
- SELECT...INTO OUTFILE 將查詢結果寫入一個文件,還可以指定列和行終止符以生成特定的輸出格式。
- SELECT...INTO DUMPFILE 將單行數據寫入文件,沒有任何格式。
在SELECT的語法展示中,INTO子句在整個語句的尾部。但是讓INTO子句緊跟在select_expr列表后。
一個INTO子句不應該在內嵌的SELECT中使用,因為這樣一個SELECT必須將它的查詢結果返回給外部上下文。
1.1 結果寫入變量
NTO子句可以命名一個或多個變量的列表,這些變量可以是用戶自定義的變量,存儲過程或函數的參數,或存儲的程序的局部變量。而對於預編譯的SELECT...INTO OUTFILE,只允許使用用戶自定義變量,see Section 13.6.4.2, “Local Variable Scope and Resolution”。
select后選定的值將分配給into后的變量,變量的數量必須與列數相匹配。如果查詢未返回任何行,則會出現錯誤代碼為1329的警告(No Data),並且變量的值保持不變。如果查詢返回多個行,報錯error 1172:Rseult consisted of more than one row,當然可以使用LIMIT 1來解決這個問題。
用戶自定義的變量對大小寫不敏感,See Section 9.4, “User-Defined Variables”。
1.2 SELECT ... INTO OUTFILE
SELECT ... INTO OUTFILE 'file_name'
文件會在服務器主機上創建,所以用戶必須擁有FILE權限才能使用該語法。
同時,file_name不能是一個已經存在的文件,它會防止諸如/etc/passwd和數據庫表等文件被損毀。character_set_filesystem系統變量控制文件名的解釋。
SELECT ... INTO OUTFILE語句主要用於讓您非常快速地將表轉儲到服務器計算機上的text文件中。如果要在服務器主機之外的其他主機上創建結果文件,通常無法使用SELECT ... INTO OUTFILE,因為無法寫出該文件相對於那個服務器主機的文件系統的路徑。(there is no way to write a path to the file relative to the server host's file system.)
但是,如果遠程計算機上安裝了MySQL客戶端軟件,則可以使用客戶端命令在客戶端主機上生成該文件,如:
mysql -e “SELECT ...”> file_name
如果可以使用服務器文件系統上的網絡映射路徑訪問遠程主機上文件的位置,也可以在服務器主機以外的其他主機上創建生成的文件。在這種情況下,目標主機上不需要存在mysql(或其他一些MySQL客戶端程序)
SELECT ... INTO OUTFILE是LOAD DATA的補充。將列值轉換為CHARACTER SET子句中指定的字符集。如果不存在此子句,則使用binary字符集轉儲值。實際上,沒有字符集轉換。如果結果集包含多個字符集中的列,則輸出數據文件也將如此,您可能無法正確重新加載文件。
該語句的export_options部分的語法,與LOAD DATA語句使用相同FIELDS和LINES子句。See 有關FIELDS和LINES子句的信息,請參見Section 13.2.6, “LOAD DATA Syntax”,包括其默認值和允許值。
三。關於輸出格式
FIELDS ESCAPED BY控制如何編寫特殊字符。如果FIELDS ESCAPED BY字符不為空,則會在必要時使用它——將它作為后面將要輸出的字符之前的前綴,以避免歧義:
- FIELDS ESCAPED BY 字符;
- FIELDS [OPTIONALLY] ENCLOSED BY 字符;
- FIELDS TERMINATED BY和LINES TERMINATED BY值的第一個字符
- ASCII NUL(零值字節;在轉義字符后實際寫入的是ASCII 0,而不是零值的字節)
FIELDS TERMINATED BY, ENCLOSED BY, ESCAPED BY, or LINES TERMINATED BY 字符必須進行轉義操作,以便能可靠地讀取文件。而為了更方便地用頁面查看,ASCII NUL 也會被轉義。
生成的文件不必符合SQL語法,因此不需要轉義任何其他內容。
如果FIELDS ESCAPED BY字符為空,則不轉義任何字符,並將NULL輸出為NULL,而不是\N。
指定一個空的轉義字符並不是一個好主意,尤其是當數據中的字段值包含剛剛給出的列表中的任何字符。
下面是一個以許多程序使用的逗號分隔值(CSV)格式生成文件的示例:
SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;
如果使用INTO DUMPFILE而不是INTO OUTFILE,MySQL只會在文件中寫入一行,不會有任何列或行終止,也不會執行任何轉義處理。如果要將BLOB值存儲在文件中,這非常有用。
NOTES:
由INTO OUTFILE或INTO DUMPFILE創建的任何文件都可由服務器主機上的所有用戶寫入。原因是MySQL服務器無法創建一個這樣的文件:該文件的擁有者不是它所運行賬戶下的用戶。(出於這個原因和其他原因,你永遠不應該以root身份運行mysqld)因此,文件必須是world-writable的,以便您可以操作其內容。如果secure_file_priv系統變量設置為非空目錄名,則要寫入的文件必須位於該目錄中。
最后,在作為事件調度程序執行的事件的一部分發生的SELECT ... INTO語句的上下文中,診斷消息(不僅是錯誤,還包括警告)被寫入錯誤日志,並且在Windows上寫入應用程序事件日志。see Section 23.4.5, “Event Scheduler Status”.
四、自己執行SELECT...INTO碰到的問題
我把上面的SELECT...INTO語句修改了一下,執行自己的版本導出數據時遇到了錯誤。
於是查看當前用戶的權限:
這塊不太懂,搜索說需要"FILE"權限,我以為自己沒有“FILE”權限(實際已經有了),於是想賦給當前用戶這個權限:
沒什么影響,只是提一下這個過程。
有了“FILE”權限,還是報錯不能執行:
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
涉及到secure_file_priv這個系統變量:
根據前一章的提示,我只能把輸出文件放到這個目錄下。
還有就是這個系統變量是只讀的,無法直接通過SQL修改。具體的修改方法可以搜索。
繼續。
現在有新的問題:
查詢結果顯示,系統變量secure_file_priv=C:\ProgramData\MySQL\MySQL Server 5.7\Uploads\
Windows的文件管理器的地址欄現實的也是:C:\ProgramData\MySQL\MySQL Server 5.7\Uploads
如下語句仍然不能執行:
SELECT * INTO OUTFILE 'C:\ProgramData\MySQL\MySQL Server 5.7\Uploads\sqltraining_stu.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM student; /* ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement */
報錯也沒變,但現在只能是文件路徑的格式問題了。修改路徑分隔符,執行成功。
SELECT * INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/sqltraining_stu.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM student; /* rows affected (0.00 sec) */