MySql 入门学习笔记(一) MySQL 数据类型

MySql 语句注意事项

命令结束符号

在写完一个命令之后需要以下边几个符号之一结尾:

  • ;
  • \g
  • \G

命令可以随意换行

并不是按了回车键就提交命令了,只要按回车键的时候输入与语句里没有上述的结束符号,该语句就算是没有结束.

可以一次提交多个命令

我们可以在一条语句里面写多个命令.中间用结束符分隔开.只要没有按回车键,就是不会提交命令.

使用“\c”放弃本次操作

如果想放弃本次编写的命令,可以在输入的命令后边加上\c.

大小写问题

MySql 默认对命令的大小写并没有限制.
但是按照习惯,命令、函数什么的都是要大写的.其他的一些名称类等,例如数据库名、表名、列名都是需要小写的.

字符串的表示

在命令里有时会用到字符串,我们可以使用单引号或者双引号把字符串内容包含上.例如:

SELECT 'aaa'

如果上述的“aaa”没有加上引号,那么该语句执行时,它会被当作列名.

注意:在ANSI_QUOTES下,双引号有特殊的用途,所以最好的情况是用单引号来表示字符串

数据类型

数值类型

整数类型

字节数越多,能表示的数值范围越大,但同时也会耗费更大的存储空间.根据表示一个数占用的字节数的不同,MySql 把证书划分成如下类型:

类型

占用的空间(字节)

无符号数取值范围

有符号数取值范围

含义

TINYINT

1

0~28-1

-27~ 27-1

非常小的整数

SMALLINT

2

0~216 -1

-215~ 215-1

小的整数

MEDIUMINT

3

0~224-1

-223~ 223-1

中等大小的整数

INT(INTEGER)

4

0~232-1

-233~ 233-1

标准的整数

BIGINT

8

0~264-1

-263~ 263-1

大整数

例如,在 TINYINT 中,占用一个字节,表示有符号数的话,既可以表示正数也可以表示负数.需要一个比特位表示正负号.但是如果表示无符号数的话,就不需要表示正负号了.
这也就是为啥有符号数和无符号数表示的范围不同取值范围的原因.

浮点数类型

浮点数是用来表示小数的,我们平时用的十进制小数也可以转换成二进制后被计算机存储.

同样的当一浮点数使用的字节数越多,表示的范围也就越多.

类型

占用的空间(字节)

绝对值最小非 0 值

绝对值最大非 0 值

含义

FLOAT

4

±1.175494351E-38

±3.402823466E+38

单精度浮点数

DOUBLE

8

±2.2250738585072014E-308

±1.7976931348623157E+308

双精度浮点数

有一点需要注意的是,虽然有的十进制小数,比如 1.68 可以很容易的被转换成二进制,但是更多的小数是无法直接转换成二进制的,比如 0.3,它转换成的二进制小数是一个无限的小数.
但是我们只能用四个字节 或者八个字节表示这个小数,所以只能进行一些舍入来近似的表示,所以我们说计算机的浮点数表示有时是不精确的.

设置最大位数和小数位数

定义浮点数类型是,可以在 FLOAT 或者 DOUBLE 后面跟上两个参数

FLOAT(M,D)
DOUBLE(M,D)
  • 其中,M 表示该小数最多需要的十进制有效数字个数
  • D 表示该小数的小数点后的十进制数字个数

在 D 相同的情况下,M 越大,该类型的取值范围越大;在 M 相同的情况下,D 越大,该类型的取值范围越小.
M 的取值范围是 1~255,D 的取值范围是 0~30.而且,D 必须不大于 M

定点数类型

上面提到,浮点数类型可能存在舍入的情况,这会导致我们的数值不够精确.所以 MySql 提供了一个定点数的数据类型,他也是存储小数的一种方式:

类型

占用的空间(字节)

取值范围

DECIMAL(M,D)

取决于 M 和 D

取决于 M 和 D

