MySQL数值类型不支持负数的解决方法mysql不能为负

说实话,我刚接手电商项目的时候,对于这个问题是很头疼的。
那时表结构早就决定了,有些列是UNSignedINT。
然而,财务部门突然不得不记录负库存(处理退货)并陷入困境。
我想了几天,终于总结出一些方法,现在和大家聊聊。


1 .直接改变类型是最暴力的方法 然后表中有一个stock_count字段,为UNSIGNEDINT,默认值设置为0。
要更改类型,直接使用: sql ALTER TABLE Product_information MODIFY COLUMN stock_count INT;
说实话,这个操作的风险不小。
我特地选择了半夜的一个时间段备份数据库,进行修改后发现所有数据都变成正数了。
然后发现表中有一条库存为-5 的记录,直接变成了5 ——这是无符号到有符号转换的典型结果。
因此,在进行更改之前请务必确认数据范围。


2 .更灵活的查询类型转换 如果不想改变表结构,可以使用CAST。
例如: sql 选择 CAST(stock AS SIGNED) AS real_stock 来自销售订单 WHERE stock < 0>我在报告中使用了此信息,并注意到一些记录会显示 stock 为 0,但 real_stock 为 -1 检查了半天,发现是导出脚本留下的错误——原来stock列的隐藏值为-1 这种方法的优点是原始数据不变,但是在写SQL的时候需要添加过滤条件WHERE stock > 0。


