day037MYSQL库、表、行详细操作

本节内容:

1、库操作
2、表操作
3、行操作

一、库操作

1、创建数据库

1.1 语法

CREATE DATABASE 数据库名 charset utf8;

1.2 数据库命名规则

可以由字母、数字、下划线、@、#、$

区分大小写

唯一性

不能使用关键字如 create select

不能单独使用数字

最长128位

# 基本上跟python或者js的命名规则一样

2、数据库相关操作

也是一些基本操作,和我们之前说的差不多。
1 查看数据库
show databases;   # 显示data目录下的所有数据库
show create database db1;
select database();

2 选择数据库(切换数据库)
USE 数据库名

3 删除数据库
DROP DATABASE 数据库名;

4 修改数据库
alter database db1 charset utf8;

5、如何返回data目录下,

Mysql

关于库的内容,有点少是吧,不是咱们的重点,来看下面的表操作~~~

二、表操作

1、存储引擎(即表类型)

mysql根据不同的表类型会有不同的处理机制,

1、存储引擎解释

首先确定一点,存储引擎的概念是MySQL里面才有的,不是所有的关系型数据库都有存储引擎这个概念,
后面我们还会说,但是现在要确定这一点。

因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型
(即:对表的存储、操作等的实现方法不同),表是什么,表本质上就是磁盘上的文件。

  其实MySQL支持多种存储引擎,每种引擎有着一些自己独特的功能,用户在使用的时候,
可以根据自己的业务场景来使用不同的存储引擎,其中MySQL最常用的存储引擎为:MyISAM和InnoDB。
在详细介绍这些存储引擎之前,我们先来看看MySQL的整个工作流程,看一下存储引擎在哪里,MySQL都做了哪些事情。

简单的比喻
在讲清楚什么是存储引擎之前,我们先来个比喻,我们都知道录制一个视频文件,可以转换成不同的格式,
例如mp4,avi,wmv等,而存在我们电脑的磁盘上也会存在于不同类型的文件系统中如windows里常见的ntfs、fat32,
存在于linux里常见的ext3,ext4,xfs,但是,给我们或者用户看懂实际视频内容都是一样的。
直观区别是,占用系统的空间大小与清晰程度可能不一样。

那么数据库表里的数据存储在数据库里及磁盘上和上述的视频格式及存储磁盘文件的系统格式特征类似,也有很多种存储方式。
但是对于用户和应用程序来说同样一张表的数据,无论用什么引擎来存储,用户能够看到的数据是一样的。
不同储引擎存取,引擎功能,占用空间大小,读取性能等可能有区别。

说白了,存储引擎就是在如何存储数据、提取数据、更新数据等技术方法的实现上,底层的实现方式不同,
那么就会呈现出不同存储引擎有着一些自己独有的特点和功能,对应着不同的存取机制。
Python

看下图:这是我在MySQL官方手册上拿下来的(手册你如果能够玩好,将来你就能做一个NB的DBA~~~)

来,看每个部分的解释,看下图:

2、MySQL存储引擎分类

前面我们对MySQL进行操作的时候并没有指定存储引擎,为什么还能用呢,没有指定还能用,说明什么,
说明MySQL默认有一个存储引擎,
我记得MySQL5.5之前,默认的存储引擎是MyISAM,之后都改为InnoDB了,
我们的重点就是这个InnoDB,也是公司中最常用的、最好用的引擎,
但是还是一些公司在用MyISAM引擎,
除了历史原因之外,还有MyISAM的效率比InnoDB高一点,
InnoDB在这方面做了很多优化,效率已经和MyISAM差不多了,
但是InnoDB引擎还有好多其他的NB的功能,
下面我们就介绍几种存储引擎。

首先看一下咱们的默认存储引擎:

查看引擎的几种方法

1、show engines;#查看MySQL所有的引擎,
2、show variables like "storage_engine%";查看当前正在使用的引擎
 注意:在存储大文件的时候,可以存到数据库,但是尽量别直接存到数据库里面,会影响数据库的效率,
 我们就存文件的路径、地址,用户想要这个大文件,我们可以到对应的路径下取读取这个文件给用户。

3、几种常用引擎介绍

1、MyISAM引擎
MyISAM引擎特点
MyISAM引擎特点:
 1.不支持事务
     事务是指逻辑上的一组操作,组成这组操作的各个单元,要么全成功要么全失败。
 2.表级锁定
     数据更新时锁定整个表:其锁定机制是表级锁定,也就是对表中的一个数据进行操作都会将这个表锁定,
     其他人不能操作这个表,这虽然可以让锁定的实现成本很小但是也同时大大降低了其并发性能。
  3.读写互相阻塞
       不仅会在写入的时候阻塞读取,MyISAM还会再读取的时候阻塞写入,但读本身并不会阻塞另外的读。
  4.只会缓存索引
     MyISAM可以通过key_buffer_size的值来提高缓存索引,以大大提高访问性能减少磁盘IO,
     但是这个缓存区只会缓存索引,而不会缓存数据。

  5.读取速度较快
        占用资源相对较少
  6.不支持外键约束,但只是全文索引

  7.MyISAM引擎是MySQL5.5版本之前的默认引擎,是对最初的ISAM引擎优化的产物。
Python
MyISAM引擎适用的生产业务场景
MyISAM引擎适用的生产业务场景
 1.不需要事务支持的业务(例如转账就不行,充值也不行)

 2.一般为读数据比较多的应用,读写都频繁场景不适合,读多或者写多的都适合。

 3.读写并发访问都相对较低的业务(纯读纯写高并发也可以)(锁定机制问题)

 4.数据修改相对较少的业务(阻塞问题)

 5.以读为主的业务,例如:www.blog,图片信息数据库,用户数据库,商品库等业务

 6.对数据一致性要求不是很高的业务。

 7.中小型的网站部分业务会用。

  小结:
  单一对数据库的操作都可以示用MyISAM,所谓单一就是尽量纯读,或纯写(insert,update,delete)等。
Python
MyISAM引擎调优精要
MyISAM引擎调优精要
1.设置合适的索引(缓存机制)(where、join后面的列建立索引,重复值比较少的建索引等)

2.调整读写优先级,根据实际需求确保重要操作更优先执行,读写的时候可以通过参数设置优先级。

3.启用延迟插入改善大批量写入性能(降低写入频率,尽可能多条数据一次性写入)。