此处的 M 和 D 的作用和我们上面描述的一样.
在 FLOAT 和 DOUBLE 中,占用的字节数一直都是四字节或者八字节,他们占用的存储空间大小并不随着 M 和 D 的值变动而变动.
与之不同的是在 DECIMAL 中,存储空间大小会随着 M、D 的变化而变动.

无符号数值类型表示

对于数值类型,例如整数、浮点数和定点数,有些情况下我们只需要用到无符号数.MySql 提供了一个表示无符号数值类型的方式,就是在原数值类型后加一个单词UNSIGNED

  • 在使用存储空间固定的情况下,无符号整数可以将表示的正数范围相较于有符号整数扩大一倍.
  • 受浮点数和定点数具体的存储格式影响,无符号数和定点数并不能提升正数的表示范围

日期和时间类型

MySql 提供了多种关于日期和时间的类型,各种类型表示的范围如下:

类型

存储空间

取值范围

含义

YEAR

1 字节

1901~2155

年份值

DATE

3 字节

1000-01-01~9999-12-31

日期值

TIME

3 字节

-838:59:59~838:59:59

时间值

DATETIME

8 字节

1000-01-01 00:00:00~9999-12-31 23:59:59

时间加日期值

TIMESTAMP

4 字节

1970-01-01 00:00:01 ~2038-01-19 03:14:07

时间戳

在 MySql5.6.4 这个版本之后,Time、DATETIME、TIMESTAMP 这几种类型添加了对毫秒、微秒的支持.由于毫秒、微秒都不到 1 秒,所以也被称为小数秒,MySql 最多支持 6 位小数秒的精度.

如果想让 TIME、DATETIME、TIMESTAMP 支持小数秒,可以这样写:

类型(小数秒位数)
//小数秒位数可以在0、1、2、3、4、5、6之中选择

例如 DATETIME(0)表示精确到秒,DATETIME(3)表示精确到毫秒,DATETIME(5)表示精确到 10 微秒.

  • 如果选择了支持小数秒,那么对应的存储空间也会相应的扩大,保留不同的小数秒位数,增加的存储空间大小也不同.

保留小数秒位数

额外需要的存储空间

0

0 字节

1 或 2

1 字节

3 或 4

2 字节

5 或 6

3 字节

按照上面的标注,当我们使用 DATETIME(1)时,需要的存储空间应该是8+1=9字节.
但是在 MySQL5.6.4 之后的版本,各个类型存储空间和取值范围如下

类型

存储空间

取值范围

含义

YEAR

1 字节

1901~2155

年份值

DATE

3 字节

1000-01-01~9999-12-31

日期值

TIME

3 字节+小数秒的存储空间

-838:59:59[000000]~838:59:59[000000]

时间值

DATETIME

5 字节+小数秒存储空间

1000-01-01 00:00:00[000000]~9999-12-31 23:59:59[000000]

时间加日期值

TIMESTAMP

4 字节+小数秒存储空间

1970-01-01 00:00:01[000000] ~2038-01-19 03:14:07[0000000]

时间戳

与之前的之前的存储空间不同的是,在 MySQL5.6.4 版本之后 DATETIME 类型的占用空间从原来的 8 字节变为了 5 字节.这是 MySQL 后面做的优化

YEAR

YEAR 类型也可以写为YEAR(4),它单纯表示一个年份值,取值范围为 1901~2155,仅占用一个字节大小.因为存储的空间有限,如果想表示更大范围的年份值,可以不使用 MySQL 自带的 YEAR 类型.用 SMALLINT 替代.或者字符串类型.

DATE、TIME 和 DATETIME
  • DATE 表示日期,格式是 YYYY-MM-DD
  • TIME 表示时间,格式是 hh:mm:ss[.uuuuuu]或者 hhh:mm:ss[.uuuuuu]
  • DATETIME 表示日期+时间,格式是 YYYY-MM-DD hh:mm:ss[.uuuuuu]

