1. 程式人生 > >shell script中執行sql語句,返回結果中文亂碼問題——在企業開發中的解決方案

shell script中執行sql語句,返回結果中文亂碼問題——在企業開發中的解決方案

問題描述

有一個需求,需要編寫一個指令碼向遠端資料庫拉取資料並生成一個檔案。在編寫完成並執行後,發現檔案中的中文為亂碼。
指令碼中的查詢命令如下所示:

QUERY_CMD="mysql -h${HOST} -u${USER} -p${PWD} -sBN "
SQL="SELECT * FROM school.student;"
${QUERY_CMD} -e ${SQL} > ${RESULT_FILE}

執行過後發現中文亂碼:

aaa|????????????|0

原因分析

中文亂碼,那麼極有可能是編碼不對。在vim下使用:set fileencoding命令檢視檔案編碼為latin1.這說明該檔案的編碼的確不對。
那為什麼會出現這種結果呢?是資料庫中的編碼就是latin1導致的嗎?
檢視遠端資料庫,發現數據庫的編碼為utf8!

KEY `idx_modify_time` (`Fmodify_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

資料庫的編碼為utf8為什麼查出來的資料編碼卻是latin1呢?奇怪了。
在資料庫中執行status命令檢視資料庫的編碼:
在這裡插入圖片描述
發現server編碼的確是utf8,但是client編碼卻是latin1!
那麼原因找到了:server編碼和client編碼不一致,client編碼是不支援中文的latin1!

方案構思

1、 既然是client的編碼不對,那麼直接將client的編碼修改為utf8不就行了?
NO!在企業開發中,一臺機器並不是僅一個人使用。很多同事的應用也在該機器上面執行,如果我將client的編碼改了,很有可能會影響其他同事的程式!所以這種方式不可取。

2、 既然不能修改全域性的配置,那麼可不可以僅修改自己本次會話中的編碼呢?
這個思路可行!一次會話中的設定僅在本次會話中有效,會話結束後不會影響其他會話。(事後驗證也的確是這樣)

3、 那麼具體怎麼實施呢?
我也不清楚該怎麼實施,不過我們可以通過man mysql來查閱相關資料!
查閱過後果然發現了相關資訊:

 ?   --default-character-set=charset_name

           Use charset_name as the default character set for the client and connection.

           A common issue that can occur when the operating system uses utf8 or another multi-byte character set is that output from the mysql client is formatted incorrectly, due to the fact that the MySQL client uses the latin1 character set
           by default. You can usually fix such issues by using this option to force the client to use the system character set instead.

           See Section 9.5, "Character Set Configuration", for more information.

在文件中找了mysql命令有一個–default-character-set引數,通過該引數,可以指定本次會話中客戶端的預設編碼。
思路已經確定,那麼可以開始實施了。

最終方案

最終方案就是使用–default-character-set引數來設定本次會話中的client端預設編碼為utf8,這樣就能使得server端和client端的編碼一致,都支援中文了。
修改過後的shell script:

QUERY_CMD="mysql -h${HOST} -u${USER} -p${PWD} -sBN --default-character-set=utf8 "
SQL="SELECT * FROM school.student;"
${QUERY_CMD} -e ${SQL} > ${RESULT_FILE}

注意,utf8不要寫成utf-8!
執行驗證,中文不再亂碼:

aaa|記得點贊哈|0