oracle的userenv和nls_lang詳解
1、userenv最常見的使用
userenv函數返回當前會話(session)的相關信息。以下sql語句可以查詢當前會話連接的數據庫字符集
select userenv('language') from dual;
有關userenv('parameter')
返回值的官網介紹如下
意思就是:返回的是當前會話使用的language和territory。characterset是數據庫的字符集。
下面我們就去驗證這種情況
2、windows上plsql使用userenv
先看下數據庫真實的語言、地區和字符集
再看下windows上NLS_LANG環境變量
最后看下plsql上userenv執行的結果
可以發現在windows上使用plsql的時候語言和地區使用的是plsql的環境變量NLS_LANG。
3、Linux上sqlplus使用userenv
首先看一下NLS_LANG為空的情況下userenv的返回值
可以看到userenv('language')
的返回值是AMERICAN_AMERICA.ZHS16GBK
。這個值是怎么來的呢?從Oracle官網上看是取的默認值,如下圖
- 如果Oracle通用安裝程序沒有指定NLS_LANG,則默認值是
AMERICAN_AMERICA.US7ASCII
- 如果language沒有指定,則language的默認值是
AMERICAN
- 如果territory沒有指定,則territory的默認值由language這個值派生而來。
- 如果charset沒有指定,則在創建session的時候charset的值是數據庫的characterset。
- NLS_LANG的每一個component都是可選的,如果只想指定NLS_LANG的territory,那么需要這樣指定:
NLS_LANG=_JAPAN
。此時territory的值是JAPAN
具體參見:Choosing a Locale with the NLS_LANG Environment Variable
下面繼續驗證
可以看到指定NLS_LANG之后,userenv('language')
從會話中取得的語言和地區發生了變化,但是字符集仍然取得的是數據庫的字符集。
4、問題:中文亂碼在哪個環節產生的?
由以上分析可知,不管是什么樣的客戶端程序(不管是plsql還是sqlplus),在創建會話的時候字符都是取數據庫本身的字符集。因此客戶端程序和session的字符集不一致的時候會產生轉碼。如果轉碼的過程中出現了字節損失,則存儲的真實數據就是損失之后的數據。至於我們看到的亂碼是因為存儲的數據會在查詢的時候再次轉碼成客戶端程序的字符集,由於數據缺失,因此就亂碼了。
至於中文亂碼的驗證可以參見【字符集】論Oracle字符集“轉碼”過程
記得幫我點贊哦!
精心整理了計算機各個方向的從入門、進階、實戰的視頻課程和電子書,按照目錄合理分類,總能找到你需要的學習資料,還在等什么?快去關注下載吧!!!
念念不忘,必有回響,小伙伴們幫我點個贊吧,非常感謝。
我是職場亮哥,YY高級軟件工程師、四年工作經驗,拒絕咸魚爭當龍頭的斜杠程序員。
聽我說,進步多,程序人生一把梭
如果有幸能幫到你,請幫我點個【贊】,給個關注,如果能順帶評論給個鼓勵,將不勝感激。
職場亮哥文章列表:更多文章
本人所有文章、回答都與版權保護平台有合作,著作權歸職場亮哥所有,未經授權,轉載必究!