前言
本文为阅读MySql官方文档的翻译,为笔者的阅读和扩展路径。
简介
DECIMAL和NUMERIC类型(定点类型)的存储精度数值的数据值。当保持精确精度是很重要时使用这些类型,例如货币数据。在MYSQL中,NUMERIC被实现为DECIMAL,所以以下关于DECIMAL的评论同样适用于NUMERIC。
MYSQL以二进制格式存储值。请参见12.25 Precision Math。
在DECIMAL列声明中,可以指定(并且通常)指定精度和小数位数。例如:
salary DECIMAL(5,2)
在本例中,5是精度,2是小数位。精度表示存储值的有效位数,小数表示可以存储在小数点后的位数。
标准SQL要求DECIMAL(5,2)能够存储任何五位数字和两位小数的值,因此可以存储在salary列中的值范围从-999.99到999.99。
在标准的SQL中,语法DECIMAL(M)等同于DECIMAL(M,0)。类似的,语法DECIMAL等同于DECIMAL(M,0),MySQL支持这两种语法,M的默认值位10。
如果scale是0,则DECIMAL值不包含小数点和小数部分。
DECIMAL最大位数为65,但给定DECIMAL列实际范围受指定的精度和小数位限制。因此当该列是被分配超过指定范围时,该值将转换成指定范围内。(确切的行为是特定于操作系统的,但通常效果时截断到允许的位数。)
DECIMAL数据类型特征
本节讨论DECIMAL数据类型(及其同义词)的特征,特别注意以下主题:
- 最大位数
- 存储格式
- 存储要求
- 非标准MySQL扩展到DECIMAL列的上限。
DECIMAL列的声明语法是DECIMAL(M,D)。参数取值的范围如下:
- M是最大数(精度)。它的范围是1到65.
- D是小数点右侧的位数(刻度)。它的范围是0到30,并且不能大于M。
如果D省略,则默认为0。如果M省略,则默认为10。
M的最大值65意味着DECIMAL值的计算是精确到65位。65位精度的限制也适用于精确数值字面量,因此此类字面量的最大范围与之前不同。(DECIMAL的文本的长度也有限制;请参阅 第 12.25.3 节,“表达式处理”。)
DECIMAL列值是存储使用二进制格式,将9个十进制数字打包成4个字节。每个小数的整数部分和小数部分的存储要求是分别明确的。每个九位数的倍数需要4个字节,剩下的任何剩余数字都需要4个字节的一部分。下表给出了剩余数字所需的存储空间。
剩余数字 | 字节数 |
---|---|
0 | 0 |
1-2 | 1 |
3–4 | 2 |
5–6 | 3 |
7–9 | 4 |
例如,DECIMAL(18,9)列的小数点两边各有九位,因此整数部分和小数部分各需要4个字节。 DECIMAL(20,6)列有14个整数位和6个小数位。整数位中的九位需要四个字节,其余五位需要三个字节,六位小数需要三个字节。
DECIMAL列不存储前导+字符或者前导-字符或者前导0数字。如果插入+0003.1到DECIMAL(5,1)列中,它将存储3.1。对于负数,-字符是不被存储。
DECIMAL列不允许值大于列定义所暗示的范围。例如,DECIMAL(3,0)列支持范围为-999至999。 DECIMAL(M,D)小数点左边允许最多有M-D位。
SQL标准要求NUMERIC(M,D)的精度是确切的M位。对于DECIMAL(M,D),标准要求精度至少为M位,但允许更多。在MySQL中,DECIMAL(M,D) 和 NUMERIC(M,D) 是相同的,并且都具有 M 位的精度。
有关DECIMAL值的内部格式的完整说明 ,请参阅MySQL发布的源代码strings/decimal.c文件。该格式在decimal2bin()函数中进行了解释(通过示例) 。
decimal_t
下面为decimal的数据结构,不代表实际存储。
typedef int32 decimal_digit_t;
struct decimal_t {
int intg, frac, len;
bool sign;
decimal_digit_t *buf;
};
- intg表示整数部分的数字个数
- frac表示小数部分的数字个数
- sign表示符号(正负)
- len表示数组长度,在MySQL实现中恒为9,表示存储的上限,而 buf 实际有效的部分, 则是由 intg 和 frac 共同决定
- *buf表示存储decimal的数字
例如
// 123.45 decimal(5, 2) 整数部分为 3, 小数部分为 2
decimal_t dec_123_45 = {
int intg = 3;
int frac = 2;
int len = 9;
bool sign = false;
decimal_digit_t *buf = {123, 450000000, ...};
};
总结
- DECIMAL位定点类型,可以精确的表示规定精度
- DECIMAL(M,D) M表示精度,D表示小数位。
- M默认为10。标准MySQL,M最大为65,超出部分通常截断。
- D默认为0,最大为30且不能大于M。
- DECIMAL存储使用二进制格式,整数和小数是分开存储的,用4个字节表示9个十进制数。