在SQL*Plus中用insert插進的都是中文的
為什麼一存入服務器後
再select出的就是???
有的時候
服務器數據先導出
重裝服務器
再導入數據
結果
發生數據查詢成???
……
這些問題
一般是因為字符集設置不對造成的
很久以來
字符集一直是困擾著眾多Oracle愛好者的問題
筆者從事Oracle數據庫管理和應用已經幾年了
經常接到客戶的類似上面提到的有關數據庫字符集的
告急
和
求救
在此我們就這個問題做一些分析和探討
首先
我們要明確什麼是字符集?字符集是一個字節數據的解釋的符號集合
有大小之分
有相互的包括關系
如us
ascii就是zhs
gbk的子集
從us
ascii到zhs
gbk不會有數據解釋上的問題
不會有數據丟失
Oracle對這種問題也要求從子集到超集的導出受支持
反之不行
在所有的字符集中utf
應該是最大
因為它基於unicode
雙字節保存字符(也因此在存儲空間上占用更多)
其次
一旦數據庫創建後
數據庫的字符集是不能改變的
因此
在設計和安裝之初考慮使用哪一種字符集是十分重要的
數據庫字符集應該是操作系統本地字符集的一個超集
存取數據庫的客戶使用的字符集將決定選擇哪一個超集
即數據庫字符集應該是所有客戶字符集的超集
在實際應用中
和字符集問題關系最大的恐怕就是exp/imp了
在做exp/imp時
如果Client 和Server的nls_lang設置是一樣的
一般就沒有問題的
但是
要在兩個不同字符集的系統之間導數據就經常會有這樣或那樣的問題
如
導出時數據庫的顯示正常
是中文
當導入到其他系統時
就成了亂碼
這也是一類常見問題
現在
介紹一些與字符集有關的NLS_LANG參數
NLS_LANG格式 NLS_LANG = language_territory
charset
有三個組成部分(語言
地域和字符集)
每個成分控制了NLS子集的特性
其中
language 指定服務器消息的語言
territory 指定服務器的日期和數字格式
charset 指定字符集
例如 AMERICAN_AMERICA
US
SCII
AMERICAN _ AMERICA
ZHS
GBK
還有一些子集可以更明確定義NLS_LANG參數 DICT
BASE 數據字典基本 表版本
DBTIMEZONE 數據庫時區
NLS_LANGUAGE 語言
NLS_TERRITORY 地域
NLS_CURRENCY 本地貨幣字符
NLS_ISO_CURRENCY ISO貨幣字符
NLS_NUMERIC_CHARACTERS 小數字符和組 分隔開
NLS_CHARACTERSET 字符集
NLS_CALENDAR 日歷系統
NLS_DATE_FORMAT 缺省的日期格式
NLS_DATE_LANGUAGE 缺省的日期語言
NLS_SORT 字符排序序列
NLS_TIME_FORMAT 時間格式
NLS_TIMESTAMP_FORMAT 時間戳格式
……
通過props$動態性能視圖我們可以查看數據庫的字符集信息 $> sqlplus internal
SQL> desc props$
Name Type Nullable Default Comments
NAME VARCHAR
(
)
VALUE$ VARCHAR
(
) Y
COMMENT$ VARCHAR
(
) Y
SQL> set arraysize
SQL> col value$ format a
SQL> select name
value$ from props$ where name=
NLS_CHARACTERSET
;
NAME VALUE$
NLS_CHARACTERSET ZHS
GBK
SQL> select * from sys
props$;
NAME VALUE$
DICT
BASE
DBTIMEZONE
:
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS
NLS_CHARACTERSET ZHS
GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD
MON
RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH
MI
SSXFF AM
NLS_TIMESTAMP_FORMAT DD
MON
RR HH
MI
SSXFF AM
NLS_TIME_TZ_FORMAT HH
MI
SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT DD
MON
RR HH
MI
SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_NCHAR_CHARACTERSET ZHS
GBK
NLS_RDBMS_VERSION
NAME VALUE$
GLOBAL_DB_NAME SCPDB
EXPORT_VIEWS_VERSION
rows selected
SQL>
從結果可以看出 NLS_LANG = AMERICAN _ AMERICA
ZHS
GBK
雖然
數據庫的字符集是在create database的時候指定的
以後不允許改變
但在一個已經建立好的數據庫上
我們可以通過修改SYS
PROPS$來修改主要是對應客戶端的顯示
與存儲無關
如
SQL> conn / as sysdba
Connected
SQL> SQL> select * from sys
props$
WHERE NAME=
NLS_LANGUAGE
;
NAME VALUE$
NLS_LANGUAGE AMERICAN
SQL>
SQL> UPDATE sys
PROPS$ SET VALUE$=
SIMPLIFIED CHINESE
WHERE NAME=
NLS_LANGUAGE
;
row updated
SQL>
SQL> select * from sys
props$
WHERE NAME=
NLS_LANGUAGE
;
NAME VALUE$
NLS_LANGUAGE SIMPLIFIED CHINESE
SQL>
通常出現問題的原因可分為三種 服務器指定字符集與客戶字符集不同
而與加載數據字符集一致
解決方法
對於這種情況
只需要設置客戶端字符集與服務器端字符集一致就可以了
具體操作如下
* 查看當前字符集
SQL> select * from sys
props$
WHERE NAME=
NLS_CHARACTERSET
;
NAME VALUE$
NLS_CHARACTERSET ZHS
GBK
SQL>
可以看出
現在服務器端Oracle數據庫的字符集為
ZHS
GBK
* 根據服務器的字符集在客戶端作相應的配置或者安裝Oracle的客戶端軟件時指定
如果還沒安裝客戶端
那麼在安裝客戶端時
指定與服務器相吻合的字符集即可
如果已經安裝好了客戶端
並且客戶端為 sql*net
以下版本
進入Windows的系統目錄
編輯oracle
ini文件
用US
ASCII替換原字符集
重新啟動計算機
設置生效
否則
如果
客戶端為 sql*net
以上版本
在Win
下 運 行REGEDIT
第一步選HKEY_LOCAL_MACHINE
第二步選擇SOFTWARE
第三步選擇 Oracle
第四步選擇 NLS_LANG
鍵 入 與服 務 器 端 相 同 的 字 符 集
(本例為
HKEY_LOCAL_MACHINE\
SOFTWARE\ORACLE\NLS_LANG
AMERICAN _ AMERICA
ZHS
GBK)
如果是UNIX客戶端則 SQL> conn / as sysdba
Connected
SQL> SQL> UPDATE sys
PROPS$ SET VALUE$=
SIMPLIFIED CHINESE
WHERE NAME=
NLS_LANGUAGE
;
row updated
SQL> COMMIT;
Commit complete
SQL>
服務器指定字符集與客戶字符集相同
與加載數據字符集不一致
解決方法
強制加載數據字符集與服務器端字符集一致
要做到這一點
可以通過重新創建數據庫
並選擇與原卸出數據一致的字符集
然後IMP數據
這種情況僅僅適用於空庫和具有同一種字符集的數據
解決這類問題
也可以先將數據加載到具有相同字符集的服務器上
然後用轉換工具卸出為foxbase 格式或access格式數據庫
再用轉換工具轉入到不同字符集的Oracle數據庫中
這樣就避免了Oracle字符集的困擾
目前數據庫格式轉換的工具很多
像power builder
以上版本提供的pipeline及Microsoft Access數據庫提供的數據導入/導出功能等
服務器指定字符集與客戶字符集不同
與輸入數據字符集不一致
對於這種情況
目前為止都還沒有太好的解決方法
通過上面的了解
我們知道
導致在後期使用數據庫時出現種種關於字符集的問題
多半是由於在數據庫設計
安裝之初沒有很好地考慮到以後的需要
所以
我們完全可以通過在服務器上和客戶端使用相同的字符集來避免由此類問題引出的麻煩
From:http://tw.wingwit.com/Article/program/Java/hx/201311/27019.html