mysql decimal类型主要场景_MySQL中Decimal类型和Float Double的区别 & BigDecimal与Double使用场景...

MySQL数据类型详解

MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型。

其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值。

float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理。这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实际存储是0,同样我存取货币为12.00,实际存储是12。

幸好mysql提供了两个数据类型:decimal,这种数据类型可以轻松解决上面的问题:decimal类型被 MySQL 以同样的类型实现,这在 SQL92 标准中是允许的。他们用于保存对准确精度有重要要求的值,例如与金钱有关的数据。

数据定义

float(M,S) M为全长,S为小数点后长度。

数据库类型和Java类型之间的关系:

DBC Type                            Java Type

CHAR                                     String

VARCHAR                              String

LONGVARCHAR                    String

NUMERIC                        java.math.BigDecimal

DECIMAL                         java.math.BigDecimal

BIT                                        boolean

BOOLEAN                            boolean

TINYINT                                  byte

SMALLINT                              short

INTEGER                                int

BIGINT                                    long

REAL                                      float

FLOAT                                   double

DOUBLE                               double

BINARY                                 byte[]

VARBINARY                          byte[]

LONGVARBINARY                byte[]

DATE                                  java.sql.Date

TIME                                   java.sql.Time

TIMESTAMP                       java.sql.Timestamp

CLOB                                     Clob

BLOB                                     Blob

ARRAY                                  Array

DISTINCT                           mapping of underlying type

STRUCT                                Struct

REF                                        Ref

项目中BigDecimal与Double使用场景

金额要用BigDecimal

金额计算不能用doube!!!!

金额计算必须用BigDecimal,下面对比一下用double 跟BigDecimal的区别。先看一个小例子:

请看题:

9e3af1e44fc0ce1bbefe98d21ff34832.png

示例1

问, 结果是多少? 0.01?

No! 结果是0.009999999999999998!

为什么会这样呢? 因为float和double都是浮点数, 都有取值范围, 都有精度范围. 浮点数与通常使用的小数不同, 使用中, 往往难以确定.

常见的问题是定义了一个浮点数, 经过一系列的计算, 它本来应该等于某个确定值, 但实际上并不是!

double相减会转换成二进制,因double有效位数为 16位这就会出现存储小数位数不够的情况,这种情况下就会出现误差,解决方法就是使用BigDecimal,它的有效长度足够长可存储小数位数。

因此可代替double来进行加减乘除, 金额必须是完全精确的计算, 故不能使用double或者float, 而应该采用java.math.BigDecimal.

加减乘除

两个BigDecimal值应该怎样进行加减乘除呢? +, -, *, / 这样写吗? 不!

请看示例:

437b26a26fb02121a265e495ec014de3.png

加减乘除使用了英文的加减乘除, 即add, substract, multiply和divide

大小比较

两个BigDecimal值怎么比较大小呢? 能用>或者

003d560d9bc5018ce0d197d78d67a211.png

两个BigDecimal值比较使用compareTo方法, 比较结果有-1, 0, 1, 分别表示小于, 等于, 大于; 对于0, 可以使用BigDecimal.ZERO表示!

四舍五入

f01e96a2572081cde5f59ac08ba4bf66.png

简化BigDecimal计算的小工具类

如果我们要做一个加法运算,需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮点数。

你能够忍受这么烦琐的过程吗?

网上提供的工具类Arith来简化操作。它提供以下静态方法,包括加减乘除和四舍五入:

public   static   double   add(double   v1,double   v2)

public   static   double   sub(double   v1,double   v2)

public   static   double   mul(double   v1,double   v2)

public   static   double   div(double   v1,double   v2)

public   static   double   div(double   v1,double   v2,int   scale)

public   static   double   round(double   v,int   scale)

定点数和浮点数的区别

在计算机系统的发展过程中,曾经提出过多种方法表达实数。典型的比如相对于浮点数的定点数(Fixed Point Number)。在这种表达方式中,小数点固定的位于实数所有数字中间的某个位置。

货币的表达就可以使用这种方式,比如 99.00 或者 00.99 可以用于表达具有四位精度(Precision),小数点后有两位的货币值。由于小数点位置固定,所以可以直接用四位数值来表达相应的数值。

SQL 中的 NUMBER 数据类型就是利用定点数来定义的。还有一种提议的表达方式为有理数表达方式,即用两个整数的比值来表达实数。

定点数表达法的缺点在于其形式过于僵硬,固定的小数点位置决定了固定位数的整数部分和小数部分,不利于同时表达特别大的数或者特别小的数。

