修改Django模型DecimalField的decimal_places参数时现有数据会受什么影响
调整DecimalField小数位数的迁移原理与风险说明
迁移执行原理
你要做的操作是将DecimalField的decimal_places从0调整为7、max_digits保持50不变,对应PostgreSQL侧的字段类型会从DECIMAL(50,0)转换为DECIMAL(50,7)。
这类小数位数扩容的调整属于无损操作:PostgreSQL对DECIMAL类型的小数位扩容只会增加小数部分的存储能力,原有存储的整数不会发生修改,仅会自动补对应位数的0到小数位;Django侧的AlterField操作仅同步模型字段定义与数据库侧的字段类型,不会修改数值解析逻辑,原有数值读取时的取值完全等价于调整前的结果。
你已确认所有数值范围在0到1000000000之间,调整后字段的整数部分可用位数为50-7=43位,远大于10位的最大整数长度,不存在存储容量不足的问题。
查看迁移生成的SQL语句
你可以使用Django自带的sqlmigrate命令预览迁移对应的SQL,不会实际执行迁移操作,命令格式如下:
python manage.py sqlmigrate <你的应用名称> <迁移文件序列号>
比如你本次的迁移文件是app01下的0003_auto_20240101_1234.py,就执行python manage.py sqlmigrate app01 0003即可输出完整的SQL语句。
四类风险的实际情况说明
- 数据丢失:不会出现。PostgreSQL对DECIMAL类型的小数位扩容属于无损转换,不会删除任何已有数据。
- 数据变更:不会出现。字段的数值存储逻辑与解析逻辑没有发生破坏性变更,原有整数读取时仅会多带7位小数0,数值本身与调整前完全等价。
- 溢出:仅当调整后字段的整数可用位数(
max_digits - decimal_places)小于原有数值的整数位数时才会触发,你的场景下不存在这类问题。 - NaN/NULL:默认配置下不会出现。PostgreSQL不会把合法的DECIMAL数值转换为NaN或NULL,数值越界时会直接抛出错误中断迁移,不会静默修改数据。
越界情况的处理逻辑
如果存在数值超出调整后字段的取值范围,Django执行迁移时会直接抛出DatabaseError,整个迁移流程会终止,所有修改都会回滚,不会修改原有表的任何数据。你需要先清理超出范围的异常数据,才能成功执行迁移。
内容的提问来源于stack exchange,提问作者Martin Thoma
相关产品推荐
相关产品推荐

