背景:
項目使用oracle數據,在開發環境測試一些正常。項目部署到客戶的服務器上後,系統在添加數據的時候報錯。輸出錯誤信息,發現是“超出最大長度”的異常。
但是按照數據庫的設計,添加的數據應該在允許的數據長度范圍內。那麼是什麼原因導致的呢,因是客戶自己按照的oracle數據庫,懷疑是部署環境的oracle參數設置和開發環境的不同。
過程:
查詢oracle的相關參數:select * from nls_database_parameters;開發數據庫和部署數據的查詢結果如下:
開發數據庫:
部署數據庫:
經比較,發現開發庫和部署庫的 nls_characterset參數的值是不同的。
那麼一個漢字和一個英文字母在開發庫和部署庫中各自占幾個字節呢? 我們可以用sql語句查詢一下。
select lengthb('金') from dual;
select lengthb('a') from dual;
開發庫
部署庫
經查詢一個漢字在開發庫中占2個字節,而在部署庫中占三個字節。
我們可以進一步看一下“金”這個漢字在開發庫中和部署庫中到底存儲成了什麼。
使用語句: select dump('金',1016) from dual;
開發庫
部署庫
可以看到漢字“金”在開發庫中存儲為 bd f0 占用2個字節,而在部署庫中存儲為 e9 87 91 占用3個字節。
結論:那麼根據以上的信息,我們可以得出結論 當nls_characterset=zhs16gbk 時,一個漢字在oracle中占用2個字節,當nls_characterset=al32utf8時,
一個漢字在oracle中占用3個字節。
解決問題:
現在原因基本上已經找到了,那麼如何解決。這也就到了我今天想要表達的主題“規避風險”。
網上一搜,發現遇到此問題的同學還是比較多的,下面給出了修改nls_characterset和nls_length_semantics參數的方法,都可以使問題得到解決。
但是修改參數可能帶來的後果是非常嚴重的,風險系數比較高。是采用修改參數的方法是另辟蹊徑。我選擇了後者。
那麼是否可以將數據庫中的varchar2類型的字段長度擴充進而規避該問題,雖然該方法也有一定的弊端,可以在項目擴充上會有遺留問題,但是在目前來看不失為一個低風險的好方法。
生成擴充腳本的sql語句如下 :
select 'alter table '||table_name||' modify '||column_name||' VARCHAR2('||data_length*2||');'
from cols
where data_type = 'VARCHAR2'
and table_name in (select table_name from tabs where status = 'VALID')
生成數據腳本如下:
參數資料:
http://www.itpub.net/thread-838447-1-1.html
http://blog.csdn.net/lanyunit/article/details/5768581