4.尽量顺序操作让insert数据都写入到尾部,较少阻塞。

5.分解大的操作,降低单个操作的阻塞时间,就像操作系统控制cpu分片一样。

6.降低并发数(减少对MySQL访问),某些高并发场景通过应用进行排队队列机制Q队列。

7.对于相对静态(更改不频繁)的数据库数据,充分利用Query Cache(可以通过配置文件配置)或memcached缓存服务可以极大的提高访问频率。

8.MyISAM的Count只有在全表扫描的时候特别高效,带有其他条件的count都需要进行实际的数据访问。

9.可以把主从同步的主库使用innodb,从库使用MyISAM引擎。主库写,从库读可以(不推荐,有些麻烦的地方,市场上有人这么用)。
Python
关于MyISAM的一些其他介绍
不支持事务、表锁设计、支持全文索引,主要面向一些 OLAP 数 据库应用,
在 MySQL 5.5.8 版本之前是默认的存储引擎(除 Windows 版本外)。

数据库系统 与文件系统一个很大的不同在于对事务的支持,MyISAM 存储引擎是不支持事务的。
究其根 本,这也并不难理解。用户在所有的应用中是否都需要事务呢?在数据仓库中,
如果没有 ETL 这些操作,只是简单地通过报表查询还需要事务的支持吗?
此外,MyISAM 存储引擎的 另一个与众不同的地方是,
它的缓冲池只缓存(cache)索引文件,而不缓存数据文件,这与 大多数的数据库都不相同。
Python
2.InnoDB引擎
InnoDB引擎特点
InnoDB引擎
 介绍:InnoDB引擎是MySQL数据库的另一个重要的存储引擎,
 正称为目前MySQL AB所发行新版的标准,被包含在所有二进制安装包里。
 和其他的存储引擎相比,InnoDB引擎的优点是支持兼容ACID的事务(类似于PostGreSQL),
 以及参数完整性(即对外键的支持)。Oracle公司与2005年10月收购了Innobase。Innobase采用双认证授权。
 它使用GNU发行,也允许其他想将InnoDB结合到商业软件的团体获得授权。

InnoDB引擎特点:
    1.支持事务:支持4个事务隔离界别,支持多版本读。

    2.行级锁定(更新时一般是锁定当前行):通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响。

    3.读写阻塞与事务隔离级别相关(有多个级别,这就不介绍啦~)。

    4.具体非常高效的缓存特性:能缓存索引,也能缓存数据。

    5.整个表和主键与Cluster方式存储,组成一颗平衡树。(了解)

    6.所有SecondaryIndex都会保存主键信息。(了解)

    7.支持分区,表空间,类似oracle数据库。

    8.支持外键约束,不支持全文索引(5.5之前),以后的都支持了。

    9.和MyISAM引擎比较,InnoDB对硬件资源要求还是比较高的。

小结:
三个重要功能:Supports transactions,
              row-level locking,
              and foreign keys
Python
InnoDB引擎适用的生产业务场景
InnoDB引擎适用的生产业务场景
    1.需要事务支持(具有较好的事务特性,例银行业务)

    2.行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引完成。

    3.数据更新较为频繁的场景,如:BBS(论坛)、SNS(社交平台)、微博等

    4.数据一致性要求较高的业务,例如:充值转账,银行卡转账。

    5.硬件设备内存较大,可以利用InnoDB较好的缓存能力来提高内存利用率,
    尽可能减少磁盘IO,可以通过一些参数来设置,这个就不细讲啦~~~

    6.相比MyISAM引擎,Innodb引擎更消耗资源,速度没有MyISAM引擎快
Python
InnoDB引擎调优精要
InnoDB引擎调优精要
1.主键尽可能小,避免给Secondery index带来过大的空间负担。

2.避免全表扫描,因为会使用表锁。

3.尽可能缓存所有的索引和数据,提高响应速度,较少磁盘IO消耗。

4.在大批量小插入的时候,尽量自己控制事务而不要使用autocommit自动提交,有开关可以控制提交方式。

5合理设置innodb_flush_log_at_trx_commit参数值,不要过度追求安全性。
如果innodb_flush_log_at_trx_commit的值为0,log buffer每秒就会被刷写日志文件到磁盘,提交事务的时候不做任何操作。

6.避免主键更新,因为这会带来大量的数据移动。

可以看一看InnoDB的重要参数学习一下。

Python
关于InnoDB的一些其他介绍
InnoDB 存储引擎将数据放在一个逻辑的表空间中,这个表空间就像黑盒一样由 InnoDB 存储引擎自身来管理。
从 MySQL 4.1(包括 4.1)版本开始,可以将每个 InnoDB 存储引擎的 表单独存放到一个独立的 ibd 文件中。
此外,InnoDB 存储引擎支持将裸设备(row disk)用 于建立其表空间。

InnoDB 通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了 SQL 标准 的 4 种隔离级别,默认为 REPEATABLE 级别,
同时使用一种称为 netx-key locking 的策略来 避免幻读(phantom)现象的产生。
除此之外,InnoDB 存储引擎还提供了插入缓冲(insert buffer)、二次写(double write)、
自适应哈希索引(adaptive hash index)、预读(read ahead) 等高性能和高可用的功能。

对于表中数据的存储,InnoDB 存储引擎采用了聚集(clustered)的方式,每张表都是按 主键的顺序进行存储的,
如果没有显式地在表定义时指定主键,InnoDB 存储引擎会为每一 行生成一个 6 字节的 ROWID,并以此作为主键。

InnoDB 存储引擎是 MySQL 数据库最为常用的一种引擎,Facebook、Google、Yahoo 等 公司的成功应用
已经证明了 InnoDB 存储引擎具备高可用性、高性能以及高可扩展性。
对其 底层实现的掌握和理解也需要时间和技术的积累。
如果想深入了解 InnoDB 存储引擎的工作 原理、实现和应用,可以参考《MySQL 技术内幕:InnoDB 存储引擎》一书。
Python
4、事务
  简单地说,事务就是指逻辑上的一组SQL语句操作,组成这组操作的各个SQL语句,
  执行时要么全成功要么全失败。
事务的介绍及特性
事务介绍:
    简单地说,事务就是指逻辑上的一组SQL语句操作,组成这组操作的各个SQL语句,执行时要么全成功要么全失败。
