Oracle數(shù)據(jù)庫varchar2字段擴容-始末
今天,有后端小伙伴提了個sql工單。對我司服務(wù)商系統(tǒng)Oracle數(shù)據(jù)庫的一個mer_name字段擴容。
alter table T_MER_SETTLE modify mer_name VARCHAR2(100)
審批前,我查了一下當(dāng)前這個mer_name字段的長度是 VARCHAR2(64)。
基于對我司客戶名稱的長度通常不超過64字的了解,我下意識里感到奇怪:莫非存在長度超過64個文字的客戶名稱?這種情況應(yīng)該很少吧?什么公司的名字能有這么長呢?
?文章來源地址http://www.zghlxwxcb.cn/news/detail-825166.html
然后,我找當(dāng)事人來詢問。他言說,當(dāng)時開發(fā)需求時,看到企業(yè)表里的mer_name是varchar2(100),就沿襲使用varchar2了,加上對系統(tǒng)里企業(yè)名稱長度通常不會超過64個漢字的認(rèn)識,就把新表的mer_name定義為varchar2(64)。 今天生產(chǎn)環(huán)境的告警顯示,在向這個T_MER_SETTLE表插入數(shù)據(jù)時出現(xiàn)“字段值超長”持久化失敗的bug,這才得知Oracle的varchar2(64)與mysql的varchar(64)不同,mysql的varchar(64)能存最多64個字符,而Oracle的varchar2(64)則不同。在數(shù)據(jù)庫字符集是UTF-8的情況下,varchar2在存漢字時,是每個漢字占3個字節(jié)。也就是說,這個varchar2(64)最多可以存64/3=21個漢字。
?
本著解決問題優(yōu)先的原則,我審批了sql工單并執(zhí)行sql。
?
優(yōu)秀的程序應(yīng)該盡可能地規(guī)避問題
字段擴容,這是我們?nèi)粘i_發(fā)中經(jīng)常遇到的小事。我們服務(wù)商系統(tǒng)類似對varchar2字段擴容的案例,幾乎每月都發(fā)生。那么,針對這個字段擴容,大家有沒有琢磨過,我們?nèi)绾卧陂_發(fā)時就能規(guī)避呢?
優(yōu)秀的程序應(yīng)該盡可能地規(guī)避問題。我們來復(fù)盤一下這個事情。
有必要先說明一個情況,我司絕大多數(shù)系統(tǒng)以mysql數(shù)據(jù)庫為主,服務(wù)商系統(tǒng)是其中唯一一個使用Oracle數(shù)據(jù)庫的小眾系統(tǒng)。并且,服務(wù)商系統(tǒng)的日常維護或需求迭代較少,由我們技術(shù)團隊中的三個同學(xué)抽一部分精力兼管。 因此,大家對Oracle數(shù)據(jù)庫了解得并不多,相比mysql,就少多了。
好,繼續(xù)來復(fù)盤。
開發(fā)人員不了解varchar2這個技術(shù)點,憑著mysql數(shù)據(jù)庫經(jīng)驗和對業(yè)務(wù)的了解,定義了??mer_name VARCHAR2(64)?。
我在審批時,也不了解varcahr2這個技術(shù)點,就去反問開發(fā)同學(xué)。同樣,其他同學(xué),也未必清楚Oracle的varchar2這個數(shù)據(jù)類型的細(xì)節(jié)。
?
那么,如何規(guī)避呢?
無藥可救了嗎?
不!
我們事后了解到,Oracle的nvarchar2不區(qū)分字符類型,它將漢字、全角符號與數(shù)字、字母、半角符號等均視為一個字符。也就是說,nvarchar2(64)表示可存最大64個字符。注意這里不是字節(jié),而是字符。 包括 數(shù)字、字母、符號、以及漢字。同時,在存儲含有文字的字段時,Oracle開發(fā)規(guī)范里建議使用nvarchar2取代varchar2。
因此,我們可以做什么?
將數(shù)據(jù)庫里的mer_name的數(shù)據(jù)類型全部改為nvarchar2,以及其他的這種varchar2字段類型使用不當(dāng)?shù)淖侄巍?/p>
這以后,服務(wù)商系統(tǒng)再有迭代開發(fā)時,開發(fā)者CV時,就不會(或很少)再有varchar2的mer_name了,樂觀一點講,再出現(xiàn)因varchar2數(shù)據(jù)類型使用不當(dāng)而導(dǎo)致“字段值超長”持久化失敗的bug就會扼殺在搖籃里。
?
【附】Oracle數(shù)據(jù)類型varchar2與nvarchar2
- varchar -?Oracle不建議使用varchar類型(我在DBeaver中新建varchar字段時自動建成了varchar2,無論是所見即所得的操作方式,還是執(zhí)行DDL方式)
- varchar2 -?varchar2(20)?表示可存最大20個字節(jié)長度的字符串。?數(shù)字/字母/半角符號?占一個字節(jié)。?對于全角符號或漢字,則要看字符集,GBK的話,一個漢字占2個字節(jié);UTF-8的話,一個漢字占3個字節(jié)。
- nvarchar -?Oracle中沒有nvarchar這個數(shù)據(jù)類型
- nvarchar2 -?nvarchar2(20)?表示可存最大20個字符。注意這里不是字節(jié)了,而是字符。?包括?數(shù)字、字母、符號、以及漢字。每個字符占2個字節(jié)存儲。
- varchar2是Oracle提供的特定數(shù)據(jù)類型,Oracle可以保證varchar2在任何版本中該數(shù)據(jù)類型都可以向上或向下兼容。
- nvarchar2雖然更占空間,但是它有更好的兼容性。尤其是當(dāng)字段包含漢字的情況下,推薦使用nvarchar2。? - - - - - - - - 我們服務(wù)商系統(tǒng)Oracle數(shù)據(jù)庫里,對于mer_name等包含漢字的字段,大家往往沿襲使用varchar2(100甚至更大),我們在新建表里涉及到這個字段時,有開發(fā)者會誤以為Oracle的varchar2與mysql里的varchar相同,我們mysql應(yīng)用里約定mer_name是varchar(32) ,就在Oracle庫里定義成了 varchar2(32) ,結(jié)果,服務(wù)商系統(tǒng)在生產(chǎn)運行過程中,出現(xiàn)插入mer_name因字段值超長而持久化數(shù)據(jù)庫失敗。 - - - - - - - -?優(yōu)秀的程序應(yīng)總是盡可能地規(guī)避問題。因此,以后在服務(wù)商系統(tǒng)里,當(dāng)定義包含漢字的字段時,使用?nvarchar2,而非?varchar2。?因此,在服務(wù)商系統(tǒng)作為我司系統(tǒng)的小眾系統(tǒng)的背景下,Oracle的技術(shù)特性我們不一一曉知是可以理解和接受的。而如何在不一一曉知這些技術(shù)特性的情況下,能夠規(guī)避這些技術(shù)特性帶來的bug,需要我們引起思考和實踐摸索。
?【附】字段值超長,程序異常截圖↓
文章來源:http://www.zghlxwxcb.cn/news/detail-825166.html
?
到了這里,關(guān)于不能坐視了!Oracle數(shù)據(jù)庫varchar2字段擴容,每月總有那么一兩次。----- 優(yōu)秀的程序應(yīng)總是盡可能地規(guī)避問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!