最终,绝大多数现代的计算机系统采纳了所谓的浮点数表达方式。这种表达方式利用科学计数法来表达实数,即用一个尾数(Mantissa ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。

比如 123.45 用十进制科学计数法可以表达为 1.2345 × 102 ,其中 1.2345 为尾数,10 为基数,2 为指数。浮点数利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数。

在MySQL中使用浮点数类型和定点数类型来表示小数。浮点数类型包括单精度浮点数(FLOAT型)和双精度浮点数(DOUBLE型)。定点数类型就是DECIMAL型。MySQL的浮点数类型和定点数类型如下表所示:

类型名称字节数负数的取值范围非负数的取值范围

FLOAT

4

-3.402823466E+38~

-1.175494351E-38

0和1.175494351E-38~

3.402823466E+38

DOUBLE

8

-1.7976931348623157E+308~

-2.2250738585072014E-308

0和2.2250738585072014E-308~

1.7976931348623157E+308

DECIMAL(M,D)或DEC(M,D)

M+2

同DOUBLE型

同DOUBLE型

从上表中可以看出,DECIMAL型的取值范围与DOUBLE相同。但是,DECIMAL的有效取值范围由M和D决定,而且DECIMAL型的字节数是M+2,也就是说,定点数的存储空间是根据其精度决定的。

MySQL

BigDecimal在进行入库时, 数据库选择decimal类型, 长度可以自定义, 如18; 小数点我们项目中用的是2, 保留2位小数. 此外还要注意的就是默认值, 一定写成0.00, 不要用默认的NULL, 否则在进行加减排序等操作时, 会带来转换的麻烦!

`balance` decimal(18,2) DEFAULT '0.00' COMMENT '账户余额',

MySQL DECIMAL数据类型用于在数据库中存储精确的数值。我们经常将DECIMAL数据类型用于保留准确精确度的列,例如会计系统中的货币数据。

要定义数据类型为DECIMAL的列,请使用以下语法:

在上面的语法中:

P是表示有效数字数的精度。 P范围为1〜65。

D是表示小数点后的位数。 D的范围是0~30。MySQL要求D小于或等于(<=)P。

DECIMAL(P,D)表示列可以存储D位小数的P位数。十进制列的实际范围取决于精度和刻度。

与INT数据类型一样,DECIMAL类型也具有UNSIGNED和ZEROFILL属性。 如果使用UNSIGNED属性,则DECIMAL UNSIGNED的列将不接受负值。

如果使用ZEROFILL,MySQL将把显示值填充到0以显示由列定义指定的宽度。 另外,如果我们对DECIMAL列使用ZERO FILL,MySQL将自动将UNSIGNED属性添加到列。

以下示例使用DECIMAL数据类型定义的一个叫作amount的列。

在此示例中,amount列最多可以存储6位数字,小数位数为2位; 因此,amount列的范围是从-9999.99到9999.99。

参考:

https://www.jb51.net/article/109363.htm

https://www.cnblogs.com/owenma/p/7991508.html

http://www.cnblogs.com/owenma/p/7097602.html

&lt;think&gt;我们正在讨论MySQL数据库中的decimal类型在Java中能否用int类型获取的问题。 从引用中我们得知: - MySQLDECIMAL类型通常用于存储精确的小数,例如金钱等需要高精度的数据。 - 在Java中,MySQLDECIMAL类型相对应的类型BigDecimal(引用[2][3][4])。 引用[2][3]明确说明了DECIMAL在Java中对应BigDecimal,并且引用[3]还提到BigDecimal是用来进行精确计算的,尤其是在商业计算中。 现在问题是:能否用int类型来获取MySQLdecimal类型的数据? 分析: - int是整数类型,而decimal可以存储小数(也可以存储整数,但它的设计是为了处理小数,特别是固定精度的小数)。 - 如果decimal字段存储的是整数部分(即小数部分为0),并且该整数的范围在int的范围内(-2147483648到2147483647),那么从数值上看,是可以转换为int的。但是,数据库驱动在映射类型时,通常不会自动将decimal类型映射到Java的int类型,因为decimal可能有小数部分,而int无法表示小数。 因此,在Java中,我们通常使用BigDecimal来接收decimal类型的数据,以确保精确性避免精度损失。 但是,如果确保该decimal字段存储的都是整数,并且不会超过int的范围,我们可以在获取到BigDecimal后,将其转换为int(例如,使用BigDecimal的intValue()方法),但这可能会导致溢出问题(如果值超过int的范围)或舍入问题(如果有小数部分,则会被截断)。 所以结论是:在Java中,不能直接用int类型来映射MySQLdecimal字段,因为类型不匹配。通常的做法是使用BigDecimal接收,然后根据需要转换(如果确定是整数且范围合适,可以转换为int;否则,应保留为BigDecimal)。 步骤: 1. 在Java中,使用BigDecimal来接收数据库中的decimal类型字段。 2. 如果业务需要整数,并且确定该字段的值是整数且不会超过int的范围,则可以通过调用BigDecimal的intValue()方法转换为int。但要注意,如果有小数部分,intValue()会直接截断小数部分(不是四舍五入),这可能会导致数据错误。 因此,建议除非明确知道数据是整数且在int范围内,否则不要转换为int。 示例代码: ```java // 假设从数据库获取的结果集是rs,字段名为&quot;price&quot; BigDecimal decimalValue = rs.getBigDecimal(&quot;price&quot;); // 如果确定是整数且不超出int范围,可以转换 // 但要注意:如果decimalValue有小数部分,转换会丢失小数部分 int intValue = decimalValue.intValueExact(); // 如果小数部分不为0或者超出int范围,会抛出异常 // 或者使用intValue(),但不会抛出异常,只是截断小数部分(如果有)并可能溢出(超出范围时结果不可预测) ``` 使用intValueExact()方法可以确保转换的精确性:如果BigDecimal不是整数或者超出了int的范围,就会抛出ArithmeticException。 所以,直接使用int类型映射是不行的,但可以在获取BigDecimal后转换为int(需要满足条件)。 注意事项:在数据库设计中,如果确定某个字段是整数,应该使用整型(如INT或BIGINT)而不是DECIMAL。 因此,针对用户的问题:MySQL数据库decimal类型数据在Java中能否用int类型获取? 回答:不能直接使用int类型来获取,因为类型不匹配;但可以在获取BigDecimal后,根据情况转换为int(需要满足整数且不超范围的条件)。 相关问题: 1. 在Java中如何正确处理MySQLDECIMAL类型? 2. BigDecimalint之间如何安全转换? 3. 为什么商业计算中推荐使用BigDecimal而不是doublefloat? 4. MySQLDECIMAL类型整型字段(如INT)有什么区别? 5. 如何避免在类型转换中丢失精度? &lt;/think&gt;### MySQL DECIMAL类型在Java中的映射问题 在MySQL数据库中,**DECIMAL类型数据不能用Java的int类型直接获取**。以下是详细分析: #### 1. **类型不匹配** - **DECIMAL本质**:MySQLDECIMAL是**精确小数类型**(如`DECIMAL(10,2)`可存储`12345678.99`),设计用于存储精确的十进制数值(如金额)[^2][^3]。 - **int本质**:Java的int是**32位整数类型**,只能存储整数值(范围:-2&sup3;&sup1; ~ 2&sup3;&sup1;-1),无法处理小数部分。 #### 2. **正确映射方式** - ✅ **必须使用`BigDecimal`**(来自`java.math`包)接收DECIMAL数据: ```java // JDBC正确示例 BigDecimal decimalValue = resultSet.getBigDecimal(&quot;column_name&quot;); ``` 原因: - `BigDecimal`可精确表示任意精度的十进制数(如`123.456`)[^3]。 - 支持银行家舍入、高精度计算等场景[^3][^4]。 #### 3. **强制转换的风险** 若强行用int接收DECIMAL字段: - **小数部分丢失**:DECIMAL值`100.99`会被截断为`100`。 - **范围溢出**:DECIMAL值`2147483648.00`(大于int最大值)会导致数据错误。 - **代码异常**:JDBC会抛出`SQLException`(类型不匹配)。 #### 4. **特殊情况处理** 若DECIMAL字段**确定存储整数**(如`DECIMAL(10,0)`),可**分两步处理**: 1. 用`BigDecimal`接收: ```java BigDecimal value = resultSet.getBigDecimal(&quot;id&quot;); ``` 2. 转为int(需验证范围): ```java if (value.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) &lt;= 0) { int intValue = value.intValueExact(); // 无小数时安全转换 } ``` ⚠️ 需严格检查数据范围小数位,否则推荐用`long`或`BigDecimal`。 --- ### 总结 | 数据库类型 | Java正确类型 | 错误类型 | 风险 | |------------|--------------|----------|------| | DECIMAL | `BigDecimal` | `int` | 精度丢失、溢出、异常 | | BIGINT | `long` | `int` | 数值截断[^1] | **建议**:始终优先使用`BigDecimal`处理DECIMAL类型,确保数据精确性[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值