需求場景
定期將特定查詢結果以 自訂分隔符、換行符、字元集 匯出為文字檔,供下游系統 (ETL、報表、對帳) 使用。
完整 Bash 腳本範例
#!/bin/bash
set -euo pipefail
# 設定區
MYSQL_USER="root"
MYSQL_PASS="StrongPass"
MYSQL_DB="home"
OUT_DIR="/var/lib/mysql-files" # secure_file_priv 允許目錄
OUT_FILE="sns_home_user_$(date +%F).txt"
SQL_QUERY="SELECT YongHuID, XueYuanID FROM sns_home_user WHERE YongHuID < 20;"
# 確保輸出目錄存在且 MySQL 可寫入
mkdir -p "$OUT_DIR"
chown mysql:mysql "$OUT_DIR"
# 刪除舊檔 (可選)
rm -f "$OUT_DIR/$OUT_FILE"
# 執行匯出
mysql -u"$MYSQL_USER" -p"$MYSQL_PASS" "$MYSQL_DB" -e "
SELECT YongHuID, XueYuanID
INTO OUTFILE '$OUT_DIR/$OUT_FILE'
FIELDS TERMINATED BY '|'
ENCLOSED BY '\"'
ESCAPED BY '\\\\'
LINES TERMINATED BY '\r\n'
FROM sns_home_user
WHERE YongHuID < 20;"
# 驗證
if [[ -f "$OUT_DIR/$OUT_FILE" ]]; then
echo "[$(date)] Export OK: $OUT_DIR/$OUT_FILE ($(wc -l < "$OUT_DIR/$OUT_FILE") rows)"
else
echo "[$(date)] Export FAILED!" >&2
exit 1
fi
關鍵 SELECT INTO OUTFILE 參數解析
| 子句 | 預設值 | 說明 | 本例設定 |
FIELDS TERMINATED BY | \t | 欄位分隔符 | '|' |
FIELDS ENCLOSED BY | 空 | 欄位包裹字元 (含分隔符時必須) | '\"' |
FIELDS ESCAPED BY | \\ | 跳脫字元 | '\\\\' (Shell 需雙重跳脫) |
LINES TERMINATED BY | \n | 換行符 | '\r\n' (Windows 相容) |
LINES STARTING BY | 空 | 每行前綴 | — |
權限與安全設定
- 執行帳號需具備
FILE 權限:GRANT FILE ON *.* TO 'export_user'@'localhost';
secure_file_priv 限制讀寫目錄,查看:SHOW VARIABLES LIKE 'secure_file_priv';
- 輸出目錄建議專用 (如
/var/lib/mysql-files),避免覆蓋系統檔。
- 生產環境密碼勿寫死腳本,使用
~/.my.cnf 或 mysql_config_editor。
進階:動態分割檔案 (按日期/數量)
# 範例:每 10000 列切一檔,需搭配應用層邏輯或 stored procedure
# MySQL 本身不支援 INTO OUTFILE 自動分檔,建議應用層分批 SELECT LIMIT offset, 10000
常見問題排查
| 錯誤 | 原因 | 解決 |
| ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option | 輸出路徑不在允許目錄 | 修改 my.cnf secure_file_priv=/var/lib/mysql-files 並重啟 |
| ERROR 1045: Access denied for user ... (using password: YES) | 缺 FILE 權限或密碼錯誤 | GRANT FILE ON *.* TO user@host; |
| 檔案建立成功但內容為空 | 查詢條件無符合資料 | 先在 CLI 跑 SQL 確認筆數 |
| 中文亂碼 | 字元集不一致 | 連線加 --default-character-set=utf8mb4,表/欄位為 utf8mb4 |