需要注意的是,DATETIME 中的时间部分表示的是一天之内的时间,而TIME 表示的是一段时间,而且可以表示负值

TIMESTAMP

1970-01-01 00:00:00 是一个初始特殊时刻,我们把某刻距离 1970-01-01 00:00:00 的秒数称为时间戳.例如当前时间是 2018-01-24 11:39:21,距离 1970-01-01 00:00:00 的秒数为 1516765161.那么当前的时间戳就为 1516765161.
在 MySQL5.6.4 之后,时间戳的值可以加入小秒数.

  • 时间戳的一个好处就是,它展示的值是可以随着时区的变化而变化的.

字符串类型

字符和字符串

字符可以大致分为两种,一种叫可见字符,一种叫不可见字符.

  • 可见字符就是我们能看到的字符,例如’b’,‘s’,','等,这样我们能看到的单个文字、标点符号、图形符号、字母、数字等就是可见字符
  • 不可见字符就是我们看不到的字符,例如换行、空格、制表符等.
  • 字符串顾名思义,就是字符串连起来的样子.

字符编码简介

先简单介绍一下字符和字节的区别.

  • 字符是面向人的概念
  • 字节是面向计算机的概念.

所以,如果想在计算机中表示字符,需要将字符与特定的字节序列对应起来,这个映射过程称之为编码.
编码不是唯一的,不同的人制作了不同的编码方案,根据表示一个字符使用的字节数量是不是固定的,编码方案分为以下两种:

  • 固定长度的编码方案
    表示不同的字符所需要的字节数量是相同的.例如 ASCII 编码方案采用一个字节来编码一个字符,ucs2 采用两个字节来编码一个字符.
  • 变长的编码方案
    表示不同的字符所需要的字节数量是不同的.例如 utf8 编码采用 1~ 3 个字节来编码一个字符.根本 312 采用 1~2 个字节来编码一个字符.

在 MySQL 中,没有对编码方案和字符集这两个概念做区分.

MySQL 的字符串类型

下面看一下 MySQL 中提供的各种字符串类型(M 表示该类型数据最多能存储的字符数量,L 表示我们实际想该类型的属性中存储的字符串在特定字符集下所占的字节数,W 表示在该特定字符集下,编码一个字符最多需要的字节数)

类型

最大长度

存储空间要求

含义

CHAR(M)

M 个字符

M*W 个字节

固定长度的字符串

VARCHAR(M)

M 个字符

L+1 或者 L+2 个字节

可变长度的字符串

TINYTEXT

28-1 个字节

L+1 个字节

非常小型的字符串

TEXT

224-1 个字节

L+3 个字节

小型字符串

MEDIUMTEXT

224-1 个字节

L+3 个字节

中等大小的字符串

LONGTEXT

232-1 个字节

L+4 个字节

大型的字符串

CHAR(M)
  • CHAR(M)中的 M 代表的是该类型最多可以存储多少个字符.
  • 上面指的是字符数量,不是字节数量.
  • M 的取值范围是 0~255.默认值为 1
  • CHAR(0)表示只能存储空字符串‘’,或者NULL

再强调一遍,在不同的字符集下,需要的存储空间是不一样的.例如一个字符集编码一个字符最多需要 W 个字节,那么类型 CHAR(M)占用的存储空间大小就是 M*W 个字节.
如果我们手机存储的字符串在特定的字符集编码下占用的字节数不足 M*W,那么剩下的空间会用空格字符补满

VARCHAR(M)

上面提到,当我们使用 CHAR(M)时,如果字符串长短不一,就会造成存储空间的浪费.
为了解决空间浪费问题我们可以使用 VARCHAR(M).

  • VARCHAR(M)中的 M 代表该类型最多可以存储的字符数量.
  • M 的取值范围理论上时 1~65535,但是 MySQL 中规定,所有列的存储数据大小不得超过 65565 个字节.所以,理论上 M 的取值时小于 65535 的.

