问题描述
数据存储过程中,部分字符串过长,超出数据库所设置的最大长度,从而导致数据插入失败。
解决办法
方案一:加大数据库字段长度,以适应数据要求。
方案二:据说可以在数据库(mysql)层面作处理,更改某些配置即可,不大懂。
方案三:裁剪数据,使得长度在数据库范围之内。
简单分析
以上三个方案都能避免数据丢失,数据库出错的问题。但方法各有好处和不足。
对于方案一,是一个最直接的方法。但是这样处理有点治标不治本,下次又出现更长的字符串呢?另外,此方法适合在开发阶段去更改数据库字段长度,对于已上线的代码,不建议去更改数据库表结构,特别是当数据库对应表的数据很大的时候。(另,普及一个小知识点,数据库的varchar类型所设置的长度是最大允许长度,并非实际占用的存储空间大小。实际存储空间大小由实际插入字符长度决定)
再来看看方案二,同样是在数据库层面作修改,但不再是更改表结构,而是更改数据库模式为非严格模式。原理如图:
因为数据库配置方面不大懂,也没试过,所以对于方案二不作其他分析。
方案三则是更改代码,在插入数据库之前对值进行裁剪,使得字符串长度满足数据库要求。是一种比较适合已上线项目的方案。一是不用冒着风险去更改数据库结构,二是相对来说,算是从根源上解决了数据过长,数据插入失败的问题。当然,因为裁剪了字符串,该方案依然会使得信息部分丢失。具体用那个方案解决,视具体情况而定。
方案三的pony orm解决过程
方法一:将字符串长度可能过长的地方都加上字符串长度检查并裁剪过长的字符。
方法二:通用解决方法,在orm执行之前,根据模型定义的长度自动作裁剪。
明显,方案二更简洁、更智能。不用满项目的去找可能过长的地方。
具体操作为:
在模型定义的时候,继承并重写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 # 获取字段设置的参数
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)
这样定义的数据库模型就支持自动裁剪了。以上代码仅作原理展示,为更简洁的书写,可以将以上逻辑转化为装饰器,并加上合理的try语句。