[MySQL][数据类型]详细讲解

目录


1.说明

  • MySQL表中建立属性列,列名称 类型
    • num tinyint unsigned;
    • 与C/C++语言相反:unsigned int num;
  • 如果向MySQL特定的类型中插入不合法的数据,MySQL一般都是直接拦截我们,不让我们做对应的操作
    • 反过来,如果已经有数据被成功地插入到MySQL中了,一定插入的是合法的数据
    • 所以,MySQL中,一般而言,数据类型本身也是一种约束
  • 约束:保证数据库中的数据是可预期的,完整的
    • 约束:约束使用者
    • 倒逼程序员,让程序员尽可能进行正确的插入
    • 另外,如果你不是一个很好的使用者,MySQL也能保证数据插入的合法性

1.数据类型分类


2.数值类型

1.int类型

  • 说明:
    • 在MySQL中,整形可以指定是有符号的和无符号的,默认是有符号的
    • 可以通过UNSIGNED来说明某个字段是无符号的
  • 示例:
mysql 复制代码
create table t1(num tinyint unsigned);
  • 注意:
    • 尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下
      • 与其如此,还不如设计时,将int类型提升为bigint类型
    • 但是具体使用还是要看使用场景

2.bit类型

  • 基本语法:bit[(M)]:位字段类型,M表示每个值的位数,范围从1到64,如果M被忽略,默认为1
  • 示例:
mysql 复制代码
create table t1 ( id int, a bit(8));

insert into t1 values(10, 10);

select * from tt4; #发现很怪异的现象,a的数据10没有出现
+------+------+
| id   | a    |
+------+------+
| 10   |      |
+------+------+
  • bit使用的注意事项:
  1. bit字段在显示时,是按照ASCII码对应的值显示
mysql 复制代码
insert into t1 values(65, 65);
select * from t1;
+------+------+
| id   | a    |
+------+------+
| 10   |      |
| 65   | A    |
+------+------+
  1. 如果有这样的值,只存放0/1,这是可以定义bit(1),可节省空间
mysql 复制代码
create table t2(gender bit(1));

insert into t2 values(0);
insert into t2 values(1);

insert into t2 values(2); -- 当插入2时,已经越界了
ERROR 1406 (22001): Data too long for column 'gender' at row 1

3.浮点数类型

1.float

  • 语法:float[(m, d)] [unsigned]:m指定显示长度,d指定小数位数,占用空间4个字节
  • 示例1:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入
mysql 复制代码
create table t3(id int, salary float(4,2));

insert into t3 values(100, -99.99);
insert into t3 values(101, -99.991); #多的这一点被拿掉了

select * from t3;
+------+--------+
| id   | salary |
+------+--------+
| 100  | -99.99 |
| 101  | -99.99 |
+------+--------+
  • 示例2:如果定义的是float(4,2) unsigned,因为把它指定为无符号的数,范围是 0 ~ 99.99
mysql 复制代码
create table t4(id int, salary float(4,2) unsigned);

insert into t4 values(100, -0.1);

show warnings;
+---------+------+-------------------------------------------------+
| Level   | Code | Message                                         |
+---------+------+-------------------------------------------------+
| Warning | 1264 | Out of range value for column 'salary' at row 1 |
+---------+------+-------------------------------------------------+

mysql> insert into t4 values(100, -0);
mysql> insert into t4 values(100, 99.99);

2.decimal

  • 语法:decimal(m, d) [unsigned]:定点数m指定长度,d表示小数点的位数
  • 示例:
mysql 复制代码
decimal(5,2) # 表示的范围是 -999.99 ~ 999.99
decimal(5,2) # unsigned 表示的范围 0 ~ 999.99
  • decimal和float很像,但是有区别:float和decimal表示的精度不一样
    • decimal的精度更准确,因此如果希望某个数据表示高精度,选择decimal
mysql 复制代码
create table t5 ( id int, salary float(10,8), salary2 decimal(10,8));

insert into t5 values(100, 23.12345612, 23.12345612);

