天天看点

MySQL Meta 信息与 CREATE TABLE 的对应关系前情提要混乱的MySQL定义总结

下面四篇文章是数月之前对length的理解

<a href="http://blog.csdn.net/maray/article/details/48657119">mysql meta中的length字段 -- (1) 初始值的length计算</a>

<a href="http://blog.csdn.net/maray/article/details/48660725">mysql meta中的length字段 -- (2) length的推导</a>

<a href="http://blog.csdn.net/maray/article/details/48687731">mysql meta中的length字段 -- (3) length的推导举例</a>

<a href="http://blog.csdn.net/maray/article/details/48712329">mysql meta中的length字段 -- (4) 玩儿mysql代码</a>

温故而知新,几个月后,对 length 等 meta 信息的理解又进一步,本文再记之。

用“混乱”这个词有点大言不惭,但是,mysql通过sql语句描述 length、scale、precision、display width这几个概念,描述手法真的很混乱。

你能清楚地描述 length、scale、precision、display width 四个概念吗?他们的区别与关联是什么?create table 语句如何表达这四个概念?

如果你能说清楚,就已经掌握,不用看本文了。说不清楚,就听我慢慢道来。

本文简单起见,只以 mysql 的四大类数据类型作为范例讨论:

整形(int、tinyint、mediumint、bigint)

浮点(float、double)

字符串(binary、char、varbinary、varchar)

定点数(decimal)

创建一个包含上面4中类型的表:

i int(3)

其中 3 仅仅表示display width,i 的 precision 为 11,也就是说,insert into sample (i) values (1234567) 是没问题的,尽管1234567的位数超过了3位。它的 scale 为 0。它的 length 是 3,它的 length 是 3,它的 length 是 3(重要事情说三遍!!!),display width 等于 length。

在这种情况下,如果客户端傻乎乎地按照length的值分配内存,必将buffer溢出。怎么办?客户端才不会相信服务器传来的这个值,它完全可以根据type=long来分配一个最大buffer,确保任意整数都能放得下。

理解了上面的概念后,回去好好看看自己写的 server 代码,是不是把 length 和 precision 的概念弄混了? 再来个例子加强理解:

f double(4, 1),

4 表示 precision,1 表示 scale,length 为4 + 1 + 1 = 6。其中 length 的算法为 precision + 小数点1位 + 符号位1位。 display width 有意义的前提是有 zerofill 标记。如果有 zerofill 标记,则自动为 unsigned,所以 display width = precision + 小数点1位, length = precision + 小数点 1 位。 总结一下:没有zerofill,length 有意义, display width 无意义;有 zerofill,length 和 display width 相等。

d decimal(6, 1),

因为 decimal 会用于金融领域,mysql 那帮孙子也谨慎起来,把 decimal 的行为实现得非常规范,所有的行为都可以解释。 6 表示 precision,1 表示 scale,length = precision + 小数点1 + 符号位1 = 8。如果后面加上 zerofill,则 length = precision + 小数点 = 7, display width = length = 7。

下面专门写一个case来验证上面对decimal的分析,同时证明 mysql 那帮人的不严肃。按道理讲,decimal 和 double 在 precision、scale、length 上的表现行为应该是一致的,但实际偏偏不是,请看:

看!除了type不同,其余都一样,但计算出来的length、填充的0的个数,居然不一样。没别的原因,mysql 的浮点类型实现得不对。

c varchar(5)

precision、scale都无意义,默认为0,length=5,display width无意义。

字符类型在这四大类中是最简单的,其次是定点数,整形和浮点数都有点bug,根本就无法“理解”

display width 仅仅在有zerofill、且为基础列的时候有意义

当 display width 有意义的时候,display width = length

length 总是有意义,它表示一个列转化成字符串时需要用多少个字节来容纳

create table语句中的数字,对不同类型的意义不同:

整形:display width

浮点:precision、scale、display width、length

定点:precision、scale、display width、length

字符:length

继续阅读