例如:你给我转账5块钱,流程如下
            a.从你银行卡取出5块钱,剩余计算money-5
            b.把上面5块钱打入我的账户上,我收到5块,剩余计算money+5.
        上述转账的过程,对应的sql语句为:
                update 你_account set money=money-5 where name='你';
                update 我_account set money=money+5 where name='我';
        上述的两条SQL操作,在事务中的操作就是要么都执行,要么都不执行,不然钱就对不上了。
        这就是事务的原子性(Atomicity)。

事务的四大特性:
    1.原子性(Atomicity)
      事务是一个不可分割的单位,事务中的所有SQL等操作要么都发生,要么都不发生。

    2.一致性(Consistency)
      事务发生前和发生后,数据的完整性必须保持一致。

    3.隔离性(Isolation)
      当并发访问数据库时,一个正在执行的事务在执行完毕前,对于其他的会话是不可见的,
      多个并发事务之间的数据是相互隔离的。
      也就是其他人的操作在这个事务的执行过程中是看不到这个事务的执行结果的,
      也就是他们拿到的是这个事务执行之前的内容,等这个事务执行完才能拿到新的数据。

    4.持久性(Durability)
      一个事务一旦被提交,它对数据库中的数据改变就是永久性的。如果出了错误,事务也不允撤销,只能通过'补偿性事务'。

事务的开启:
数据库默认事务是自动提交的,也就是发一条sql他就执行一条。
如果想多条sql放在一个事务中执行,则需要使用事务进行处理。
当我们开启一个事务,并且没有提交,mysql会自动回滚事务。
或者我们使用rollback命令手动回滚事务。

数据库开启事务的命令,我们后面会讲到~~~
Python
在介绍上面两个引擎中涉及的两个概念(OLTP和OLAP)的介绍

参考文章:

5、其他引擎的介绍
其他引擎简单介绍
#NDB 存储引擎
2003 年,MySQL AB 公司从 Sony Ericsson 公司收购了 NDB 存储引擎。
NDB 存储引擎是一个集群存储引擎,类似于 Oracle 的 RAC 集群,不过与 Oracle RAC 的 share everything 结构不同的是,
其结构是 share nothing 的集群架构,因此能提供更高级别的 高可用性。
NDB 存储引擎的特点是数据全部放在内存中(从 5.1 版本开始,可以将非索引数 据放在磁盘上),
因此主键查找(primary key lookups)的速度极快,并且能够在线添加 NDB 数据存储节点(data node)以便线性地提高数据库性能。
由此可见,NDB 存储引擎是高可用、 高性能、高可扩展性的数据库集群系统,其面向的也是 OLTP 的数据库应用类型。

#Memory 存储引擎
正如其名,Memory 存储引擎中的数据都存放在内存中,数据库重 启或发生崩溃,表中的数据都将消失。
它非常适合于存储 OLTP 数据库应用中临时数据的临时表,也可以作为 OLAP 数据库应用中数据仓库的维度表。
Memory 存储引擎默认使用哈希 索引,而不是通常熟悉的 B+ 树索引。

#Infobright 存储引擎
第三方的存储引擎。其特点是存储是按照列而非行的,因此非常 适合 OLAP 的数据库应用。
其官方网站是 http://www.infobright.org/,上面有不少成功的数据 仓库案例可供分析。

#NTSE 存储引擎
网易公司开发的面向其内部使用的存储引擎。
目前的版本不支持事务, 但提供压缩、行级缓存等特性,不久的将来会实现面向内存的事务支持。

#BLACKHOLE
黑洞存储引擎,可以应用于主备复制中的分发主库。
也可以用来防网络攻击,dds攻击,

MySQL 数据库还有很多其他存储引擎,上述只是列举了最为常用的一些引擎。
如果 你喜欢,完全可以编写专属于自己的引擎,这就是开源赋予我们的能力,也是开源的魅 力所在。
Python

4、存储引擎的使用

1、创建表时指定引擎
create table innodb_t2(id int)engine=innodb;
2、在配置文件中指定默认的存储引擎
linux:vim /etc/my.cnf   windows:my.ini文件
[mysqld]
default-storage-engine=INNODB  #配置默认引擎,现在用的mysql默认基本都是InnoDB,所以其实都可以不用配置了
innodb_file_per_table=1  #表示独立表空间存储,可以不写
3、不同引擎在创建表的时候生成文件的不同
创建四个表,分别使用innodb,myisam,memory,blackhole存储引擎,进行插入数据测试

#下面是使用四个不同的引擎来创建的表
create table t1(id int)engine=innodb;
create table t2(id int)engine=myisam;
create table t3(id int)engine=memory;
create table t4(id int)engine=blackhole;

通过四种引擎来创建的表,我们对照着其生成的文件来看一下区别,看下图:

4、关于上面的文件作用介绍:
数据库文件夹中各文件的作用
1.db.opt文件:用来记录该库的默认字符集编码和字符集排序规则用的。
也就是说如果你创建数据库指定默认字符集和排序规则,
那么后续创建的表如果没有指定字符集和排序规则,那么该新建的表将采用db.opt文件中指定的属性。

2.后缀名为.frm的文件:这个文件主要是用来描述数据表结构(id,name字段等)和字段长度等信息

3.后缀名为.ibd的文件:这个文件主要储存的是采用独立表储存模式时储存数据库的数据信息和索引信息;

4.后缀名为.MYD(MYData)的文件:从名字可以看出,
这个是存储数据库数据信息的文件,主要是存储采用独立表储存模式时存储的数据信息;

5.后缀名为.MYI的文件:这个文件主要储存的是数据库的索引信息;

6.ibdata1文件:主要作用也是储存数据信息和索引信息,这个文件在mysql安装目录的data文件夹下。

  从上面可以看出,.ibd储存的是数据信息和索引信息,ibdata1文件也是存储数据信息和索引信息,
  .MYD和.MYI也是分别储存数据信息和索引信息,那他们之间有什么区别呢?

  主要区别是再于数据库的存储引擎不一样,
  如果储存引擎采用的是MyISAM,则生成的数据文件为表名.frm、表名.MYD、表名的MYI;
  而储存引擎如果是innoDB,开启了innodb_file_per_table=1,也就是采用独立储存的模式,生成的文件是表名.frm、表名.ibd,
  如果采用共存储模式的,数据信息和索引信息都存储在ibdata1(在里面进行分类,从外面看是一个文件)中;

  在进行数据恢复的时候,如果用的是MYISAM数据引擎,那么数据很好恢复,只要将相应.frm, .MYD, .MYI文件拷贝过去即可。
  但是如果是innodb的话,则每一个数据表都是一个单独的文件,只将相应的.frm和.ibd文件拷贝过去是不够的,
  必须在你的ibd文件的tablespace id和ibdata1文件中的元信息的tablespace id一致才可以。

