CREATE TABLE t(
a INT UNSIGNED,
b INT UNSIGNED
)ENGINE=INNODB;
INSERT INTO t SELECT 1,2;
SELECT * FROM t;
SELECT a-b FROM t;
执行最后一条select语句的结果是
其实结果在不同的系统可能还会不一样
可以是 − 1 -1 −1,可以是一个很大的正值,也可能会报错,报错就是如上,out of range超出了范围。
原因其实是,这里 1 − 2 1-2 1−2变成十六进制的结果是 0 x F F F F F F F F 0xFFFFFFFF 0xFFFFFFFF,再转变成二进制其实是一串1, 11111111… 11111111… 11111111…,然后再将其变为十进制,如果是有符号位,那么前面的1代表是负数,然后取反加1,结果就是-1,如果前面没有符号位,那就表示一个很大的正数。
ZEROFILL
ZEROFILL像是一个长度属性,关系到的是数字类型后面的长度值,比如int(10),通常像这种类型后面添加的参数不是代表字符个数就是字节个数,那么整形应该已经是限定死是4个字节的,那这里的10代表什么?其实如果没有ZEROFILL这个属性,这里的10没有任何意义。
现在我们对上面创建的表进行修改,修改成int(4)和加上zerofill属性
ALTER TABLE t CHANGE COLUMN a a INT(4) UNSIGNED ZEROFILL;
//再进行查询
SELECT * FROM t;
ZEROFILL的效果其实就是如果宽度小于设定的宽度,则会进行自动填充0,要注意的是,这里只是最后显示的结果,在Mysql中实际存储的还是1,可以使用hex函数来证明
可以看到HEX(a)为1而不是0001,所以里面储存的还是1,而不是0001,其实也可以设想一下,如果数据库内部存储的是0001这样的字符串,又怎么进行整形的加减乘除呢?
SQL_MODE模式的设置
SQL_MODE是比较容易让人忽略的一个常量,默认为空,SQL_MODE的设置其实是一种比较冒险的设置,因为在这种设置下,可以允许一些非法操作,比如可以将NULL插入到非NULL的字段中,甚至可以插入一些非法日期,比如 “2012-12-32”,因此最好将这个值设为严格模式。
对于SQL_MODE的设置,可以在Mysql的配置文件如my.cnf和my.ini中进行,也可以在客户端的工具中进行,并且可以分别进行全局的设置或者当前会话的设置。下面的语句可以用来查看当前SQL_MODE的设置情况。
//查看全局
SELECT @@global.sql_mode;
//查看当前会话
SELECT @@session.sql_mode;
日期和时间类型
Mysql数据中总共有5种于日期和时间有关的数据类型
| 类型 | 所占空间 |
| — | — |
| DATETIME | 8个字节 |
| TIMESTAMP | 4个字节 |
| DATE | 3个字节 |
| TIME | 3个字节 |
| YEAR | 1个字节 |
DATITIME和DATE
DATETIME是占用空间最多的一种类型,占用了8个字节,可以显示日期同时也可以显示时间,其可以表达的范围为1000-01-01 00:00:00到9999-12-31 23:59:59。而DATE只可以表示日期,不可以显示时间,其可以表达的范围为1000-01-01到9999-12-31。
在mysql数据库中,对日期和输入格式的要求是十分宽松的,以下的输入都可以视为日期类型
2011-01-01 00:01:00
2011/01/01 00+01+10
20110101000110
11/01/01 00@01@10
其中,最后一种类型的年上面的11是表示离当前时间最近的年份。
SELECT CAST(‘11/01/01 00@01/10’ AS DATE