You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite中限制数值列整数10位小数4位无效,ALTER语句是否有误?

嘿,你的ALTER语句语法上完全没问题!之所以插入10.123456没触发你预期的错误,核心原因是大多数数据库对numeric(p,s)类型的默认处理逻辑不是直接报错,而是自动对超出小数位的值做四舍五入或截断,悄悄把值调整到符合列定义的精度后存储。

问题拆解与解决方案

1. 你的ALTER语句本身没有问题

ALTER TABLE scustdisc ADD COLUMN spec_price numeric(10,4) 这个语句是完全合法的:

  • 10代表数值的总位数(小数点前+小数点后)最多10位
  • 4代表小数点后最多保留4位
    语法和逻辑定义上都没有错误。

2. 为什么插入超精度值不报错?

不同数据库的默认行为略有差异,但核心逻辑一致:

  • PostgreSQL:默认会自动将超出小数位的数值四舍五入到指定精度。比如你插入10.123456,实际存储的是10.1235(四舍五入到4位小数),不会触发错误。
  • MySQL:如果没开启严格模式(默认可能没开),同样会自动截断或四舍五入超精度的值,不会报错。只有当sql_mode包含STRICT_TRANS_TABLES时,才会触发错误。

3. 如何实现“超精度就报错”的预期效果?

根据你使用的数据库类型,有两种常见方案:

方案一:添加检查约束(通用,适合所有支持CHECK的数据库)

给spec_price列添加检查约束,强制要求数值的小数位不超过4位,同时整数部分不超过6位(因为总位数10-小数位4=6):

ALTER TABLE scustdisc ADD CONSTRAINT chk_spec_price_precision 
CHECK (
  -- 限制整数部分最多6位,小数部分最多4位
  spec_price BETWEEN -999999.9999 AND 999999.9999
  -- 确保小数位不超过4位(乘以10000后是整数)
  AND (spec_price * 10000) = FLOOR(spec_price * 10000)
);

这样再插入10.123456时,就会因为违反检查约束而报错。

方案二:修改数据库模式(针对特定数据库)

  • MySQL:开启严格模式,修改sql_mode参数:

    -- 临时生效,重启数据库后失效
    SET sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
    -- 永久生效,需要修改my.cnf/my.ini配置文件,添加或修改该行后重启
    sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
    

    开启后,插入超精度值就会直接触发错误。

  • PostgreSQL:没有全局的严格模式开关,最可靠的方式就是用上面的检查约束来实现拦截。


内容的提问来源于stack exchange,提问作者ProfileForStack4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:36:39