字符串占用的存储空间:

♣ 真正的字符串内容:假设真正的字符串占用的字节数为 L
♣ 占用的字节数:

  • 当 VARCHAR(M)类型采用的一个字符集编码一个字符最多需要 W 个字节,那么 W*M<256 时,需要 1 个字节来表示占用的字节数
  • 当 65535>M*W>=356 时,需要两个字节来表示占用的字节数.
    ♣ VARCHAR(M) 实际占用的存储空间为L+占用的字节数(1 或 2)
    假如类型为 VARCHAR(5),在字符集 utf8 下,MW=53<256,占用字节数表示位为 1
    当类型为 VARCHAR(100)时,在字符集 utf8 下,MW=1003>256,这时占用字节数表示位为 2

在上面两种情况中,存储同一个字符串,所需的存储空间是不一样的,分为别 L+1 和 L+2

这也就是为什么说 VARCHAR(M)是一个可变长度的字符串类型.

各种 TEXT 类型

当一个字符串足够长时,VARCHAR(M)类型不能满足存储需要,我们需要一个更大的存储类型来存储.
这就是 TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT.它们都是变长类型,与 VARCHAR(M)相同,占用的存储空间有实际内容+占用的字节长度表示位两部分组成.

  • TINYTEXT 最多可以存储 28-1 个字节,所以内容占用的字节长度用 1 个字节表示
  • TEXT 最多可以存储 216-1 个字节,所以占用长度的字节长度用 2 个字节表示
  • MEDIUMTEXT 最多可以存储 224-1 个字节,所以占用长度的字节长度用 3 个字节表示
  • LONGTEXT 最多可以存储 232-1 个字节,所以内容占用的字节长度用 4 个字节表示

之前提到过,MySQL 规定列存储的数据大小总和不超过 65535 个字节,但是这个规定,对 TEXT 类型是不起作用的.

ENUM 类型和 SET 类型

当某一列中之能存储固定的信息,比如“男”、“女”.如果存入别的字符串会出问题,这时候需要一个 ENUM 类型,也就是枚举类型:

ENUM('str1','str2','str3'···)

他表示在给定的字符串列表中选一个.那么上面的例子,我们可以定义为 ENUM(‘男’,‘女’)

但是,又衍生一个问题.假如我们需要从列表里面选择多个,ENUM 就不能满足要求了,我们可以使用 SET,格式如下:

SET('str1','str2','str3'···)

它表示可以在给定的字符串列表里面选择多个.

以上,ENUM 和 SET 类型都是一种特殊的字符串类型,可以满足从字符串列表里单选或者多选元素的需求.

二进制类型

BIT 类型

当我们存储耽搁或者多个比特位的需求,我们需要用的 BIT 类型

类型

字节数

含义

BIT(M)

近似为(M+7)/8

存储 M 个比特位的值

其中 M 的取值范围为 1~64,而且 M 可以省略,默认为 1.

注意,MySQL 中是以字节为单位存储数据的,一个字节拥有 8 个 bit,当我们想存储的 BIT 数量不足 8 个时,MySQL 会自动填满.

BINARY(M) 与 VARBINARY(M)

BINARY(M) 与 VARBINARY(M) 对应之前提到的 CHAR(M)和 VARCHAR(M),前者是固定长度,后者是可变长度.
与 CHAR 不同的是 BINARY(M)和 VARBINARY(M)是用来存储字节的.M 代表最多存放的字节数量

其他的二进制类型

TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB 是针对数据量很大的二进制数据提出的,比如图片、音频、压缩文件啥的。它们很像 TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT,不过各种 BLOB 类型是用来存储字节的,而各种 TEXT 类型是用来存储字符的而已

注意:对于比较大的二进制数据,比如图片、音频、压缩文件什么的,通常情况下都不会存储在数据库中,而是将其存储在文件管理系统中,然后数据库中保存对应的路径