問題描述
數(shù)據(jù)存儲過程中抚笔,部分字符串過長,超出數(shù)據(jù)庫所設置的最大長度侨拦,從而導致數(shù)據(jù)插入失敗殊橙。
解決辦法
方案一:加大數(shù)據(jù)庫字段長度,以適應數(shù)據(jù)要求狱从。
方案二:據(jù)說可以在數(shù)據(jù)庫(mysql)層面作處理膨蛮,更改某些配置即可,不大懂季研。
方案三:裁剪數(shù)據(jù)敞葛,使得長度在數(shù)據(jù)庫范圍之內。
簡單分析
以上三個方案都能避免數(shù)據(jù)丟失与涡,數(shù)據(jù)庫出錯的問題惹谐。但方法各有好處和不足持偏。
對于方案一,是一個最直接的方法氨肌。但是這樣處理有點治標不治本鸿秆,下次又出現(xiàn)更長的字符串呢?另外怎囚,此方法適合在開發(fā)階段去更改數(shù)據(jù)庫字段長度卿叽,對于已上線的代碼,不建議去更改數(shù)據(jù)庫表結構桩了,特別是當數(shù)據(jù)庫對應表的數(shù)據(jù)很大的時候。(另埠戳,普及一個小知識點井誉,數(shù)據(jù)庫的varchar類型所設置的長度是最大允許長度,并非實際占用的存儲空間大小整胃。實際存儲空間大小由實際插入字符長度決定)
再來看看方案二颗圣,同樣是在數(shù)據(jù)庫層面作修改,但不再是更改表結構屁使,而是更改數(shù)據(jù)庫模式為非嚴格模式在岂。原理如圖:
因為數(shù)據(jù)庫配置方面不大懂,也沒試過蛮寂,所以對于方案二不作其他分析蔽午。
方案三則是更改代碼,在插入數(shù)據(jù)庫之前對值進行裁剪酬蹋,使得字符串長度滿足數(shù)據(jù)庫要求及老。是一種比較適合已上線項目的方案。一是不用冒著風險去更改數(shù)據(jù)庫結構范抓,二是相對來說骄恶,算是從根源上解決了數(shù)據(jù)過長,數(shù)據(jù)插入失敗的問題匕垫。當然僧鲁,因為裁剪了字符串,該方案依然會使得信息部分丟失象泵。具體用那個方案解決寞秃,視具體情況而定。
方案三的pony orm解決過程
方法一:將字符串長度可能過長的地方都加上字符串長度檢查并裁剪過長的字符偶惠。
方法二:通用解決方法蜕该,在orm執(zhí)行之前,根據(jù)模型定義的長度自動作裁剪洲鸠。
明顯堂淡,方案二更簡潔馋缅、更智能。不用滿項目的去找可能過長的地方绢淀。
具體操作為:
在模型定義的時候萤悴,繼承并重寫init方法,具體代碼為:
class TestTable(db.Entity):
def __init__(self, *args, **kwargs):
for field in getattr(type(self), '_columns_without_pk_'): # 讀取模型定義的所有字段
field_type = getattr(type(self), field).py_type # 獲取字段類型
if field_type == str:
cur_value = kwargs.get(field) # 獲取傳入的字符串
if not cur_value:
continue
params = getattr(type(self), field).args # 獲取字段設置的參數(shù)
str_len = 255 # 默認的str類型的最大長度
if params:
str_len = params[0] # 獲取設置的str類型字段允許的最大長度
if len(cur_value) > str_len: # 對超標的字符串進行裁剪
kwargs[field] = cur_value[:str_len]
super(db.Entity, self).__init__(*args, **kwargs)
name = Required(str, 4, index=True)
desc = Optional(str, 10)
這樣定義的數(shù)據(jù)庫模型就支持自動裁剪了皆的。以上代碼僅作原理展示覆履,為更簡潔的書寫,可以將以上邏輯轉化為裝飾器费薄,并加上合理的try語句硝全。