msyql人家设定的规则就是这样存储表的,使用人家的系统,就要理解人家的规则。
Python
在Oracle 和SQL Server等所有数据存储管理机制都是一样的。
而MySql数据库提供了多种存储引擎。
用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。

  Oracle中不存在引擎的概念,
数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、
联机分析处理OLAP(On-Line Analytical Processing)。
OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。
OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。

2、表介绍

表相当于文件,表中的一条记录就相当于文件的一行内容,
表中的一条记录有对应的标题,称为表的字段


第一行的id、name2、age是字段,,其余的,一行内容称为一条记录。

3、创建表

1、创建表的语法

#语法:
create table 表名(
字段名1 类型[(宽度) 约束条件],
字段名2 类型[(宽度) 约束条件],
字段名3 类型[(宽度) 约束条件]
);

#注意:
1. 在同一张表中,字段名是不能相同
2. 宽度和约束条件可选、非必须,宽度指的就是字段长度约束,例如:char(10)里面的10
3. 字段名和类型是必须的

fe:代码示例

代码示例
mysql> create database db1 charset utf8;

mysql> use db1;

mysql> create table t1(
    -> id int,
    -> name varchar(50),
    -> sex enum('male','female'),
    -> age int(3)
    -> );

mysql> show tables; #查看db1库下所有表名

mysql> desc t1;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(50)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | YES  |     | NULL    |       |
| age   | int(3)                | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+

mysql> select id,name,sex,age from t1;
Empty set (0.00 sec)

mysql> select * from t1;
Empty set (0.00 sec)

mysql> select id,name from t1;
Empty set (0.00 sec)
Mysql

fe:插入数据

插入数据
mysql> insert into t1 values
    -> (1,'chao',18,'male'),
    -> (2,'sb',81,'female')
    -> ;
mysql> select * from t1;
+------+------+------+--------+
| id   | name | age  | sex    |
+------+------+------+--------+
|    1 | chao |   18 | male   |
|    2 | sb |   81 | female |
+------+------+------+--------+


mysql> insert into t1(id) values
    -> (3),
    -> (4);
mysql> select * from t1;
+------+------+------+--------+
| id   | name | age  | sex    |
+------+------+------+--------+
|    1 | chao |   18 | male   |
|    2 | sb |   81 | female |
|    3 | NULL | NULL | NULL   |
|    4 | NULL | NULL | NULL   |
+------+------+------+--------+
Python

4、查看表结构

mysql> describe t1; #查看表结构,可简写为:desc 表名
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(50)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | YES  |     | NULL    |       |
| age   | int(3)                | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+


mysql> show create table t1G; #查看表详细结构,可加G

5、MySQL的基础数据类型

1、介绍

存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,
每种数据类型都有自己的宽度,但宽度是可选的

详细参考:
MySQL数据类型
官网介绍

mysql常用数据类型概览:

#1. 数字:
    整型:tinyinit  int  bigint
    小数:
        float :在位数比较短的情况下不精准
        double :在位数比较长的情况下不精准
            0.000001230123123123
            存成:0.000001230000

        decimal:(如果用小数,则用推荐使用decimal)
            精准
            内部原理是以字符串形式去存

#2. 字符串:
    char(10):简单粗暴,浪费空间,存取速度快
        root存成root000000
    varchar:精准,节省空间,存取速度慢

    sql优化:创建表时,定长的类型往前放,变长的往后放
                    比如性别           比如地址或描述信息

    >255个字符,超了就把文件路径存放到数据库中。
            比如图片,视频等找一个文件服务器,数据库中只存路径或url。

#3. 时间类型:
    最常用:datetime

#4. 枚举类型与集合类型
Mysql

2、数值类型

注意:对于整型来说,数据类型后面的宽度并不是存储长度限制,而是显示限制,
假如:int(8),那么显示时不够8位则用0来填充,够8位则正常显示,
通过zerofill来测试,存储长度还是int的4个字节长度。
默认的显示宽度就是能够存储的最大的数据的长度,
比如:int无符号类型,那么默认的显示宽度就是int(10),有符号的就是int(11),
因为多了一个符号,
所以我们没有必要指定整数类型的数据,没必要指定宽度,
因为默认的就能够将你存的原始数据完全显示

1.整数类型
整数类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT
作用:存储年龄,等级,id,各种号码等
fe:设置有无符号,默认有符号
默认有,create table t1(x tinyint)
create table t2(x tinyint unsigned);  (加了unsigned,就是无符号)
设置有无符号示例
1.tinyint默认为有符号
mysql> create table t1(x tinyint); #默认为有符号,即数字前有正负号
mysql> desc t1;
mysql> insert into t1 values
    -> (-129),
    -> (-128),
    -> (127),
    -> (128);
mysql> select * from t1;
+------+
| x    |
+------+
| -128 | #-129存成了-128
| -128 | #有符号,最小值为-128
|  127 | #有符号,最大值127
|  127 | #128存成了127
+------+

2.设置无符号tinyint
mysql> create table t2(x tinyint unsigned);  (加了unsigned,就是无符号)
mysql> insert into t2 values
    -> (-1),
    -> (0),
    -> (255),
    -> (256);
mysql> select * from t2;
+------+
| x    |
+------+
|    0 | -1存成了0
|    0 | #无符号,最小值为0
|  255 | #无符号,最大值为255
|  255 | #256存成了255
+------+

用zerofill测试整数类型的显示宽度
    mysql> create table t7(x int(3) zerofill);
    mysql> insert into t7 values
        -> (1),
        -> (11),
        -> (111),
        -> (1111);
    mysql> select * from t7;
    +------+
    | x    |
    +------+
    |  001 |
    |  011 |
    |  111 |
    | 1111 | #超过宽度限制仍然可以存
Python

MySQL的mode设置

MySQL的mode设置

