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命令查看数据库的编码:
shell script中执行sql语句,返回结果中文乱码问题_第1张图片
发现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

你可能感兴趣的:(数据持久化——数据库,操作系统——Linux——脚本)