前言
已經(jīng)有3年多沒再關(guān)心或者遇到編碼格式的問題了俱两,一是離Oracle數(shù)據(jù)庫操作遠(yuǎn)了冒晰,二是現(xiàn)在的Terminal缔御,IDE和操作系統(tǒng)語言環(huán)境配置都很標(biāo)準(zhǔn)惜颇,比如清一色的UTF-8編碼和UNIX(LF)皆刺,我自己的組合是以下形式,Xmanager + Visual Studio Code/Notepad2 + 增加中文語言包顯示的操作系統(tǒng)凌摄,Oracle zhs16gbk芹橡,MySQL utf8,Python 2/3 utf-8望伦。本來應(yīng)該是非常統(tǒng)一而和諧的開發(fā)環(huán)境因?yàn)閟qlplus spool導(dǎo)出中文內(nèi)容而又變更混沌林说,索性再徹底分析以下中文亂碼的源頭和解決方案。
保持操作系統(tǒng)屯伞,終端登錄腿箩,數(shù)據(jù)庫3者編碼格式一致性很重要
更新記錄
2017年09月06日 - 初稿
閱讀原文 - https://wsgzao.github.io/post/lang/
Locale
下面2個(gè)地址對(duì)Locale語言字符集的介紹已經(jīng)很清晰了,我只強(qiáng)調(diào)2點(diǎn)
- 大多數(shù)UNIX操作系統(tǒng)建議默認(rèn)顯示語言為英語劣摇,但是一定要添加中文語言支持包
- 顯示中文亂碼多數(shù)原因是操作系統(tǒng)LANG環(huán)境變量或者類似Xshell編碼不統(tǒng)一造成的
Locale - http://wiki.ubuntu.org.cn/Locale
Localization - https://wiki.gentoo.org/wiki/Localization/Guide
NLS_LANG
本次遇到的問題主要是由于使用sqlplus spool從Oracle數(shù)據(jù)庫導(dǎo)出中文數(shù)據(jù)引發(fā)連鎖問題珠移,雖然和數(shù)據(jù)庫相關(guān)但是解決中文亂碼的思路基本上是一致的,方便各位以后可以借鑒和參考末融。
# 源主機(jī):CentOS 6.8 已安裝中文語言包钧惧,保持LANG和NLS_LANG默認(rèn)環(huán)境變量,Oracle Instant Client 12.2.0.1.0勾习,已安裝sqlplus
echo $LANG
en_US.UTF-8
echo $NLS_LANG
空
# 數(shù)據(jù)庫服務(wù)器:Oracle Database 11.2.0.3.0浓瞪,NLS_CHARACTERSET ZHS16GBK
sqlplus system/oracle@orabiz
SQL> select * from v$nls_parameters;
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_LANGUAGE
AMERICAN
NLS_TERRITORY
AMERICA
NLS_CURRENCY
$
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_ISO_CURRENCY
AMERICA
NLS_NUMERIC_CHARACTERS
.,
NLS_CALENDAR
GREGORIAN
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_DATE_FORMAT
DD-MON-RR
NLS_DATE_LANGUAGE
AMERICAN
NLS_CHARACTERSET
ZHS16GBK
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_SORT
BINARY
NLS_TIME_FORMAT
HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT
DD-MON-RR HH.MI.SSXFF AM
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_TIME_TZ_FORMAT
HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT
DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY
$
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_NCHAR_CHARACTERSET
AL16UTF16
NLS_COMP
BINARY
NLS_LENGTH_SEMANTICS
BYTE
PARAMETER
----------------------------------------------------------------
VALUE
----------------------------------------------------------------
NLS_NCHAR_CONV_EXCP
FALSE
19 rows selected.
問題1:ORA-12705
ERROR:
ORA-12705: Cannot access NLS data files or invalid environment specified
12705, 00000, "Cannot access NLS data files or invalid environment specified"
// *Cause: Either an attempt was made to issue an ALTER SESSION command
// with an invalid NLS parameter or value; or the environment
// variable(s) NLS_LANG, ORA_NLSxx, or ORACLE_HOME was incorrectly
// specified, therefore the NLS data files cannot be located.
// *Action: Check the syntax of the ALTER SESSION command and the NLS
// parameter, correct the syntax and retry the statement, or
// specify the correct directory path/values in the environment
// variables.
根據(jù)以上Oracle官方提示,合理的解決思路大致是這樣
- 檢查數(shù)據(jù)庫服務(wù)器的NLS parameter
- 在客戶端中配置與服務(wù)端匹配的NLS_LANG
比如我的環(huán)境就需要配置
export NLS_LANG="american_america.zhs16gbk"
它的格式如下:NLS_LANG=language_territory.charset
它有三個(gè)組成部分(語言巧婶、地域和字符集)乾颁,每個(gè)成分控制了NLS子集的特性。
Language:指定服務(wù)器消息的語言艺栈, 影響提示信息是中文還是英文
Territory:指定服務(wù)器的日期和數(shù)字格式英岭,
Charset:指定字符集。
如:AMERICAN_AMERICA.ZHS16GBK, SIMPLIFIED CHINESE_CHINA.ZHS16GBK
export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"
從NLS_LANG的組成我們可以看出湿右,真正影響數(shù)據(jù)庫字符集的其實(shí)是第三部分诅妹。
所以兩個(gè)數(shù)據(jù)庫之間的字符集只要第三部分一樣就可以相互導(dǎo)入導(dǎo)出數(shù)據(jù),前面影響的只是提示信息是中文還是英文毅人。
問題2:VI打開文件中文亂碼
其實(shí)這個(gè)問題就是由第一個(gè)問題引申出來的吭狡,主要和LANG環(huán)境變量有關(guān)
Locale 是軟件在運(yùn)行時(shí)的語言環(huán)境, 它包括語言(Language), 地域 (Territory) 和字符集(Codeset)尖殃。
一個(gè)locale的書寫格式為: 語言[_地域[.字符集]].
zh_CN.GB2312=中文_中華人民共和國+國標(biāo)2312字符集。
我說中文赵刑,身處中國大陸分衫,使用國標(biāo)2312字符集來表達(dá)字符。
zh_TW.BIG5=中文_臺(tái)灣.大五碼字符集
我說中文般此,身處臺(tái)灣地區(qū)蚪战,使用Big5字符集來表達(dá)字符。
根據(jù)以上信息合理的解決思路大致是這樣
- 檢查操作系統(tǒng)是否已添加中文語言包
- 檢查SecureCRT/Xshell等終端編碼是否為默認(rèn)編碼或UTF-8
- 檢查LANG環(huán)境變量是否合適
比如我的環(huán)境就需要配置铐懊,為什么不加zh_CN.UTF-8邀桑,你猜呢
export LANG=zh_CN