2、浮点型
定点数类型  DEC,等同于DECIMAL  
浮点类型:FLOAT DOUBLE
作用:存储薪资、身高、温度、体重、体质参数等
三种浮点型数介绍
三种浮点型数介绍
1.FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

    定义:
            单精度浮点数(非准确小数值),m是整数部分总个数,d是小数点后个数。m最大值为255,d最大值为30,例如:float(255,30)

    有符号:
               -3.402823466E+38 to -1.175494351E-38,
               1.175494351E-38 to 3.402823466E+38
    无符号:
               1.175494351E-38 to 3.402823466E+38

    精确度:
               **** 随着小数的增多,精度变得不准确 ****

2.DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

    定义:
               双精度浮点数(非准确小数值),m是整数部分总个数,d是小数点后个数。m最大值也为255,d最大值也为30

    有符号:
               -1.7976931348623157E+308 to -2.2250738585072014E-308
               2.2250738585072014E-308 to 1.7976931348623157E+308

    无符号:
               2.2250738585072014E-308 to 1.7976931348623157E+308

    精确度:
               ****随着小数的增多,精度比float要高,但也会变得不准确 ****


3.decimal[(m[,d])] [unsigned] [zerofill]

    定义:
    准确的小数值,m是整数部分总个数(负号不算),d是小数点后个数。
    m最大值为65,d最大值为30。比float和double的整数个数少,但是小数位数都是30位


    精确度:
       **** 随着小数的增多,精度始终准确 ****
         对于精确数值计算时需要用此类型
         decimal能够存储精确值的原因在于其内部按照字符串存储。

精度从高到低:decimal、double、float

    decimal精度高,但是整数位数少
    float和double精度低,但是整数位数多

float已经满足绝大多数的场景了,但是什么导弹、航线等要求精度非常高,
所以还是需要按照业务场景自行选择,如果又要精度高又要整数位数多,那么你可以直接用字符串来存。

Python
3、位类型(了解,不讲
BIT(M)可以用来存放多位二进制数,M范围从1~64,如果不写默认为1位。
注意:对于位字段需要使用函数读取
bin()显示为二进制
hex()显示为十六进制
位类型测试
mysql> create table t9(id bit);
mysql> desc t9; #bit默认宽度为1
+-------+--------+------+-----+---------+-------+
| Field | Type   | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| id    | bit(1) | YES  |     | NULL    |       |
+-------+--------+------+-----+---------+-------+

mysql> insert into t9 values(8);
mysql> select * from t9; #直接查看是无法显示二进制位的
+------+
| id   |
+------+
|     |
+------+
mysql> select bin(id),hex(id) from t9; #需要转换才能看到
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
+---------+---------+

mysql> alter table t9 modify id bit(5);
mysql> insert into t9 values(8);
mysql> select bin(id),hex(id) from t9;
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
| 1000    | 8       |
+---------+---------+
Python

3、日期类型

类型:DATE,TIME,DATETIME ,IMESTAMP,YEAR
作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等
日期类型分类
YEAR
YYY(范围:1901/2155)2018

DATE
    YYYY-MM-DD(范围:1000-01-01/9999-12-31)例:2018-01-01

TIME
    HH:MM:SS(范围:'-838:59:59'/'838:59:59')例:12:09:32

DATETIME
    YYYY-MM-DD HH:MM:SS(范围:1000-01-01 00:00:00/9999-12-31 23:59:59    Y)例: 2018-01-01 12:09:32

TIMESTAMP
    YYYYMMDD HHMMSS(范围:1970-01-01 00:00:00/2037 年某时)
Python
日期类型测试
year:
    mysql> create table t10(born_year year); #无论year指定何种宽度,最后都默认是year(4)
    mysql> insert into t10 values
        -> (1900),
        -> (1901),
        -> (2155),
        -> (2156);
    mysql> select * from t10;
    +-----------+
    | born_year |
    +-----------+
    |      0000 |
    |      1901 |
    |      2155 |
    |      0000 |
    +-----------+


date,time,datetime:
    mysql> create table t11(d date,t time,dt datetime);
    mysql> desc t11;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | d     | date     | YES  |     | NULL    |       |
    | t     | time     | YES  |     | NULL    |       |
    | dt    | datetime | YES  |     | NULL    |       |
    +-------+----------+------+-----+---------+-------+

    mysql> insert into t11 values(now(),now(),now());
    mysql> select * from t11;
    +------------+----------+---------------------+
    | d          | t        | dt                  |
    +------------+----------+---------------------+
    | 2017-07-25 | 16:26:54 | 2017-07-25 16:26:54 |
    +------------+----------+---------------------+



timestamp:
    mysql> create table t12(time timestamp);
    mysql> insert into t12 values();
    mysql> insert into t12 values(null);
    mysql> select * from t12;
    +---------------------+
    | time                |
    +---------------------+
    | 2017-07-25 16:29:17 |
    | 2017-07-25 16:30:01 |
    +---------------------+

============注意啦,注意啦,注意啦===========
    1. 单独插入时间时,需要以字符串的形式,按照对应的格式插入
    2. 插入年份时,尽量使用4位值
    3. 插入两位年份时,<=69,以20开头,比如50,  结果2050
                    >=70,以19开头,比如71,结果1971
    mysql> create table t12(y year);
    mysql> insert into t12 values
        -> (50),
        -> (71);
    mysql> select * from t12;
    +------+
    | y    |
    +------+
    | 2050 |
    | 1971 |
    +------+
Python

mysql的日期格式对字符串采用的是’放松’政策,可以以字符串的形式插入。

datetime与timestamp的区别
在实际应用的很多场景中,MySQL的这两种日期类型都能够满足我们的需要,存储精度都为秒,
但在某些情况下,会展现出他们各自的优劣。下面就来总结一下两种日期类型的区别。

1.DATETIME的日期范围是1001——9999年,TIMESTAMP的时间范围是1970——2038年。

2.DATETIME存储时间与时区无关,TIMESTAMP存储时间与时区有关,显示的值也依赖于时区。
在mysql服务器,操作系统以及客户端连接都有时区的设置。

3.DATETIME使用8字节的存储空间,TIMESTAMP的存储空间为4字节。
因此,TIMESTAMP比DATETIME的空间利用率更高。

4.DATETIME的默认值为null;TIMESTAMP的字段默认不为空(not null),
默认值为当前时间(CURRENT_TIMESTAMP),如果不做特殊处理,并且update语句中没有指定该列的更新值,则默认更新为当前时间。
Python

工作中一般都用datetime就可以了。 

对上面datetime与timestamp的区别中第四条的验证
mysql> create table t1(x datetime not null default now()); # 需要指定传入空值时默认取当前时间
Query OK, 0 rows affected (0.01 sec)

mysql> create table t2(x timestamp); # 无需任何设置,在传空值的情况下自动传入当前时间
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t1 values();
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values();
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+---------------------+
| x                   |
+---------------------+
| 2018-07-07 01:26:14 |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from t2;
+---------------------+
| x                   |
+---------------------+
| 2018-07-07 01:26:17 |
+---------------------+
1 row in set (0.00 sec)
Python

4、字符串类型

类型:char,固定长度
varchar  可变长度

  作用:名字,信息等等

length(字段):查看该字段数据的字节长度

char_length(字段):查看该字段数据的字符长度
char和varchar的介绍
#官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
#注意:char和varchar括号内的参数指的都是字符的长度

#char类型:定长,简单粗暴,浪费空间,存取速度快
    字符长度范围:0-255(一个中文是一个字符,是utf8编码的3个字节)
    存储:
        存储char类型的值时,会往右填充空格来满足长度
        例如:指定长度为10,存>10个字符则报错(严格模式下),存<10个字符则用空格填充直到凑够10个字符存储

    检索:
        在检索或者说查询时,查出的结果会自动删除尾部的空格,如果你想看到它补全空格之后的内容,
        除非我们打开pad_char_to_full_length SQL模式(SET sql_mode = 'strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH';)

#varchar类型:变长,精准,节省空间,存取速度慢
    字符长度范围:0-65535(如果大于21845会提示用其他类型 。
    mysql行最大限制为65535字节,字符编码为utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
    存储:
        varchar类型存储数据的真实内容,不会用空格填充,如果'ab  ',尾部的空格也会被存起来
        强调:varchar类型会在真实数据前加1-2Bytes的前缀,
        该前缀用来表示真实数据的bytes字节数(1-2Bytes最大表示65535个数字,正好符合mysql对row的最大字节限制,即已经足够使用)
        如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)
        如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)

    检索:
        尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容
