MySQL -数据类型
博客主页:【夜泉_ly】
本文专栏:【暂无】
欢迎点赞👍收藏⭐关注❤️
目录
- 前言
- 数值类型
- int
- bit
- float
- 字符串
- char
- varchar
- enum set
- 日期和时间类型
前言
在之前的操作篇,
我们用到的大多是DDL(数据定义语言)。
在建表时,有列属性的名称,也有类型。
MySQL 支持多种类别的SQL数据类型:
数值类型、日期和时间类型、字符串(字符和字节)类型、空间类型以及 JSON数据类型。
具体的、权威的信息建议查官方文档,
点上面那个蓝色的字体就行。
本篇主要讲最常见的数据类型。
数值类型
位、整数、浮点数都叫数值类型。
int
其中,带 int 的都叫整数类型。
类型都可以加 un 前缀,代表无符号。
类型 | 存储(字节) | 最小值(有符号) | 最小值(无符号) | 最大值(有符号) | 最大值(无符号) |
---|---|---|---|---|---|
TINYINT | 1 | -128 | 0 | 127 | 255 |
SMALLINT | 2 | -32768 | 0 | 32767 | 65535 |
MEDIUMINT | 3 | -8388608 | 0 | 8388607 | 16777215 |
INT | 4 | -2147483648 | 0 | 2147483647 | 4294967295 |
BIGINT | 8 | -2^63 | 0 | 2^63-1 | 2^64-1 |
表格来自手册
需注意的是,
在C/C++中,越界的数据会被截断。
但MySQL中,它不会让你插入越界的数据。
如果我们向MySQL特定的类型插入不合法的数据,
MySQL一般都是直接拦截我们,不让我们做对应的操作。
这点一定要和其他语言做区分,
MySQL不能截断数据,
一但截断,不能区分哪些是有效的,哪些是被截过的。
反过来,如果我们已经有数据被成功插入到MySQL中了,
那么插入的数据一定是合法的。
所以在MySQL中,一般而言,
数据类型本身就是一种 约束。
这种约束,让程序员尽可能的进行正确的插入,
保证了数据库中的数据是完整、可预期的。
至于用不用unsigned,看场景,
比如年龄,就可以用unsigned。
而用什么类型,也取决于场景,
还是年龄,如果你无脑选最大的(比如bigint),
那数据一多,空间浪费就多。
下面看看操作。
create database test_db;
use test_db;
create table if not exists t1(
num tinyint
);
desc t1;
show create table t1 \G
建立属性列时,名称在前,类型在后
insert into t1 values (-128);
insert into t1 values (127);
insert into t1 values (0);
insert into t1 values (128);
insert into t1 values (-129);
MySQL不会让你插入越界的数据
create table if not exists t2(
num tinyint unsigned
);
insert into t1 values (0);
insert into t1 values (255);
insert into t1 values (-1);
insert into t1 values (256);
无符号的
bit
create table if not exists t3(
id int,
online bit
);
desc t3;
show create table t3 \G
创建时,不显示指定长度,默认是一位
insert into t3 values (123, 0);
insert into t3 values (124, 1);
insert into t3 values (125, 2);
insert into t3 values (125, -1);
也有约束
select * from t3;
有些版本的MySQL直接select不会显示0x00、0x01,可指定使用十六进制hex(…)
alter table t3 modify online bit(64);
alter table t3 modify online bit(65);
bit最多设置64位
float
float/double 都可以用来存小数,
与C/C++相同,这个数也是近似值。
并且,在手册的描述中到处都是弃用弃用,
这个语法将被弃用、那个语法将被弃用。
(不过我英语不好,不确定读懂没有,
你们可以自行去手册确认。)
稍微总结了一下我们需要注意的点:
- 不再使用 FLOAT(M, D) 或 DOUBLE(M, D),
直接使用 FLOAT 或 DOUBLE - 不再使用 UNSIGNED ,
建议使用 CHECK 约束来确保非负数值。 - 对于需要精确小数计算的情况,
推荐使用 DECIMAL 类型。
不过我们还是简单过一下操作:
create table if not exists t4(
salary float(4, 2)
);
desc t4;
show create table t4 \G
(4,2):位数不超过4的情况下,小数点后有2位
insert into t4 values (99.99);
insert into t4 values (-99.99);
insert into t4 values (100.0);
insert into t4 values (0.999);
insert into t4 values (99.999);
select * from t4;
- 位数不能超
- 精度多了会四舍五入
- 四舍五入的结果,必须在合法范围内
- 如果是unsigned,会把负数部分ban掉,正数部分同有符号的。
- 默认的float可以存很大的数,我的是3e38左右
再看看精度问题:
create table if not exists t5(
f1 float(9, 8),
f2 decimal(9, 8)
);
insert into t5 values (1.11111111, 1.111111111);
insert into t5 values (1.23456789, 1.23456789);
select * from t5;
对于需要精确小数计算的情况,推荐使用 DECIMAL 类型。
字符串
The string data types are CHAR, VARCHAR, BINARY, VARBINARY, BLOB, TEXT, ENUM, and SET.
char
char 可以存固定长度的字符串,
这个字符,就是一个符号
和存储的大小无关。
比如 a 是一个字符,啊 也是一个字符,
如果你用的字符编码集是utf8mb4
那么😊也是一个字符。
可以简单验证:
create table if not exists test_char(
name char(1)
);
show create table test_char \G
insert into test_char values ('a');
insert into test_char values ('啊');
insert into test_char values ('😊');
select * from test_char;
顺带一提,这一段我是在vscode上操作的,
因为我不知道怎么把 😂 弄到 XShell 上。
alter table test_char modify name char(255);
alter table test_char modify name char(256);
char 最多255个字符
varchar
varchar 表示可变长度字符串
这个可变长度,
指的是实际存储所占空间的长度。
举个例子:
假设你有一个 varchar(1000) 字段,并存储字符串 ‘a’:
如果字符集是 utf8,‘a’ 占用 1 字节。
另外,记录字符串的长度也需要 1 字节。
因此,存储 ‘a’ 的总空间是:1 字节(字符) + 1 字节(长度前缀) = 2 字节。
varchar总共可以存65535个字节,
而字符长度,取决于编码。
具体来说,varchar需要用1~3字节存字符长度,
因此字符串最多用65532字节,
最大长度 = (65535-3) / 单个字符所占字节数。
create table if not exists t6(
name varchar(2)
);
insert into t6 values ('aa');
insert into t6 values ('aaa');
alter table t6 modify name varchar(16383);
alter table t6 modify name varchar(16384);
我的是utf8mb4,一个字符4字节,所以长度<=(65535-3)/4=16383
- 注1:一行的大小也有上限,
所以如果除了varchar还有其他字段,
varchar的上限只会变得更小。 - 注2:虽然上面我们一直在测边界,
但实际中,如果你的数据已经接近边界了,
那你还是换一个数据类型来存吧。
(比如上图就建议 use blog or text instead)
enum set
enum 单选,set 多选。
create table if not exists t7(
id int unsigned,
gender enum('男', '女', '其他'),
hobby set('代码', '吃饭', '睡觉')
);
insert into t7 values(1, '男', '代码');
insert into t7 values(2, '女', '代码, 睡觉');
insert into t7 values(2, '女', '代码,睡觉');
insert into t7 values(3, 3, 3);
insert into t7 values(4, 1, 7);
select * from t7;
注:
- enum 可以插入下标,从1开始。
- set 可以插入数字,用比特位代表对应选项。
- set 插入多个值时,用逗号分割(请不要顺手打个空格)。
日期和时间类型
首先我们得知道,
日期,通常代表年月日
时间,通常代表时分秒
日期时间,就是年月日时分秒
常用类型有三个:
date:表示日期(年-月-日)。
datetime:表示日期和时间(年-月-日 时:分:秒)。
timestamp:自动存储当前时间戳,在数据插入时自动更新(需设置)。
关于自动更新,
我们可以简单测试:
create table test_time( t1 datetime, t2 timestamp, t3 datetime default current_timestamp, t4 timestamp default current_timestamp, t5 datetime on update current_timestamp, t6 timestamp onupdate current_timestamp, t7 datetime default current_timestamp on update current_timestamp, t8 timestamp default current_timestamp on update current_timestamp );
show create table test_time \G
insert into test_time values ();
select * from test_time;
update test_time set t1 = '1-1-1 1:1:1', t2 = '2000-1-1 1:1:1' where t1 is null;
select * from test_time;
希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!