mysql> select * from t5;
+------+-------------+-------------+
| id   | salary      | salary2     |
+------+-------------+-------------+
| 100  | 23.12345695 | 23.12345612 |
+------+-------------+-------------+
  • 说明:
    • float表示的精度大约是7位
    • decimal整数最大位数m为65,支持小数最大位数d是30
      • 如果d被省略,默认为0
      • 如果m被省略,默认是10
  • 建议:如果希望小数的精度高,推荐使用decimal

3.字符串类型

1.char

  • 语法:char(L) :固定长度字符串,L是可以存储的长度,单位为字符 ,最大长度值可以为255
    • 此处的字符,真的就是一个字符,而不是一个字节
  • 案例:
mysql 复制代码
mysql> create table t6(id int, name char(2));
mysql> insert into t6 values(100, 'ab');
mysql> insert into t6 values(101, '中国');

mysql> select * from tt9;
+------+--------+
| id   | name   |
+------+--------+
| 100  | ab     |
| 101  | 中国    |
+------+--------+
  • 说明 :char(2)表示可以存放两个字符,可以是字母或汉字,但是不能超过2个,最多只能是255
    • utf8中,汉字占3个字节,此处可以看出,此处字符!=字节

2.varchar

  • 语法:varchar(L):可变长度字符串,L表示字符长度,最大长度65535个字节
  • 示例:
mysql 复制代码
create table t7(id int ,name varchar(6)); #--表示这里可以存放6个字符

insert into t7 values(100, 'hello');
insert into t7 values(100, '我爱你,中国');

select * from tt10;
+------+--------------------+
| id   | name               |
+------+--------------------+
| 100  | hello              |
| 100  | 我爱你,中国        |
+------+--------------------+
  • 说明 :关于varchar(len),这个len值,和表的编码密切相关:
    • varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532
    • 当表的编码是utf8 时,varchar(n)的参数n最大值是65532/3=21844(因为utf中,一个字符占用3个字节)
    • 如果编码是gbk ,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节)
mysql 复制代码
create table tt11(name varchar(21845))charset=utf8; #--验证了utf8确实是不能超过21844
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

create table tt11(name varchar(21844)) charset=utf8;
Query OK, 0 rows affected (0.01 sec)

3.char和varchar比较

  • 如何选择定长或变长字符串?
    • 如果数据确定长度都一样,就使用定长(char)
      • 比如:身份证,手机号,md5
    • 如果数据长度有变化,就使用变长(varchar)
      • 比如:名字,地址,但是要保证最长的能存的进去
    • 定长的磁盘空间比较浪费,但是效率高。
    • 变长的磁盘空间比较节省,但是效率低
    • 定长的意义是,直接开辟好对应的空间
    • 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少

4.日期和时间类型

  • 常用的日期有如下三个:
    • date :日期 'yyyy-mm-dd',占用三字节
    • datetime :时间日期格式 'yyyy-mm-dd HH:ii:ss',表示范围从1000到 9999,占用八字节
    • timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss,格式和datetime完全一致,占用四字节
  • 示例:
mysql 复制代码
# 创建表
create table birthday (t1 date, t2 datetime, t3 timestamp);

# 插入数据:
insert into birthday(t1,t2) values('1997-7-1','2008-8-8 12:1:1'); #--插入两种时间
select * from birthday;
+------------+---------------------+-------------------+
| t1         | t2                  | t3                |
+------------+---------------------+-------------------+
| 1997-07-01 | 2008-08-08 12:01:01 | 2024-1-1 18:28:55 | #--添加数据时,时间戳自动补上当前时间
+------------+---------------------+-------------------+

# 更新数据:
update birthday set t1='2000-1-1';
select * from birthday;
+------------+---------------------+-------------------+
| t1         | t2                  | t3                |
+------------+---------------------+-------------------+
| 2000-01-01 | 2008-08-08 12:01:01 | 2024-1-2 18:32:09 | #--更新数据,时间戳会更新成当前时间
+------------+---------------------+-------------------+

5.enum和set

1.基本语法

  • enum:枚举,"单选"类型
    • 该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值
    • 出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应如下数字:1,2,3, ...最多65535 个
    • 当添加枚举值时,也可以添加对应的数字编号