Python
char和varchar测试
创建一个t1表,包含一个char类型的字段
create table t1(id int,name char(4));
超过长度:
严格模式下(报错):
    mysql> insert into t1 values('xiaoshabi');
    ERROR 1406 (22001): Data too long for column 'name' at row 1
非严格模式下(警告):
    mysql> set sql_mode='NO_ENGINE_SUBSTITUTION';
    Query OK, 0 rows affected (0.00 sec)

    mysql> create table t1(id int,name char(4));
    Query OK, 0 rows affected (0.40 sec)

    mysql> insert into t2 values('xiaoshabi');
    Query OK, 1 row affected, 1 warning (0.11 sec)
    查看一下结果:
    mysql> select * from t1;
    +------+------+
    | id   | name |
    +------+------+
    |    1 | xiao | #只有一个xiao
    +------+------+
    1 row in set (0.00 sec)
varchar类型和上面的效果是一样的,严格模式下也会报错。

如果没有超过长度,那么char类型时mysql会使用空格来补全自己规定的char(4)的4个字符,varchar不会,我们来做个对比
例如:
#再创建一个含有varchar类型的表t2
然后插入几条和t1里面相同的数据
mysql>insert into t1 values(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');

mysql>create table t2(id int,name varchar(4));

mysql> insert into t2 values(1,'xiao'),(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');
查看一下t1表和t2表的内容
mysql> select * from t1;
+------+------+
| id   | name |
+------+------+
|    1 | xiao |
|    2 | a    |
|    3 | bb   |
|    4 | ccc  |
|    5 | d    |
+------+------+
5 rows in set (0.00 sec)

mysql> select * from t2;
+------+------+
| id   | name |
+------+------+
|    1 | xiao |
|    2 | a    |
|    3 | bb   |
|    4 | ccc  |
|    5 | d    |
+------+------+
5 rows in set (0.00 sec)

好,两个表里面数据是一样的,每一项的数据长度也是一样的,
那么我们来验证一下char的自动空格在后面补全的存储方式和varchar的不同

通过mysql提供的一个char_length()方法来查看一下所有数据的长度
mysql> select char_length(name) from t1;
+-------------------+
| char_length(name) |
+-------------------+
|                 4 |
|                 1 |
|                 2 |
|                 3 |
|                 1 |
+-------------------+
5 rows in set (0.00 sec)

mysql> select char_length(name) from t2;
+-------------------+
| char_length(name) |
+-------------------+
|                 4 |
|                 1 |
|                 2 |
|                 3 |
|                 1 |
+-------------------+
5 rows in set (0.00 sec)
通过查看结果可以看到,两者显示的数据长度是一样的,不是说好的char会补全吗,
我设置的字段是char(4),那么长度应该都是4才对啊?这是因为mysql在你查询的时候自动帮你把结果里面的空格去掉了,
如果我们想看到它存储数据的真实长度,需要设置mysql的模式,通过一个叫做PAD_CHAR_TO_FULL_LENGTH的模式,就可以看到了,所以我们把这个模式加到sql_mode里面:

mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

然后我们在查看一下t1和t2数据的长度:
mysql> select char_length(name) from t1;
+-------------------+
| char_length(name) |
+-------------------+
|                 4 |
|                 4 |
|                 4 |
|                 4 |
|                 4 |
+-------------------+
5 rows in set (0.00 sec)

mysql> select char_length(name) from t2;
+-------------------+
| char_length(name) |
+-------------------+
|                 4 |
|                 1 |
|                 2 |
|                 3 |
|                 1 |
+-------------------+
5 rows in set (0.00 sec)
通过结果可以看到,char类型的数据长度都是4,这下看到了两者的不同了吧,至于为什么mysql会这样搞,我们后面有解释的,先看现象就可以啦。

现在我们再来看一个问题,就是当你设置的类型为char的时候,我们通过where条件来查询的时候会有一个什么现象:
mysql> select * from t1 where name='a';
+------+------+
| id   | name |
+------+------+
|    2 | a    |
+------+------+
1 row in set (0.00 sec)
ok,结果没问题,我们在where后面的a后面加一下空格再来试试:
mysql> select * from t1 where name='a ';
+------+------+
| id   | name |
+------+------+
|    2 | a    |
+------+------+
1 row in set (0.00 sec)
ok,能查到,再多加一些空格试试,加6个空格,超过了设置的char(4)的4:
mysql> select * from t1 where name='a      ';
+------+------+
| id   | name |
+------+------+
|    2 | a    |
+------+------+
1 row in set (0.00 sec)
ok,也是没问题的
总结:通过>,=,>=,<,<=作为where的查询条件的时候,char类型字段的查询是没问题的。
但是,当我们将where后面的比较符号改为like的时候,(like是模糊匹配的意思,
我们前面见过,show variables like '%char%';来查看mysql字符集的时候用过)

其中%的意思是匹配任意字符(0到多个字符都可以匹配到),还有一个符号是_(匹配1个字符),
这两个字符其实就像我们学的正则匹配里面的通配符,
那么我们通过这些符号进行一下模糊查询,看一下,char类型进行模糊匹配的时候,是否还能行,看例子:

mysql> select * from t1 where name like 'a';
Empty set (0.00 sec)
发现啥也没查到,因为char存储的数据是4个字符长度的,不满4个是以空格来补全的,你在like后面就只写了一个'a',是无法查到的。
我们试一下上面的通配符来查询:
mysql> select * from t1 where name like 'a%';
+------+------+
| id   | name |
+------+------+
|    2 | a    |
+------+------+
1 row in set (0.00 sec)
这样就能看到查询结果了

试一下_是不是匹配1个字符:
mysql> select * from t1 where name like 'a_';
Empty set (0.00 sec)
发现一个_果然不行,我们试试三个_。
mysql> select * from t1 where name like 'a___';
+------+------+
| id   | name |
+------+------+
|    2 | a    |
+------+------+
1 row in set (0.00 sec)
发现果然能行,一个_最多匹配1个任意字符。
如果多写了几个_呢?
mysql> select * from t1 where name like 'a_____';
Empty set (0.00 sec)
查不到结果,说明_匹配的是1个字符,但不是0-1个字符。
Python
char和varchar测试结果总结:

  针对char类型,mysql在存储的时候会将不足规定长度的数据使用后面(右边补全)补充空格的形式进行补全,
然后存放到硬盘中,但是在读取或者使用的时候会自动去掉它给你补全的空格内容,
因为这些空格并不是我们自己存储的数据,所以对我们使用者来说是无用的。

1、char和varchar性能对比:
char
以char(5)和varchar(5)来比较,加入我要存三个人名:sb,ssb1,ssbb2
char:
    优点:简单粗暴,不管你是多长的数据,我就按照规定的长度来存,
    5个5个的存,三个人名就会类似这种存储:sb ssb1 ssbb2,
    中间是空格补全,取数据的时候5个5个的取,简单粗暴速度快

    缺点:貌似浪费空间,并且我们将来存储的数据的长度可能会参差不齐

varchar:
    varchar类型不定长存储数据,更为精简和节省空间
    例如存上面三个人名的时候类似于是这样的:sbssb1ssbb2,连着的,
    如果这样存,请问这三个人名你还怎么取出来,
    你知道取多长能取出第一个吗?(,我能看出来啊,那我只想说:滚犊子!)

    不知道从哪开始从哪结束,遇到这样的问题,你会想到怎么解决呢?
    还记的吗?想想?socket?tcp?struct?把数据长度作为消息头。

    所以,varchar在存数据的时候,会在每个数据前面加上一个头,这个头是1-2个bytes的数据,
    这个数据指的是后面跟着的这个数据的长度,1bytes能表示2**8=256,两个bytes表示2**16=65536,
    能表示0-65535的数字,所以varchar在存储的时候是这样的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,
    所以存的时候会比较麻烦,导致效率比char慢,取的时候也慢,先拿长度,再取数据。

    优点:节省了一些硬盘空间,一个acsii码的字符用一个bytes长度就能表示,
    但是也并不一定比char省,看一下官网给出的一个表格对比数据,
    当你存的数据正好是你规定的字段长度的时候,varchar反而占用的空间比char要多。

Value   CHAR(4) Storage Required    VARCHAR(4)  Storage Required
''  '    '  4 bytes ''  1 byte
'ab'    'ab  '  4 bytes 'ab'    3 bytes
'abcd'  'abcd'  4 bytes 'abcd'  5 bytes
'abcdefgh'  'abcd'  4 bytes 'abcd'  5 bytes
        
    缺点:存取速度都慢

 总结:
  所以需要根据业务需求来选择用哪种类型来存
  其实在多数的用户量少的工作场景中char和varchar效率差别不是很大,最起码给用户的感知不是很大,
    并且其实软件级别的慢远比不上硬件级别的慢,所以你们公司的运维发现项目慢的时候会加内存、换nb的硬盘,
    项目的效率提升的会很多,但是我们作为专业人士,我们应该提出来这样的技术点来提高效率。

  但是对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),
    因此在本质上,使用固定长度的CHAR列不一定比使用可变长度VARCHAR列性能要好。
    因而,主要的性能因素是数据行使用的存储总量。
    由于CHAR平均占用的空间多于VARCHAR,
    因此使用VARCHAR来最小化需要处理的数据行的存储总量和磁盘I/O是比较好的。

 所以啊,两个选哪个都可以,如果是大型并发项目,追求高性能的时候,
  需要结合你们服务器的硬件环境来进行测试,看一下char和varchar哪个更好,这也能算一个优化的点吧~~~~
Char
varchar
#官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
CHAR 和 VARCHAR 是最常使用的两种字符串类型。
一般来说
CHAR(N)用来保存固定长度的字符串,对于 CHAR 类型,N 的范围 为 0 ~ 255
VARCHAR(N)用来保存变长字符类型,对于 VARCHAR 类型,N 的范围为 0 ~ 65 535
CHAR(N)和 VARCHAR(N) 中的 N 都代表字符长度,而非字节长度。
ps:对于 MySQL 4.1 之前的版本,如 MySQL 3.23 和 MySQL 4.0,CHAR(N)和 VARCHAR (N)中的 N 代表字节长度。

#CHAR类型
对于 CHAR 类型的字符串,MySQL 数据库会自动对存储列的右边进行填充(Right Padded)操作,
直到字符串达到指定的长度 N。而在读取该列时,MySQL 数据库会自动将 填充的字符删除。
有一种情况例外,那就是显式地将 SQL_MODE 设置为 PAD_CHAR_TO_ FULL_LENGTH,例如:

mysql> CREATE TABLE t ( a CHAR(10));
      Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO t SELECT 'abc';
      Query OK, 1 row affected (0.03 sec)
      Records: 1  Duplicates: 0  Warnings: 0
mysql> SELECT a,HEX(a),LENGTH(a) FROM tG;
      *************************** 1. row ***************************
              a: abc
         HEX(a): 616263
      LENGTH (a): 3
      1 row in set (0.00 sec)
      mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
      Query OK, 0 rows affected (0.00 sec)
mysql> SELECT a,HEX(a),LENGTH(a) FROM tG;
      *************************** 1. row ***************************
              a: abc
         HEX(a): 61626320202020202020
      LENGTH (a): 10
      1 row in set (0.00 sec)

在上述这个例子中,先创建了一张表 t,a 列的类型为 CHAR(10)。
然后通过 INSERT语句插入值“abc”,因为 a 列的类型为 CHAR 型,所以会自动在后面填充空字符串,
使其长 度为 10。接下来在通过 SELECT 语句取出数据时会将 a 列右填充的空字符移除,
从而得到 值“abc”。通过 LENGTH 函数看到 a 列的字符长度为 3 而非 10。

接着我们将 SQL_MODE 显式地设置为 PAD_CHAR_TO_FULL_LENGTH。
这时再通过 SELECT 语句进行查询时,得到的结果是“abc ”,
abc 右边有 7 个填充字符 0x20,并通 过 HEX 函数得到了验证。
这次 LENGTH 函数返回的长度为 10。需要注意的是,LENGTH 函数返回的是字节长度,而不是字符长度。
对于多字节字符集,CHAR(N)长度的列最多 可占用的字节数为该字符集单字符最大占用字节数 *N。
例如,对于 utf8 下,CHAR(10)最 多可能占用 30 个字节。
通过对多字节字符串使用 CHAR_LENGTH 函数和 LENGTH 函数, 可以发现两者的不同,示例如下:

mysql> SET NAMES gbk;
     Query OK, 0 rows affected (0.03 sec)
mysql> SELECT @a:='MySQL 技术内幕 '; Query OK, 0 rows affected (0.03 sec)
mysql> SELECT @a,HEX(@a),LENGTH(@a),CHAR_LENGTH(@a)G; ***************************** 1. row **************************** a: MySQL 技术内幕
HEX(a): 4D7953514CBCBCCAF5C4DAC4BB
LENGTH (a): 13
CHAR_LENGTH(a): 9
1 row in set (0.00 sec)

变 量 @ a 是 g b k 字 符 集 的 字 符 串 类 型 , 值 为 “ M y S Q L 技 术 内 幕 ”,
十 六 进 制 为 0x4D7953514CBCBCCAF5C4DAC4BB,LENGTH 函数返回 13,即该字符串占用 13 字节,
 因为 gbk 字符集中的中文字符占用两个字节,因此一共占用 13 字节。CHAR_LENGTH 函数 返回 9,很显然该字符长度为 9。


#VARCHAR类型
VARCHAR 类型存储变长字段的字符类型,与 CHAR 类型不同的是,其存储时需要在 前缀长度列表加上实际存储的字符,
该字符占用 1 ~ 2 字节的空间。当存储的字符串长度小 于 255 字节时,其需要 1 字节的空间,
当大于 255 字节时,需要 2 字节的空间。所以,对 于单字节的 latin1 来说,
CHAR(10)和 VARCHAR(10)最大占用的存储空间是不同的, CHAR(10)占用 10 个字节这是毫无疑问的,
而 VARCHAR(10)的最大占用空间数是 11 字节,因为其需要 1 字节来存放字符长度。
-------------------------------------------------
注意 对于有些多字节的字符集类型,其 CHAR 和 VARCHAR 在存储方法上是一样的,
同样 需要为长度列表加上字符串的值。
对于 GBK 和 UTF-8 这些字符类型,其有些字符是以 1 字节 存放的,
有些字符是按 2 或 3 字节存放的,因此同样需要 1 ~ 2 字节的空间来存储字符的长 度。
-------------------------------------------------
虽然 CHAR 和 VARCHAR 的存储方式不太相同,但是对于两个字符串的比较,都只比 较其值,
忽略 CHAR 值存在的右填充,即使将 SQL _MODE 设置为 PAD_CHAR_TO_FULL_ LENGTH 也一样,例如:

mysql> CREATE TABLE t ( a CHAR(10), b VARCHAR(10));
    Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t SELECT 'a','a';
    Query OK, 1 row affected (0.00 sec)
    Records: 1  Duplicates: 0  Warnings: 0
mysql> SELECT a=b FROM tG;
    *************************** 1. row ***************************
    a=b: 1
    1 row in set (0.00 sec)
    mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
    Query OK, 0 rows affected (0.00 sec)
mysql> SELECT a=b FROM tG;
    *************************** 1. row ***************************
    a=b: 1
    1 row in set (0.00 sec)
Bash
2、其他类型简单介绍
其他类型简单介绍
4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

BLOB:
     1._BLOB和_text存储方式不同,_TEXT以文本方式存储,英文存储区分大小写,而_Blob是以二进制方式存储,不分大小写。
     2._BLOB存储的数据只能整体读出。
     3._TEXT可以指定字符集,_BLO不用指定字符集。
Bash

5、枚举类型与集合类型

字段的值只能在给定范围中选择,如单选框,多选框,
如果你在应用程序或者前端不做选项限制,在MySQL的字段里面也能做限制

  enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female
  set 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3…)

 枚举类型(enum)
    An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.)
     示例:
      CREATE TABLE shirts (
       name VARCHAR(40),
       size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
       );
       INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small');



集合类型(set)
    A SET column can have a maximum of 64 distinct members.
 示例:
    CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
    INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Mysql
测试
 mysql> create table consumer(
    -> name varchar(50),
    -> sex enum('male','female'),
    -> level enum('vip1','vip2','vip3','vip4','vip5'), #在指定范围内,多选一
    -> hobby set('play','music','read','study') #在指定范围内,多选多
    -> );

    mysql> insert into consumer values
        -> ('xiaogui','male','vip5','read,study'),
        -> ('taibai','female','vip1','girl');

    mysql> select * from consumer;
    +------+--------+-------+------------+
    | name | sex    | level | hobby      |
    +------+--------+-------+------------+
    | xiaogui | male   | vip5  | read,study |
    | taibai | female | vip1  |            |
    +------+--------+-------+------------+
原文地址:https://www.cnblogs.com/yipianshuying/p/10111296.html