Linux系统下MySQL的导入数据的命令语句Load Data InFile的用法详解
文章目錄
- 語法格式
- LOW_PRIORITY
- CONCURRENT
- LOCAL
- REPLACE 或 IGNORE
- PARTITION
- CHARACTER SET
- 對導入文件的字段進行格式描述
- 指定行的起始符號和終止符號
- IGNORE number LINES
- 指定數據表的列名
- 獲取表達式的值存儲到指定的列中
- 開啟/關閉功能
- 參考示例
- 示例一
- 示例二
- 示例三
- 示例四
- 示例五
- 錯誤匯總
- secure_file_priv 參數的問題
- 導入的記錄包含的字段值個數超過要導入的列數
- 導入文件的字符編碼與數據表的字符編碼不一致
- 導入文件的字段數量與數據表的列數量不一致
- 使用 local 與不使用 local 的差異
語法格式
LOAD DATA[LOW_PRIORITY | CONCURRENT] [LOCAL]INFILE 'file_name'[REPLACE | IGNORE]INTO TABLE tbl_name[PARTITION (partition_name [, partition_name] ...)][CHARACTER SET charset_name][{FIELDS | COLUMNS}[TERMINATED BY 'string'][[OPTIONALLY] ENCLOSED BY 'char'][ESCAPED BY 'char']][LINES[STARTING BY 'string'][TERMINATED BY 'string']][IGNORE number {LINES | ROWS}][(col_name_or_user_var[, col_name_or_user_var] ...)][SET col_name={expr | DEFAULT}[, col_name={expr | DEFAULT}] ...]LOW_PRIORITY
如果你指定關鍵詞LOW_PRIORITY,這個只對那些只采用了表級別鎖(如MYISAM)的引擎有影響,比如InnoDB使用的是行鎖,不受這個影響,具體的來說,使用了LOW_PRIORITY,則本操作會在其它線程完成之后再操作。
如果你指定關鍵詞 low_priority,那么 MySQL 將會等到沒有其他人讀這個表的時候,才會插入數據。
CONCURRENT
CONCURRENT 會和其它線程同時進行,這個對性能是有一些影響。
LOCAL
這是個非常重要的關鍵字,指明了文件的位置,簡單的說,如果指定了 local,則表示文件位于客戶端所在主機的位置,如果沒有指定,則表示文件在數據庫服務所在主機上,即數據庫服務器上。同時,這個關鍵字的使用還會影響到 load data 命令對于錯誤數據的處理方式。
所謂客戶端,就是用來訪問數據庫和管理數據庫的客戶端軟件,例如 Navicat Premium 客戶端。客戶端是安裝在用戶自己的主機上,通過客戶端連接上遠程數據庫服務器后(即登錄數據庫),可以直接通過客戶端的圖形化界面對數據庫進行管理,也可以通過客戶端的命令行界面對數據庫發送命令。
例如下面的命令語句來導入數據:
mysql> load data low_priority local infile "/Users/liaowenxiong/Desktop/student.txt" into table student columns terminated by ',' lines terminated by '\n' ignore 1 lines (id,age,name); Query OK, 3 rows affected (0.10 sec) Records: 3 Deleted: 0 Skipped: 0 Warnings: 0注:/Users/liaowenxiong/Desktop/student.txt 這個是文件在客戶端所在主機的文件路徑。
1.如果是指定了 local,則數據從客戶端讀取,文檔中的說法是會在服務端的臨時目錄下創建一份文件的副本,但我在測試的時候并沒有發現。file_name 必須是文件在客戶端所在主機的絕對路徑(例如:/Users/liaowenxiong/Desktop/student.txt),由于涉及到數據傳輸,所以這種方式會相對來說慢一些。
我不使用 Navicat Premium 的命令終端,使用本地主機的命令終端遠程登錄數據庫后,執行下面的命令:
load data low_priority local infile "student.txt" into table student columns terminated by ',' lines terminated by '\n' ignore 1 lines (id,age,name);注:這里指定了關鍵詞 local,直接使用文件名稱。此時使用的是本地主機命令終端遠程連接服務器,所以這種情況下的本地其實就是服務器本地,默認是在用戶的家目錄下查找文件,當前我登錄的是 root 用戶,那么就會在 /root/ 目錄下查找文件。
2.如果未指定 local,則文件應該是直接在服務端,這種情況下如果文件名使用的是相對路徑,則又分兩種情況,一種是文件名前沒有相對目錄,默認是在當前數據庫對應的目錄下查找。什么意思呢?假設你當前使用的數據庫名稱叫 test,那么在 MySQL 的數據根目錄下就會有一個目錄名稱為 test,那么命令就會在這個 test 目錄下查找這個文件;如果你在文件名稱前面加上了目錄名稱,例如,ab/student.txt,那么命令不會在 test 目錄下查找,但是依舊在 MySQL 的數據根目錄下查找,即會在 MySQL 數據根目錄下查找文件路徑 ab/student.txt。
如何查看 MySQL 數據庫的數據根目錄,請參見《Linux 下如何查找 MySQL 數據庫的數據根目錄呢?》
不指定關鍵詞 local 直接使用文件名執行 load data infile 語句:
mysql> load data low_priority-> infile "student.txt"-> into table student-> columns terminated by ','-> lines terminated by '\n' -> ignore 1 lines -> (id,age,name); ERROR 13 (HY000): Can't get stat of '/var/lib/mysql/test/student.txt' (Errcode: 2 - No such file or directory)我們看到,提示無法獲取文件 student.txt 的狀態,默認是在 /var/lib/mysql/test/ 目錄查找文件,其中 test 是當前數據庫名稱,/var/lib/mysql 是 MySQL 的數據根目錄。
不知道關鍵詞 local ,在文件名稱前面再加上一個目錄,結果會如何:
mysql> load data low_priority-> infile "ab/student.txt"-> into table student-> columns terminated by ','-> lines terminated by '\n' -> ignore 1 lines -> (id,age,name); ERROR 13 (HY000): Can't get stat of '/var/lib/mysql/ab/student.txt' (Errcode: 2 - No such file or directory)我們看到提示信息,并沒有在當前數據庫下查找文件,而是在數據根目錄下根據你指定的相對路徑查找文件。
3.如果指定了 local,則當某條數據處理有誤時,系統把這個錯誤記錄為一個 warning,不會影響下一條數據的處理,因為涉及到數據傳輸。而如果沒有指定 local,則默認情況下,遇到錯誤后不會繼續執行。
REPLACE 或 IGNORE
當前的數據跟表中的數據有惟一性沖突的時候,采用什么樣的方式,是替換已有還是忽略當前。特別需要說明的是,當這兩種方式都未指定時,如果數據來自于客戶端,則重復的數據會忽略,如果來源于服務端,則命令將終止執行。
服務端執行語句,不指定 REPLACE 或 IGNORE:
mysql> load data low_priority-> infile "/root/student.txt"-> into table student-> columns terminated by ','-> lines terminated by '\n' -> ignore 1 lines -> (id,age,name); ERROR 1062 (23000): Duplicate entry '00000000000000000001' for key 'PRIMARY'服務端執行導入語句,如果導入文檔中存在與數據表主鍵重復的記錄,則直接報錯。
客戶端執行語句,不指定 REPLACE 或 IGNORE:
mysql> load data low_priority local infile "/Users/liaowenxiong/Desktop/student.txt" into table student columns terminated by ',' lines terminated by '\n' ignore 1 lines (id,age,name); Query OK, 0 rows affected (0.08 sec) Records: 3 Deleted: 0 Skipped: 3 Warnings: 3從上面執行結果看,客戶端執行導入語句后,會把導入文檔中與數據表主鍵重復的記錄忽略,即跳過。
PARTITION
指定具體的分區,由于之前數據庫中沒用到過分區,個人對這塊也不熟悉,所以暫時不解釋,等到了解了再補充
CHARACTER SET
指定導入文件的字符編碼,如果文件的字符編碼和數據庫的編碼不一致,可能會出現亂碼的問題。所以要注意的是,這里指定的是文件的字符編碼,而不是數據庫的字符編碼
對導入文件的字段進行格式描述
[{FIELDS | COLUMNS}[TERMINATED BY 'string'][[OPTIONALLY] ENCLOSED BY 'char'][ESCAPED BY 'char']]1.FIELDS 和 COLUMNS,指定接下來描述的是導入文件中的字段或者列格式,兩個任選一個即可。
2.TERMINATED BY 'string' 指定導入文件中的字段間分隔符是 ‘string’
3.ENCLOSED BY 'char' 指定字段值由什么符號包圍
4.ESCAPED BY 'char' 指定轉義符號
注意:在不指定這個參數的情況下,默認的字段分隔符是水平制表符 \t,默認字段值無任何值包圍,默認轉義字符為 \。
指定行的起始符號和終止符號
[LINES [STARTING BY ‘string’] [TERMINATED BY ‘string’]]1.LINES 指定接下來描述的是導入文件中的行格式
2.STARTING BY 'string' 指定行開始的符號
3.TERMINATED BY 'string' 指定行結尾的符號
如果導入文件的數據記錄沒有起始符號,而每行記錄都是換行產生的,那么這個選項可以省略。因為默認情況下,行的起始符為空,終止符為 \n,對于 Windows 產生的文本文件來說,需要指定換行符為 \r\n 。
IGNORE number LINES
忽略文件中的前 number 行,通常情況下,我們生成的文件可能有列名,那么必須忽略列名,即忽略文件的前 1 行。需要注意的是這里是行的數量,而不是行號。
指定數據表的列名
有的時候我們不需要給數據表中的所有列都填充值,這個時候就可以指定數據表中的列名,用 () 將列名括起來。
就是將導入文件的字段依次序對應數據庫表中列,比方說導入文件中的第一個字段要存儲到數據表的哪列中,這個列名必須明確。
注意:
1.這里也可以是用戶自定義的用戶表達式
2.這里是指定數據庫中表的列名,不是導入文檔中的列名
獲取表達式的值存儲到指定的列中
[SET col_name = expr,…]如果在前一步中指定了用戶表達式,那么相應就可以使用列名等于用戶表達式的方式來指定,這個我沒有用過,給出一個官方的示例如下:
LOAD DATA INFILE 'file.txt' INTO TABLE t1(column1, @var1) SET column2 = @var1/100;開啟/關閉功能
LOAD DATA INFILE 這個導入數據命令語句是可以開啟和關閉的,必須開啟此功能才能使用,使用如下命令查看功能開啟狀態:
mysql> show global variables like 'local_infile'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | local_infile | ON | +---------------+-------+ 1 row in set (0.01 sec)如果是關閉的,則輸入以下命令將其開啟:
set global local_infile=ON;參考示例
示例一
student.txt 的內容如下:
"id" "name" "00000000000000000001" "liaowenxiong" "00000000000000000002" "liudehua" "00000000000000000003" "zhangxueyou"student.txt 的內容格式分析:
1.第一行記錄是列名稱,需要忽略掉
2.每列的值使用雙引號括起來
3.字段值之間使用制表符分隔(一種空白字符)
4.每行記錄以換行符結尾,即以換行符分隔
數據表結構如下:
mysql> desc student; +-------------+------------------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+------------------------------+------+-----+-------------------+-----------------------------+ | id | bigint(20) unsigned zerofill | NO | PRI | NULL | auto_increment | | name | varchar(30) | YES | | NULL | | | age | tinyint(3) unsigned | YES | | NULL | | | score | double(4,1) | YES | | NULL | | | birthday | date | YES | | NULL | | | insert_time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------------+------------------------------+------+-----+-------------------+-----------------------------+ 6 rows in set (0.00 sec)登錄數據庫后,執行以下命令:
mysql> load data low_priority # 如果你指定關鍵詞 `low_priority`,那么 MySQL 將會等到沒有其他人讀這個表的時候,才會插入數據 infile "/root/student.txt" # /root/student.txt 這是存放在數據庫服務器上的導入數據的文本文件 into table student # 這是數據表 fields terminated by '\t' # 指定字段的分隔符,用單引號括起來,`\t` 表示tab字符,也是默認的字段分隔符 enclosed by '"' # 指定字段值的括起符號,例如,字段值使用雙引號括起來,那么就指定雙引號'"',注意單引號里面的雙引號才是字段值的括起符號 escaped by '\\' # 指定轉義符號,默認是反斜杠 lines terminated by '\n' # 指定每行記錄的分隔符,默認是換行符,MacOS是`\r`,Linux是`\n`,Windows是`\r\n` ignore 1 lines # 指定忽略前面的多少行記錄,如果導入數據的文本文件中含有列名稱,那么就忽略掉前面的第一行即可 (id,name); # 這里是指定數據表的字段名稱,表示文本文件的第一列對應數據表的id字段,第二列對應數據表的name字段無注釋版本:
load data low_priority infile "/root/student.txt" into table student fields terminated by '\t' enclosed by '"' escaped by '\\' lines terminated by '\n' ignore 1 lines (id,name);示例二
student.txt 的內容如下:
id name 00000000000000000001 liaowenxiong 00000000000000000002 liudehua 00000000000000000003 zhangxueyoustudent.txt 的內容格式分析:
1.第一行記錄是列名稱
2.本示例中,字段值沒有使用雙引號括起來,所以不需要通過 enclosed by 來指定字段閉合符號。
3.字段值之間使用制表符分隔(一種空白字符)
4.每行記錄以換行符結尾,即以換行符分隔
執行以下命令即可導入數據:
load data low_priority infile "/root/student.txt" into table student fields terminated by '\t' lines terminated by '\n' ignore 1 lines (id,name);示例三
student.txt 的內容如下:
id,age,name 00000000000000000001,18,liaowenxiong 00000000000000000002,28,liudehua 00000000000000000003,38,zhangxueyoustudent.txt 的內容格式分析:
1.第一行記錄是列名稱,需要忽略掉
2.本示例中,字段值沒有使用雙引號括起來,所以不需要通過 enclosed by 來指定字段閉合符號。
3.字段值之間使用逗號分隔
4.每行記錄以換行符結尾,即以換行符分隔
5.文檔中的字段 age 和 name 與數據表的順序不同
登錄數據庫后,執行命令語句如下:
load data low_priority infile "/root/student.txt" into table student columns terminated by ',' lines terminated by '\n' ignore 1 lines (id,age,name); # 表示文檔的第一列和數據表的id字段對應,第二列和數據表的age字段對應,第三列和數據表的name字段對應示例四
student.txt 的內容如下:
id,age,name 00000000000000000001,18,liaowenxiong 00000000000000000002,28,liudehua 00000000000000000003,38,zhangxueyou通過客戶端 Navicat Premium 的命令行終端執行以下的命令:
load data low_priority local infile "/Users/liaowenxiong/Desktop/student.txt" into table student columns terminated by ',' lines terminated by '\n' ignore 1 lines (id,age,name);通過客戶端的命令終端執行 load data infile 可以使用文件在本地的文件路徑,但是要在前面指定關鍵詞 local。
示例五
student.txt 的內容如下:
id,age,name 00000000000000000001 18 liaowenxiong 00000000000000000002 28 liudehua 00000000000000000003 38 zhangxueyou執行如下命令語句導入數據:
load data low_priority infile "/root/student.txt" into table student fields terminated by ' ' lines terminated by '\n' ignore 1 lines (id,age,name);特別注意:字段之間如果使用【空格】分隔,也就是按一下空格鍵,那么這樣的分隔符號用 ' ' 表示,單引號內輸入一個空格即可,不是 \t 也不是 \b。
錯誤匯總
secure_file_priv 參數的問題
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement在 MySQL 5.7.6 版本引入了參數 secure_file_priv,該參數用來指定 LOAD DATA、SELECT … INTO OUTFILE 語句和 LOAD_FILE() 函數的導入導出目錄。
secure_file_priv 的值如下:
| null | MySQL 服務禁止導入和導出操作 |
| 目錄路徑 | 如果這個參數設為一個目錄路徑,MySQL 服務只允許在這個目錄中執行文件的導入和導出操作。這個目錄必須存在,MySQL 服務不會創建它。例如,值為 /tmp/,表示導入/導出只能發生在 /tmp/ 目錄下 |
| 沒有值 | 表示不對 mysqld 的導入/導出做限制 |
注:默認值是 /var/lib/mysql-files/
查看參數 secure_file_priv 的值,你可以輸入:
mysql> show variables like '%secure%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | require_secure_transport | OFF | | secure_auth | ON | | secure_file_priv | | +--------------------------+-------+ 3 rows in set (0.00 sec)如何解決:
Windows下,在 MySQL 安裝目錄下找到配置文件 my.ini,打開文件后在其中的 [mysqld] 內加入 secure_file_priv =''
Centos Linux 下,修改 /etc/my.cnf 文件,在 [mysqld] 內加入 secure_file_priv = ''
然后重啟 MySQL 配置才會生效。
因為 secure_file_priv 參數是只讀參數,不能使用 set global 命令修改:
mysql> set global secure_file_priv=''; ERROR 1238 (HY000): Variable 'secure_file_priv' is a read only variable導入的記錄包含的字段值個數超過要導入的列數
ERROR 1262 (01000): Row 1 was truncated; it contained more data than there were input columns這個錯誤表示第一行被截取了,第一行包含的數據超過了輸入的列數,輸入的列數由后面的小括號指定(id,name)。產生這個問題的原因往往是因為報錯的行被編輯過,即第一行并沒有在第二個字段的位置以換行符結尾,而是后面還有字符,可能是多余的空白字符等,所以需要手動重新整理數據。
ERROR 1300 (HY000): Invalid utf8 character string: ''導入文件的字符編碼與數據表的字符編碼不一致
ERROR 1300 (HY000): Invalid utf8 character string: ''可以將導入文件的字符編碼改成數據表的字符編碼保存后再執行命令語句。
導入文件的字段數量與數據表的列數量不一致
ERROR 1261 (01000): Row 228 doesn't contain data for all columns可能是因為數據庫的【嚴格轉換模式】導致,輸入以下的命令查看數據庫的參數 sql_mode 的值:
mysql> show variables like 'sql_mode'; +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)將其中的 STRICT_TRANS_TABLES 就是嚴格轉換模式,可以將其去掉。
set sql_mode='ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';使用 local 與不使用 local 的差異
如果 load data 語句使用了 local 參數,則客戶端使用 TCP 遠程連接數據庫服務器時(例如,你在自己的電腦通過命令終端使用 SSH 連接遠程數據庫服務器),在這種情況下所謂的本地(local)其實就是服務端主機了,那么該命令就會在服務端主機上直接讀取指定的導入文件,沒有 file 權限仍然能夠導入文本文件,這個時候是非常危險的,因為 local 參數的內部原理是從客戶端的主機讀取文本文件并傳送到服務端的 /tmp 目錄并保存為一個臨時文件,再執行 load data 語句的。
另外,要使用 local 參數,還需要看服務端和客戶端是否都開啟了 local_infile 功能(默認是開啟的),任何一端的 local_infile 關閉了都不能使用 local 參數,會報如下的錯誤:
ERROR 1148 (42000): The used command is not allowed with this MySQL version如果 load data 語句不使用 local 參數,則用戶必須要有導入文件的 file 權限才能夠執行 load data 語句導入文本文件的數據到數據庫中。如果沒有file權限,而執行 load data 語句導入文本文件,會報沒有 file 權限的錯誤或者報如下的錯誤:
ERROR 1045 (28000): Access denied for user 'test'@'%' (using password: YES)為了安全,要限制客戶端使用 local 參數在沒有 file 權限的時候使用 load data 語句導入文本文件數據,需要在服務端將參數 local_infile 的值設為 OFF。
如果想全面禁止使用 load data 語句,則可以將參數 secure_file_priv 的值設為 NULL,這樣就無法使用 load data infile 語句導入數據了,也無法使用 select into outfile 語句導出數據。
總結
以上是生活随笔為你收集整理的Linux系统下MySQL的导入数据的命令语句Load Data InFile的用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 火火兔怎么连接到电脑(火火兔怎么连接到电
- 下一篇: qq特别关心怎么看关心我的人手机qq特别