1.問題介紹
根本原因是字符集的問題,是數據庫的字符集和寫入程序的linux系統的字符集不一致導致;
但是用export NLS_LANG=”SIMPLIFIED CHINESE”_CHINA.ZHS16GBK添加環境變量,或者在.bash_profile文件中添加這個環境變量,或者在/etc/profile文件中添加這個環境變量,用source 命令使其生效,後寫入oralce數據庫的中文還是問號?,接着有重啓了系統,重啓了服務器,讓環境變量生效,還是顯示問號;
2.正確的用代碼設置字符集的方法
(1)在服務器端查看字符集的類型
用命令:select userenv('language') from dual 查看數據庫的字符集類型是SIMPLIFIED CHINESE_CHINA.ZHS16GBK,注意顯示中文末尾必須是ZHS16GBK;
(2)在寫入數據庫的程序中初始化的數據庫之前採用下面的代碼設置環境變量
char chValueName[] = "NLS_LANG";
string strLang="SIMPLIFIED CHINESE_CHINA.ZHS16GBK";//必須與數據庫服務端的一致
int errorcode=setenv(chValueName, strLang.c_str(), 1);
if (errorcode!=0)
{
ERROR("linux setenv %s failed errorcode %d !",strLang.c_str(),errorcode);
}
else
{
INFO("linux setenv %s succeed !",strLang.c_str());
}
(3)編譯程序,重新運行,就可以正常寫入漢字到oracle數據庫了;
3.字符集介紹
NLS_LANG格式:
NLS_LANG = language_territory.charset
有三個組成部分(語言、地域和字符集),每個成分控制了NLS子集的特性。其中:language
指定服務器消息的語言。
territory 指定服務器的日期和數字格式。
charset 指定字符集,只要這一個一致,就可以寫入漢字到數據庫,這個字段的值決定了字符轉換格式,如果不一致,就會找不到字符,一個漢字就會顯示爲兩個問號;
4.linux添加環境變量的幾種方法
(1)直接在終端用命令添加,這個環境變量設置只在該終端窗口中有效,退出窗口就會失效;
export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
(2)在.bash_profile文件中添加,/etc/profile對所有用戶生效,~/.bash_profile只對當前用戶生效。用命令vi .bash_profile添加也是用export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
(3)在/etc/profile中添加,對所有的用戶有效;修改完後需要用source命令使其生效;
vi /etc/profile
(4)使用shell腳本添加環境變量
if grep -Fxq "export NLS_LANG=\"SIMPLIFIED CHINESE\"_CHINA.ZHS16GBK" /etc/profile
then
echo " export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK found"
else
echo " add NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK to file"
sed -i '$a export NLS_LANG=\"SIMPLIFIED CHINESE\"_CHINA.ZHS16GBK' /etc/profile
source /etc/profile
fi
5.windows下設置環境變量
char chValueName[] = "NLS_LANG";
string strLang=SIMPLIFIED CHINESE_CHINA.ZHS16GBK;
HKEY hKey = NULL;
DWORD dwDataLen = SMALL_LEN;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, “System\\CurrentControlSet\\Control\\Session Manager\\Environment”, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
{
DB_DEBUG("RegOpenKey %s fail, err:%ld", “System\\CurrentControlSet\\Control\\Session Manager\\Environment”, GetLastError());
break;
}
//先查看有沒有環境變量
if (RegQueryValueEx(hKey, chValueName, NULL, NULL, (BYTE*)chData, &dwDataLen) == ERROR_SUCCESS)
{//如果已經設置且相同則返回
if (strLang.compare(chData) == HPR_OK)
{
RegCloseKey(hKey);
iRetVal = HPR_OK;
break;
}
}
RegCloseKey(hKey);
//如果沒有設置或者不同,則重新設置;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_chRegEnvPath, 0, KEY_SET_VALUE, &hKey) != ERROR_SUCCESS)
{
break;
}
RegSetValueEx(hKey, chValueName, 0, REG_SZ, (const BYTE*)strLang.c_str(), strLang.length());
DWORD_PTR dwResult = 0;
//使立即生效
LRESULT lRet = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM("Environment"), SMTO_ABORTIFHUNG, 2000, &dwResult);
if (lRet != 0)
{
RegCloseKey(hKey);
DB_DEBUG("Change Oracle nls lang:%s to:%s success!", chData, strLang.c_str());
break;
}
DB_DEBUG("Change Oracle nls lang:%s to:%s failed!", chData, strLang.c_str());
RegCloseKey(hKey);