3 .使用函数进行更多秘密处理 ABS功能特别有用。
例如,库存不足时显示负数: sql 选择 ABS(库存) AS stock_abs, IF(库存 < 0>我使用此功能来显示活动报告,他们非常高兴。
但让我们关注具体的问题。
例如:ABS(UNSIGNEDINT)忽略符号所以负数-5 变成正数5 后来改为: sql 选择 IF(库存 >= 0, 库存, -1 (库存 + 1 )) AS stock_ 调整后, ...
这样,负数就不会变成正数。
不过这种写法有点复杂。
我的开发同事说“编写 SQL 就像编写代码”。


4 . 小数精度 然后,财务部门要求将金额记录到小数点后两位。
我直接使用DECIMAL(1 0,2 )。
因此,会计系统输入值1 2 3 4 5 .6 7 ,数据库变为1 2 3 4 5 .6 7 000。
财务女孩差点解雇了我——原来 DECIMAL(1 0,2 ) 意味着总长度是 1 0 位数字和 2 位小数,但她没有注意精度。
现在我特别注意DECIMAL的参数设置: sql -
报告财务金额 创建表财务记录( id INT 自动递增主键, 金额 DECIMAL(1 2 ,2 ) NOT NULL 默认 0.00 );
记住请写出正确的数字。
例如,使用 DECIMAL(1 2 ,2 ) 作为金额更安全。


5 .特殊情况使用ENUM 有一个有趣的操作,我不经常使用,但值得注意。
例如,is_active 列最初为 TINYINT UNSIGNED(0 或 1 ),需要更改为枚举: sql ALTER TABLE user_status MODIFY COLUMN is_active ENUM('Inactive', 'Active');
这适用于具有固定状态的列,例如订单状态。
但缺点是移动数据很麻烦,而且 ENUM 不支持索引——所以要谨慎使用。


老实说,如果你过多地使用这些方法,你会发现最好的解决方案是在表设计中使用 INT。
但对于历史建筑的改造来说,那就是小菜一碟了。
当我现在接手一个新项目时,我被要求:
库存情报
使用的货币 DECIMAL(1 0,2 )
使用ENUM做状态(谨慎使用)
最后,还有一个不幸的情况:有一张product_stock表,其中inventory为UNSIGNEDMEDIUMINT,最大值为3 2 7 6 7 结果导入数据时,导出负inventory为3 2 7 6 6 (无符号模),我花了两个小时才发现这个错误。
因此,如果您知道数据永远不会为负,请不要使用无符号 - 即使性能实际上更高。


对于那些还没有亲自运行过这个功能的人来说,请注意:MySQL 5 .7 开始支持ZEROFILL属性,该属性可以自动给无符号数加零,比如UNSIGNEDINT ZEROFILL。
但我从未在负数情况下使用过它。
数据量太大,不敢尝试。

MySQL存储负数有限制需要注意mysql不能存负数么

坦白说,用MySQL存储负数主要取决于类型的正确选择,尤其是整数类型和浮点类型的区别。
我们先来说说最重要的事情。
如果使用太多整数,很容易超出范围。
例如,去年我们运行了一个电子商务项目,并使用 SMALLINT 来存储会员余额。
结果,用户的充值-5 万就被系统作为合法值传递了。
这就是整数真正愚弄人们的地方——它爆炸了。
另一个问题是浮点数的精度。
去年我在做金融项目的时候,用DOUBLE来存储汇率差异,结果丢了两位小数。
结果,计算的损失比实际损失多了3 000元。
还有另一个重要的细节。
MySQL 会自动转换类型,但不正确的转换可能会导致灾难。
例如,将 INT 转换为 DOUBLE 时,-1 00 变为 -1 .00e+02 很多人不重视这一点。

一开始我以为处理负数和处理正数一样简单,但后来我发现我错了。
尤其是在进行跨数据库连接时,两个表使用不同的类型来存储负数,结果的比较总是不正确的。
等等,还有一件事。
DECIMAL类型精度较高,但建表时必须手动指定长度,如DECIMAL(1 0,2 )。
如果书写错误,负数可能会被截断。
对于对负数敏感的业务场景,建议使用INT类型时留出5 0%的余量,浮点数使用DECIMAL。
怠惰にならないでください。
您认为哪种类型最容易处理负数?

MySQL 查询语句的 limit, offset 是怎么实现的?

上周发生了一些事情。
当OFFSET很大时。
效率确实很慢。
为了什么 ?我查了资料。

MySQL首先计算OFFSET+LIMIT。
分析阶段是固定的。

发送数据时。
首先屏幕在哪里。
所以看看OFFSET。
OFFSET值很大。
很多行要跳过。
数据库应该从头开始计数吗?
当然不是。
太慢了。
那么。
前辈建议使用优化方法。

例如。
有一个主键标识符。
可以保存最后一个最大的ID。

SELECT FROM t2 WHERE i1 > 9 0000000 AND id > LAST_MAX_ID LIMIT 1 0
LAST_MAX_ID 存储最后一个最大的 ID。
第一次是0。

这样。
直接从最后的位置检查。
无需全表分析。

分页符怎么办?不。

因为我们不知道下一页的起点。

现在。
您可以使用Redis。

将符合条件的ID注册到Redis zset中。

使用zset的排名功能。
获取某个页面的ID。

使用这些标识符来查询 MySQL 中的数据。

这边。
寻呼转换为ID检查。

该方法适用于数据量较大的情况。
频繁更新。

内存足够。
您可以放置​​多个标识符。

如果业务复杂。
具体情况还有待具体分析。

算了。
在这里分享一下。

MySQL为何在int类型内填写-1,报错。

未签名,是的,您需要考虑到这一点。
添加unsigned后,只能在正数范围内使用。
例如int(1 0)unsigned,范围是0到2 ^1 0-1 ,即0到1 02 3 不使用负数。

如果不加unsigned,则默认有符号,正负数都可以。
比如int(1 0),范围是-2 ^9 到2 ^9 -1 ,也就是-5 1 2 到5 1 1
我在做开发的时候,因为这个遇到了一个问题。
是表字段,添加了unsigned。
结果插入了负数,直接报错。
我花了很长时间才弄清楚。
我当时很困惑。

所以定义是否使用unsigned时一定要看清楚。
如果你的业务场景肯定不会使用负数,那么可以通过添加unsigned来节省一些存储空间。
如果您不确定,最好使用签名的。