mysql 复制代码
enum('选项1', '选项2', '选项3', ...);
  • set:集合,"多选"类型
    • 该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储其中任意多个值
    • 而且出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32, ... 最多64个
mysql 复制代码
set('选项值1','选项值2','选项值3', ...);
  • 说明:不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读
  • **示例:**有一个调查表votes,需要调查人的喜好, 比如(登山,游泳,篮球,武术)中去选择[可多选],(男,女)[单选]
mysql 复制代码
create table votes(
-> username varchar(30),
-> hobby set('登山', '游泳', '篮球', '武术'), #--使用数字标识每个爱好的时候,采用比特位位置来与set中的爱好对应起来
-> gender enum('男','女')); #--使用数字标识的时候,就是正常的数组下标

//插入数据
insert into votes values('雷锋', '登山,武术', '男');
insert into votes values('Juse', '登山,武术', 2);

select * from votes where gender=2;
+----------+---------------+--------+
| username | hobby         | gender |
+----------+---------------+--------+
| Juse     | 登山,武术      |女      |
+----------+---------------+--------+

2.查询数据

  • 有如下数据,想查找所有喜欢登山的人:
mysql 复制代码
+-----------+---------------+--------+
| username  | hobby         | gender |
+-----------+---------------+--------+
| 雷锋      | 登山,武术      | 男     |
| Juse      | 登山,武术      | 女     |
| LiLei     | 登山          | 男     |
| LiLei     | 篮球          | 男     |
| HanMeiMei | 游泳          | 女     |
+-----------+---------------+--------+
  • 使用如下查询语句:
    • 不能查询出所有,爱好为登山的人
mysql 复制代码
mysql> select * from votes where hobby='登山';
+----------+--------+--------+
| username | hobby  | gender |
+----------+--------+--------+
| LiLei    | 登山   | 男     |
+----------+--------+--------+
  • 集合查询使用find_ in_ set函数:find_in_set(sub, str_list):
    • 如果sub在str_list中,则返回下标
    • 如果不在,返回0
    • str_list用逗号分隔的字符串
mysql 复制代码
select find_in_set('a', 'a,b,c');
+---------------------------+
| find_in_set('a', 'a,b,c') |
+---------------------------+
| 1                         |
+---------------------------+

select find_in_set('d', 'a,b,c');
+---------------------------+
| find_in_set('d', 'a,b,c') |
+---------------------------+
| 0                         |
+---------------------------+
  • 查询爱好登山的人
mysql 复制代码
select * from votes where find_in_set('登山', hobby);
+----------+---------------+--------+
| username | hobby         | gender |
+----------+---------------+--------+
| 雷锋     | 登山,武术      | 男     |
| Juse     | 登山,武术      | 女     |
| LiLei    | 登山          | 男     |
+----------+---------------+--------+
相关推荐
一个程序员_zhangzhen6 分钟前
sqlserver新建用户并分配对视图的只读权限
数据库·sqlserver
zfj3219 分钟前
学技术学英文:代码中的锁:悲观锁和乐观锁
数据库·乐观锁··悲观锁·竞态条件
吴冰_hogan11 分钟前
MySQL InnoDB 存储引擎 Redo Log(重做日志)详解
数据库·oracle
zhou周大哥21 分钟前
linux 安装 ffmpeg 视频转换
linux·运维·服务器
nbsaas-boot27 分钟前
探索 JSON 数据在关系型数据库中的应用:MySQL 与 SQL Server 的对比
数据库·mysql·json
cmdch201728 分钟前
Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题
数据库·sql·mybatis
程序员学习随笔30 分钟前
PostgreSQL技术内幕21:SysLogger日志收集器的工作原理
数据库·postgresql
Sun_12_230 分钟前
SQL注入(SQL lnjection Base)21
网络·数据库
秦时明月之君临天下31 分钟前
PostgreSQL标识符长度限制不能超过63字节
数据库·postgresql
woshilys33 分钟前
sql server 备份恢复
数据库·sqlserver