python 全栈开发,Day61(库的操作,表的操作,数据类型,数据类型(2),完整性约束)

昨日内容回顾

一、回顾
定义:mysql就是一个基于socket编写的C / S架构的软件

包含:
---服务端软件
- socket服务端
- 本地文件操作
           - 解析指令(mysql语句)
---客户端软件
- socket客户端
- 发送指令
           - 解析指令(mysql语句)
重点理解:
数据库服务器、数据管理系统、数据库、表与记录的关系

总结:

数据库服务器 -:运行数据库管理软件

数据库管理软件:管理 - 数据库

数据库:即文件夹,用来组织文件 / 表

表:即文件,用来存放多行内容 / 多条记录

  

一、库的操作

本节重点:

  • 掌握库的增删改查

一、系统数据库

执行如下命令,查看系统库

show databases;

information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息、列信息、权限信息、字符信息等
performance_schema: MySQL 5.5开始新增一个数据库:主要用于收集数据库服务器性能参数,记录处理查询请求时发生的各种事件、锁等现象
mysql: 授权库,主要存储系统用户的权限信息
sys:通过这个库可以快速的了解系统的元数据信息。sys库里这些视图中的数据,都是从information_schema里面获得的,目标是把performance_schema的把复杂度降低,让DBA能更好的阅读这个库里的内容。让DBA更快的了解DB的运行情况。

二、创建数据库

1、求救语法:

help create database;

2、创建数据库语法

CREATE DATABASE 数据库名 charset utf8;

3、数据库命名规则:  

可以由字母、数字、下划线、@、#、$
区分大小写
唯一性
不能使用关键字如 create select
不能单独使用数字
最长128位
# 基本上跟python或者js的命名规则一样

三、数据库相关操作

查看数据库

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

查看当前库

mysql> show create database db1;
+----------+--------------------------------------------------------------+
| Database | Create Database                                              |
+----------+--------------------------------------------------------------+
| db1      | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.06 sec)

选择数据库

比如db1

mysql> use db1;
Database changed

查看当前所在的库

mysql> select database();
+------------+
| database() |
+------------+
| db1        |
+------------+
1 row in set (0.00 sec)

删除数据库

比如db1

mysql> drop database db1;
Query OK, 2 rows affected (0.40 sec)

修改数据库字符集

先创建(因为上面被干掉了),再修改

mysql> create database db1;
Query OK, 1 row affected (0.00 sec)

mysql> alter database db1 charset utf8;
Query OK, 1 row affected (0.00 sec)

四、了解内容

SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统,SQL语言由IBM开发。SQL语言分为3种类型:
1、DDL语句    数据库定义语言: 数据库、表、视图、索引、存储过程,例如CREATE DROP ALTER

2、DML语句    数据库操纵语言: 插入数据INSERT、删除数据DELETE、更新数据UPDATE、查询数据SELECT

3、DCL语句    数据库控制语言: 例如控制用户的访问权限GRANT、REVOKE

二、表的操作

本节掌握

  • 存储引擎介绍(了解)

  • 表的增删改查

一、存储引擎(了解)

前几节我们知道mysql中建立的库===》文件夹,库中的表====》文件

现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处理文本用txt类型,处理表格用excel,处理图片用png等

数据库中的表也应该有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎。

ps: 存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)

在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql
数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据
自己的需要编写自己的存储引擎

 

SQL 解析器、SQL 优化器、缓冲池、存储引擎等组件在每个数据库中都存在,但不是每 个数据库都有这么多存储引擎。MySQL 的插件式存储引擎可以让存储引擎层的开发人员设 计他们希望的存储层,例如,有的应用需要满足事务的要求,有的应用则不需要对事务有这 么强的要求 ;有的希望数据能持久存储,有的只希望放在内存中,临时并快速地提供对数据 的查询。

二、mysql支持的存储引擎

查看所有支持的引擎

mysql> show engines\G;
*************************** 1. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
...(内容太多,这里不过多展示了)

查看正在使用的存储引擎

mysql> show variables like '%storage_engine%';
+----------------------------------+--------+
| Variable_name                    | Value  |
+----------------------------------+--------+
| default_storage_engine           | InnoDB |
| default_tmp_storage_engine       | InnoDB |
| disabled_storage_engines         |        |
| internal_tmp_disk_storage_engine | InnoDB |
+----------------------------------+--------+
4 rows in set, 1 warning (0.00 sec)

几大数据库引擎介绍

1、InnoDB 存储引擎

支持事务,其设计目标主要面向联机事务处理(OLTP)的应用。其

特点是行锁设计、支持外键,并支持类似 Oracle 的非锁定读,即默认读取操作不会产生锁。 从 MySQL 5.5.8 版本开始是默认的存储引擎。

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 存储引擎》一书。

2、MyISAM 存储引擎

不支持事务、表锁设计、支持全文索引,主要面向一些 OLAP 数 据库应用,在 MySQL 5.5.8 版本之前是默认的存储引擎(除 Windows 版本外)。数据库系统 与文件系统一个很大的不同在于对事务的支持,MyISAM 存储引擎是不支持事务的。究其根 本,这也并不难理解。用户在所有的应用中是否都需要事务呢?在数据仓库中,如果没有 ETL 这些操作,只是简单地通过报表查询还需要事务的支持吗?此外,MyISAM 存储引擎的 另一个与众不同的地方是,它的缓冲池只缓存(cache)索引文件,而不缓存数据文件,这与 大多数的数据库都不相同。

3、NDB 存储引擎

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 的数据库应用类型。
View Code

4、Memory 存储引擎

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

5、Infobright 存储引擎

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

6、NTSE 存储引擎

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

7、BLACKHOLE

黑洞存储引擎,可以应用于主备复制中的分发主库。

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

 

指定表类型/存储引擎

默认不写就是innodb

mysql> create table t1(id int)engine=innodb;
Query OK, 0 rows affected (0.25 sec)

 

小练习:

创建四张表,分别使用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;

查看data文件下db1数据库中的文件:

#.frm是存储数据表的框架结构

# .ibd是mysql数据文件 

#.MYD是MyISAM表的数据文件的扩展名

#.MYI是MyISAM表的索引的扩展名

#发现后两种存储引擎只有表结构,无数据

#memory,在重启mysql或者重启机器后,表内数据清空
#blackhole,往表内插入任何数据,都相当于丢入黑洞,表内永远不存记录

  

三、表介绍

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

 

id,name,sex,age,birth称为字段,其余的,一行内容称为一条记录

 

四、创建表

语法:

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

#注意:
1. 在同一张表中,字段名是不能相同
2. 宽度和约束条件可选
3. 字段名和类型是必须的

1.创建数据库

create database db2 charset utf8;

2.使用数据库

use db2;

3.创建a1表

create table a1(
  id int,
  name varchar(50),
  age int(3)
);

4.插入表的记录

insert into a1 values
(1,'mjj',18),
(2,'wusir',28);

ps:以;作为mysql的结束语

 

5.查询表的数据和结构

(1)查询a1表中的存储数据

mysql> select * from a1;
+----------+------------+-----------+
|   id   |   name   |   age   |
+----------+------------+-----------+
|        1 | mjj        |        18 |
|        2 | wusir      |        28 |
+----------+------------+-----------+
2 rows in set (0.00 sec)

(2)查看a1表的结构

mysql> desc a1;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
|   id     | int(11)     | YES  |     | NULL    |       |
|   name   | varchar(50) | YES  |     | NULL    |       |
|   age    | int(3)      | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.10 sec)

(3)查看表的详细结构

 注意:\G后面不需要加分号,否则报

ERROR: No query specified

mysql> show create table a1\G
*************************** 1. row ***************************
       Table: a1
Create Table: CREATE TABLE `a1` (
  `  id` int(11) DEFAULT NULL,
  `  name` varchar(50) DEFAULT NULL,
  `  age` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

 

6.复制表

(1)新创建一个数据库db3

mysql> create database db3 charset utf8;
Query OK, 1 row affected (0.00 sec)

(2)使用db3

mysql> use db3;
Database changed

这是上个创建的db2数据库中的a1表

mysql> select * from db2.a1;
+----------+------------+-----------+
|   id   |   name   |   age   |
+----------+------------+-----------+
|        1 | mjj        |        18 |
|        2 | wusir      |        28 |
+----------+------------+-----------+
2 rows in set (0.00 sec)

(3)复制db2.a1的表结构和记录

这就是复制表的操作(既复制了表结构,又复制了记录)

mysql> create table b1 select * from db2.a1;
Query OK, 2 rows affected (0.30 sec)
Records: 2  Duplicates: 0  Warnings: 0

(4)查看db3.b1中的数据和表结构

再去查看db3文件夹下的b1表发现 跟db2文件下的a1表数据一样

mysql> select * from db3.b1;
+----------+------------+-----------+
|   id   |   name   |   age   |
+----------+------------+-----------+
|        1 | mjj        |        18 |
|        2 | wusir      |        28 |
+----------+------------+-----------+
2 rows in set (0.00 sec)

ps1:如果只要表结构,不要记录

在db2数据库下新创建一个b2表,给一个where条件,条件要求不成立,条件为false,只拷贝表结构

mysql> create table b2 select * from db2.a1 where 1>5;
Query OK, 0 rows affected (0.68 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看表结构:

mysql> desc b2;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
|   id     | int(11)     | YES  |     | NULL    |       |
|   name   | varchar(50) | YES  |     | NULL    |       |
|   age    | int(3)      | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

查看表结构中的数据,发现是空数据

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

ps2:还有一种做法,使用like(只拷贝表结构,不拷贝记录)

推荐使用like

mysql> create table b3 like db2.a1;
Query OK, 0 rows affected (0.53 sec)

mysql> desc b3;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
|   id     | int(11)     | YES  |     | NULL    |       |
|   name   | varchar(50) | YES  |     | NULL    |       |
|   age    | int(3)      | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> select * from db3.b3;
Empty set (0.00 sec)

7.删除表:

drop table 表名;

比如b3

mysql> drop table db3.b3;
Query OK, 0 rows affected (0.20 sec)

 

三、数据类型

介绍

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

详细参考链接:http://www.runoob.com/mysql/mysql-data-types.html

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. 枚举类型与集合类型

 

一、数值类型

整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT

作用:存储年龄,等级,id,各种号码等

tinyint 小整数

tinyint[(m)] [unsigned] [zerofill]

小整数,数据类型用于保存一些范围的整数数值范围:
有符号:
    -128 ~ 127
无符号:
    0 ~ 255

PS: MySQL中无布尔值,使用tinyint(1)构造。
View Code

int 整数

int[(m)][unsigned][zerofill]

整数,数据类型用于保存一些范围的整数数值范围:
有符号:
        -2147483648 ~ 2147483647
无符号:
        0 ~ 4294967295
View Code

bigint 大整数

bigint[(m)][unsigned][zerofill]
大整数,数据类型用于保存一些范围的整数数值范围:
有符号:
        -9223372036854775808 ~ 9223372036854775807
无符号:
        0  ~  18446744073709551615
View Code

注意:一般表的主键id,会设置自增。对于业务量比较大的表,建议id字段设置bigint,并且添加无符号属性。能支撑几十年是没有问题的!

 

验证1:有符号和无符号tinyint

有符号tinyint

#创建数据库db4
mysql> create database db4 charset utf8;
Query OK, 1 row affected (0.00 sec)

#切换到当前db4数据库
mysql> use db4;
Database changed

#创建t1 规定x字段为tinyint数据类型(默认是有符号的)
mysql> create table t1(x tinyint);
Query OK, 0 rows affected (0.27 sec)

#验证,插入-1这个数
mysql> insert into t1 values(-1);
Query OK, 1 row affected (0.11 sec)

#查询 表记录,查询成功(证明默认是有符号类型)
mysql> select * from t1;
+------+
| x    |
+------+
|   -1 |
+------+
1 row in set (0.00 sec)

#执行如下操作,会发现报错。因为有符号范围在(-128,127)
mysql> insert into t1 values(-129),(128);
ERROR 1264 (22003): Out of range value for column 'x' at row 1

无符号tinyint

#创建表时定义记录的字符为无符号类型(0,255) ,使用unsigned
mysql> create table t2(x tinyint unsigned);
Query OK, 0 rows affected (0.30 sec)

#报错,超出范围
mysql> insert into t2 values(-129);
ERROR 1264 (22003): Out of range value for column 'x' at row 1

#插入成功
mysql> insert into t2 values(255);
Query OK, 1 row affected (0.09 sec)

 

验证2:int类型后面的存储是显示宽度,而不是存储宽度

#创建表t3,设置长度为1。注意:INT(1) 和 INT(11)本身没有区别
mysql> create table t3(id int(1) unsigned);
Query OK, 0 rows affected (0.30 sec)

#插入255555记录也是可以的
mysql> insert into t3 values(255555);
Query OK, 1 row affected (0.09 sec)

#查看表记录
mysql> select * from t3;
+--------+
| id     |
+--------+
| 255555 |
+--------+
1 row in set (0.00 sec)
ps:以上操作还不能够验证,再来一张表验证用zerofill 用0填充

#zerofill 用0填充
mysql> create table t4(id int(5) unsigned zerofill);
Query OK, 0 rows affected (0.31 sec)

#插入1
mysql> insert into t4 value(1);
Query OK, 1 row affected (0.09 sec)

#插入的记录是1,但是显示的宽度是00001
mysql> select * from t4;
+-------+
| id    |
+-------+
| 00001 |
+-------+
1 row in set (0.00 sec)

注意:为该类型指定宽度时,仅仅只是指定查询结果的显示宽度,与存储范围无关,存储范围如下

其实我们完全没必要为整数类型指定显示宽度,使用默认的就可以了

默认的显示宽度,都是在最大值的基础上加1

int的存储宽度是4个Bytes,即32个bit,即2**32

无符号最大值为:4294967296-1

有符号最大值:2147483648-1

有符号和无符号的最大数字需要的显示宽度均为10,而针对有符号的最小值则需要11位才能显示完全,所以int类型默认的显示宽度为11是非常合理的

最后:整形类型,其实没有必要指定显示宽度,使用默认的就ok

 

二、浮点型

定点数类型: DEC等同于DECIMAL

浮点类型:FLOAT DOUBLE

作用:存储薪资、身高、体重、体质参数等

语法:

float

FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
#参数解释:单精度浮点数(非准确小数值),M是整数部分总个数,D是小数点后个数。M最大值为255,D最大值为30

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

#无符号:
           1.175494351E-38 to 3.402823466E+38
#精确度: 
           **** 随着小数的增多,精度变得不准确 ****

double

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要高,但也会变得不准确 ****

decimal

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

#参数解释:准确的小数值,M是整数部分总个数(负号不算),D是小数点后个数。 M最大值为65,D最大值为30。


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

  

验证三种类型建表:

1.验证float类型建表

#D最大值为30,超过不允许创建
mysql> create table t5(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.

#M最大值为255,超过不允许创建
mysql> create table t5(x float(256,30));
ERROR 1439 (42000): Display width out of range for column 'x' (max = 255)

#建表成功
mysql> create table t5(x float(255,30));
Query OK, 0 rows affected (0.56 sec)

2.验证DOUBLE类型建表

#M最大值为255,D最大值为30。在这个范围内,就可以创建
mysql> create table t6(x double(255,30));
Query OK, 0 rows affected (0.53 sec)

3.验证deimal类型建表

#M最大值为65,D最大值为30,超过不允许创建
mysql> create table t7(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.

#超过M最大值,不允许创建
mysql> create table t7(x decimal(66,30));
ERROR 1426 (42000): Too-big precision 66 specified for 'x'. Maximum is 65.

#M最大值为65,D最大值为30
mysql> create table t7(x decimal(65,30));
Query OK, 0 rows affected (0.29 sec)

 

验证三种类型的精度:

分别对三张表插入相应的记录

#小数点后31个1
mysql> insert into t5 values(1.1111111111111111111111111111111);
Query OK, 1 row affected (0.21 sec)

mysql> insert into t6 values(1.1111111111111111111111111111111);
Query OK, 1 row affected (0.10 sec)

mysql> insert into t7 values(1.1111111111111111111111111111111);
Query OK, 1 row affected, 1 warning (0.09 sec)

#查询结果
#随着小数的增多,精度开始不准确
mysql> select * from t5;
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111164093017600000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

#精度比float要准确点,但随着小数的增多,同样变得不准确
mysql> select * from t6;
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111200000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

#精度始终准确,d为30,于是只留了30位小数
mysql> select * from t7;
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111111111111111111 |
+----------------------------------+
1 row in set (0.00 sec)

 

三、日期类型

DATE TIME DATETIME TIMESTAMP YEAR
作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等

语法:

YEAR
    YYYY(1901/2155)

DATE
    YYYY-MM-DD(1000-01-01/9999-12-31)

TIME
    HH:MM:SS('-838:59:59'/'838:59:59')

DATETIME
    YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59    Y)

TIMESTAMP
    YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)

 

1. year

#无论year指定何种宽度,最后都默认是year(4)
mysql> create table t8(born_year year);
Query OK, 0 rows affected (0.34 sec)

#插入失败,超出范围(1901/2155)
mysql> insert into t8 values(1900),(1901),(2155),(2156);
ERROR 1264 (22003): Out of range value for column 'born_year' at row 1

#查看表记录
mysql> select * from t8;
Empty set (0.00 sec)

#插入2条正常的值
mysql> insert into t8 values(1905),(2018);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

#查看表记录
mysql> select * from t8;
+-----------+
| born_year |
+-----------+
|      1905 |
|      2018 |
+-----------+
2 rows in set (0.00 sec)

 

2. date、year、datetime

#创建t9表
mysql> create table t9(d date,t time,dt datetime);
Query OK, 0 rows affected (0.28 sec)

#查看表的结构
mysql> desc t9;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d     | date     | YES  |     | NULL    |       |
| t     | time     | YES  |     | NULL    |       |
| dt    | datetime | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#调用mysql自带的now()函数,获取当前类型指定的时间 如下结构
mysql> insert into t9 values(now(),now(),now());
Query OK, 1 row affected, 1 warning (0.10 sec)

#查看表记录
mysql> select * from t9;
+------------+----------+---------------------+
| d          | t        | dt                  |
+------------+----------+---------------------+
| 2018-06-12 | 16:38:43 | 2018-06-12 16:38:43 |
+------------+----------+---------------------+
1 row in set (0.00 sec)

 

3. timestamp(了解即可)

mysql> create table t10(time timestamp);
Query OK, 0 rows affected (0.27 sec)

mysql> insert into t10 values();
Query OK, 1 row affected (0.05 sec)

mysql> insert into t10 values(null);
Query OK, 1 row affected (0.04 sec)

mysql> select * from t10;
+---------------------+
| time                |
+---------------------+
| 2018-06-12 16:40:56 |
| 2018-06-12 16:41:00 |
+---------------------+
2 rows in set (0.00 sec)

mysql> insert into t10 values(now());
Query OK, 1 row affected (0.09 sec)

mysql> select * from t10;
+---------------------+
| time                |
+---------------------+
| 2018-06-12 16:40:56 |
| 2018-06-12 16:41:00 |
| 2018-06-12 16:41:14 |
+---------------------+
3 rows in set (0.00 sec)

 

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语句中没有指定该列的更新值,则默认更新为当前时间。
View Code

 

注意事项

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

 

综合练习:

创建一张学生表(student),要求有id,姓名,出生年份,出生的年月日,进班的时间,以及来老男孩学习的现在具体时间。

#创建表
create table student(
    id int,
    name varchar(20),
    born_year year,
    birth date,
    class_time time,
    reg_time datetime
);

#插入3条记录
insert into student values
    (1,'alex',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"),
    (2,'egon',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"),
    (3,'wsb',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13");

#查看表记录
mysql> select * from student;
+------+------+-----------+------------+------------+---------------------+
| id   | name | born_year | birth      | class_time | reg_time            |
+------+------+-----------+------------+------------+---------------------+
|    1 | alex |      1995 | 1995-11-11 | 11:11:11   | 2017-11-11 11:11:11 |
|    2 | egon |      1997 | 1997-12-12 | 12:12:12   | 2017-12-12 12:12:12 |
|    3 | wsb  |      1998 | 1998-01-01 | 13:13:13   | 2017-01-01 13:13:13 |
+------+------+-----------+------------+------------+---------------------+
3 rows in set (0.00 sec)
View Code

 

四、数据类型(2)

本节重点

  • 掌握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模式(设置SQL模式:SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
      查询sql的默认模式:select @@sql_mode;)

  

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)

检索:
    尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容

官网解释如下:

验证:

验证之前了解两个函数:

length():查看字节数
char_length():查看字符数

1.char填充空格来满足固定长度,但是在查询时却会很不要脸地删除尾部的空格

(装作自己好像没有浪费过空间一样),然后修改sql_mode让其现出原形。

#创建数据库db5进行测试
mysql> create database db5;
Query OK, 1 row affected (0.00 sec)

#切换到db5
mysql> use db5;
Database changed

#创建t1表,分别指明字段x为char类型,字段y为varchar类型
mysql> create table t1(x char(5),y varchar(4));
Query OK, 0 rows affected (0.51 sec)

#char存放的是5个字符,而varchar存4个字符。注意:你瞅呢后面是2个空格!
mysql> insert into t1 values('你瞅呢  ','你瞅啥 ');
Query OK, 1 row affected (0.10 sec)

#在检索时char很不要脸地将自己浪费的2个字符给删掉了,装的好像自己没浪费过空间一样,而varchar很老实,存了多少,就显示多少
mysql> select x,char_length(x),y,char_length(y) from t1;
+-----------+----------------+------------+----------------+
| x         | char_length(x) | y          | char_length(y) |
+-----------+----------------+------------+----------------+
| 你瞅呢    |              3 | 你瞅啥     |              4 |
+-----------+----------------+------------+----------------+
1 row in set (0.00 sec)

#查看当前mysql的mode模式
mysql> select @@sql_mode;
+--------------------------------------------+
| @@sql_mode                                 |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)

#略施小计,让char现原形
mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.07 sec)

#再次查看mode模式
mysql> select @@sql_mode;
+-------------------------+
| @@sql_mode              |
+-------------------------+
| PAD_CHAR_TO_FULL_LENGTH |
+-------------------------+
1 row in set (0.00 sec)

#原形毕露了吧...
mysql> select x,char_length(x) y,char_length(y) from t1;
+-------------+------+----------------+
| x           | y    | char_length(y) |
+-------------+------+----------------+
| 你瞅呢      |    5 |              4 |
+-------------+------+----------------+
1 row in set (0.00 sec)

# 查看字节数
#char类型:3个中文字符+2个空格=11Bytes
#varchar类型:3个中文字符+1个空格=10Bytes
mysql> select x,length(x),y,length(y) from t1;
+-------------+-----------+------------+-----------+
| x           | length(x) | y          | length(y) |
+-------------+-----------+------------+-----------+
| 你瞅呢      |        11 | 你瞅啥     |        10 |
+-------------+-----------+------------+-----------+
1 row in set (0.00 sec)

 

总结:

#常用字符串系列:char与varchar
注:虽然varchar使用起来较为灵活,但是从整个系统的性能角度来说,char数据类型的处理速度更快,有时甚至可以超出varchar处理速度的50%。因此,用户在设计数据库时应当综合考虑各方面的因素,以求达到最佳的平衡

#其他字符串系列(效率:char>varchar>text)
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列    TINYBLOB BLOB MEDIUMBLOB LONGBLOB 
BINARY系列 BINARY VARBINARY

text:text数据类型用于保存变长的大字符串,可以组多到65535 (2**16 − 1)个字符。
mediumtext:A TEXT column with a maximum length of 16,777,215 (2**24 − 1) characters.
longtext:A TEXT column with a maximum length of 4,294,967,295 or 4GB (2**32 − 1) characters.

  

枚举类型和集合类型

字段的值只能在给定范围中选择,如单选框,多选框

enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female

set 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3...)

#创建表
create table consumer(
    id int,
    name varchar(50),
    sex enum('male','female','other'),
    level enum('vip1','vip2','vip3','vip4'),#在指定范围内,多选一
    fav set('play','music','read','study') #在指定范围内,多选多
);

#插入2条记录
insert into consumer values
    (1,'高圆圆','female','vip2','read,study'),
    (2,'赵丽颖','female','vip4','play');

#查看表记录
mysql> select * from consumer;
+------+-----------+--------+-------+------------+
| id   | name      | sex    | level | fav        |
+------+-----------+--------+-------+------------+
|    1 | 高圆圆    | female | vip2  | read,study |
|    2 | 赵丽颖    | female | vip4  | play       |
+------+-----------+--------+-------+------------+
2 rows in set (0.00 sec)

 

五、完整性约束

本节重点:

  • not null 与 default

  • unique

  • primary

  • auto_increment

  • foreign key

 

一、介绍

约束条件与数据类型的宽度一样,都是可选参数

作用:用于保证数据的完整性和一致性

主要分为:

PRIMARY KEY (PK)    #标识该字段为该表的主键,可以唯一的标识记录
FOREIGN KEY (FK)    #标识该字段为该表的外键
NOT NULL    #标识该字段不能为空
UNIQUE KEY (UK)    #标识该字段的值是唯一的
AUTO_INCREMENT    #标识该字段的值自动增长(整数类型,而且为主键)
DEFAULT    #为该字段设置默认值

UNSIGNED #无符号
ZEROFILL #使用0填充

说明:

#1. 是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值
#2. 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值
sex enum('male','female') not null default 'male'

#必须为正值(无符号) 不允许为空 默认是20
age int unsigned NOT NULL default 20 
# 3. 是否是key
主键 primary key
外键 foreign key
索引 (index,unique...)

 

二、not null 与default

是否可空,null表示空,非字符串
not null - 不可空
null - 可空

默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值

create table tb1(
    nid int not null default 2,
    num int not null
);

 

验证1:默认值可以为空

#id字段默认可以为空
mysql> create table t11(id int);
Query OK, 0 rows affected (0.31 sec)

#查看表结构
mysql> desc t11;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

##给t11表插一个空的值
mysql> insert into t11 values();
Query OK, 1 row affected (0.10 sec)

#查询结果如下
mysql> select * from t11;
+------+
| id   |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

 

验证2:设置not null,插入值时不能为空

#设置字段id不为空
mysql> create table t12(id int not null);
Query OK, 0 rows affected (0.28 sec)

#查看表结构
mysql> desc t12;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

#不能插入空
mysql> insert into t12 values();
ERROR 1364 (HY000): Field 'id' doesn't have a default value

注意:如果插入成功,请查看当前mode模式是否为PAD_CHAR_TO_FULL_LENGTH

如果是,请手动修改为默认值

#修改为默认值
mysql> SET sql_mode = 'NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES';
Query OK, 0 rows affected, 1 warning (0.00 sec)

#再次查看mode
mysql> select @@sql_mode;
+--------------------------------------------+
| @@sql_mode                                 |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)

#再次插入空值,就会报错!
mysql> insert into t12 values();
ERROR 1364 (HY000): Field 'id' doesn't have a default value

 

STRICT_TRANS_TABLES表示严格模式,如果语句中有非法或丢失值,则会出现错误。语句被放弃并滚动!

 

验证3:设置id字段默认值

设置id字段有默认值后,则无论id字段是null还是not null,都可以插入空,插入空默认填入default指定的默认值

第一种情况

#给id字段设置默认值
mysql> create table t13(id int default 1);
Query OK, 0 rows affected (0.27 sec)

#查看表结构
mysql> desc t13;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | 1       |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

#插入一个空值
mysql> insert into t13 values();
Query OK, 1 row affected (0.09 sec)

#查看表记录
mysql> select * from t13;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

第二种情况

#给id字段设置默认值,不允许为空
mysql> create table t14(id int not null default 2);
Query OK, 0 rows affected (0.26 sec)

#查看表结构,Null为No,表示不允许为空
mysql> desc t14;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | 2       |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

#插入一条空记录
mysql> insert into t14 values();
Query OK, 1 row affected (0.36 sec)

#查看表记录
mysql> select * from t14;
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)

 

小练习:

创建学生表student2,设置每个字段的约束条件。

#创建表
create table student2(
    id int not null,
    name varchar(50) not null,
    age int(3) unsigned not null default 18,
    sex enum('male','female') default 'male',
    fav set('smoke','drink','tangtou') default 'drink,tangtou'
);

#插入一条记录,只插入了not null约束条件字段对应的值
mysql> insert into student2(id,name) values(1,'张三');
Query OK, 1 row affected (0.09 sec)

#查询结果如下
mysql> select * from student2;
+----+--------+-----+------+---------------+
| id | name   | age | sex  | fav           |
+----+--------+-----+------+---------------+
|  1 | 张三   |  18 | male | drink,tangtou |
+----+--------+-----+------+---------------+
1 row in set (0.00 sec)

 

3、unique

中文翻译:不同的。在mysql中称为单列唯一

 

举例说明:创建公司部门表(每个公司都有唯一的一个部门)。

验证之前重复插入记录的操作是可行的,但是不符合场景

#创建表
create table department(
    id int,
    name char(10)
);

#插入2条记录,name值是一样的
mysql> insert into department values(1,'IT'),(2,'IT');
Query OK, 2 rows affected (0.09 sec)
Records: 2  Duplicates: 0  Warnings: 0

#查看表记录
mysql> select * from department;
+------+------+
| id   | name |
+------+------+
|    1 | IT   |
|    2 | IT   |
+------+------+
2 rows in set (0.00 sec)

发现: 同时插入两个IT部门也是可以的,但这是不合理的,所以我们要设置name字段为unique 解决这种不合理的现象。

接下来,使用约束条件unique,来对公司部门的字段进行设置。

第一种创建unique的方式

例子1:

#删除已经存在的表
mysql> drop table department;
Query OK, 0 rows affected (0.19 sec)

#创建表
create table department(
    id int,
    name char(10) unique
);

#插入2条记录,name是一样的会报错
mysql> insert into department values(1,'it'),(2,'it');
ERROR 1062 (23000): Duplicate entry 'it' for key 'name'

例子2:

#删除已经存在的表
mysql> drop table department;
Query OK, 0 rows affected (0.45 sec)

#创建表
create table department(
    id int unique,
    name char(10) unique
);

#插入2条记录
mysql> insert into department values(1,'it'),(2,'sale');
Query OK, 2 rows affected (0.09 sec)
Records: 2  Duplicates: 0  Warnings: 0

 

第二种创建unique的方式

#删除已经存在的表
mysql> drop table department;
Query OK, 0 rows affected (0.18 sec)

#创建表
create table department(
    id int,
    name char(10) ,
    unique(id),
    unique(name)
);

#插入2条记录
mysql> insert into department values(1,'it'),(2,'sale');
Query OK, 2 rows affected (0.09 sec)
Records: 2  Duplicates: 0  Warnings: 0

 

联合唯一:

#创建services表
create table services(
    id int,
    ip char(15),
    port int,
    unique(id),
    unique(ip,port)
);

#查看表结构,UNI表示唯一,MUL表示联合
mysql> desc services;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  | UNI | NULL    |       |
| ip    | char(15) | YES  | MUL | NULL    |       |
| port  | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#插入3条记录
#联合唯一,只要两列记录,有一列不同,既符合联合唯一的约束
insert into services values
    (1,'192,168,11,23',80),
    (2,'192,168,11,23',81),
    (3,'192,168,11,25',80);

#查看表记录
mysql> select * from services;
+------+---------------+------+
| id   | ip            | port |
+------+---------------+------+
|    1 | 192,168,11,23 |   80 |
|    2 | 192,168,11,23 |   81 |
|    3 | 192,168,11,25 |   80 |
+------+---------------+------+
3 rows in set (0.00 sec)

#插入一条记录,ip和port是已经存在的。那么就导致插入失败!
mysql> insert into services values (4,'192,168,11,23',80);
ERROR 1062 (23000): Duplicate entry '192,168,11,23-80' for key 'ip'

 

4.primary key

一个表中可以:

单列做主键
多列做主键(复合主键)

约束:等价于 not null unique,字段的值不为空且唯一

存储引擎默认是(innodb):对于innodb存储引擎来说,一张表必须有一个主键。

单列主键

#删除已存在的表
mysql> drop table t14;
Query OK, 0 rows affected (0.43 sec)

# 创建t14表,为id字段设置主键,唯一的不同的记录
create table t14(
    id int primary key,
    name char(16)
);

#插入2条记录
insert into t14 values
(1,'xiaoma'),
(2,'xiaohong');

#插入的id是已存在的,报错!
mysql> insert into t14 values(2,'wxxx');
ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'

 

not null + unique的化学反应,相当于给id设置primary key

#创建表
create table t15(
    id int not null unique,
    name char(16)
);

#查看表结构,PRI表示主键
mysql> desc t15;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | NO   | PRI | NULL    |       |
| name  | char(16) | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

注意:一个表中,只能有一个主键

 

复合主键

验证复合主键的使用

#创建表
create table t16(
    ip char(15),
    port int,
    primary key(ip,port)
);

#插入2条记录
insert into t16 values
('1.1.1.2',80),
('1.1.1.2',81);

#查看表结构,发现有2个PRI,但是它是属于一个主键'key'
mysql> desc t16;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| ip    | char(15) | NO   | PRI | NULL    |       |
| port  | int(11)  | NO   | PRI | NULL    |       |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)
View Code

 

5.auto_increment

约束:约束的字段为自动增长,约束的字段必须同时被key约束

(重点)验证:

不指定id,则自动增长

#创建student
create table student(
    id int primary key auto_increment,
    name varchar(20),
    sex enum('male','female') default 'male'
);

#查看表结构
mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum('male','female') | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

#插入2条记录,不指定id
mysql> insert into student(name) values ('老白'),('小白');
Query OK, 2 rows affected (0.09 sec)
Records: 2  Duplicates: 0  Warnings: 0

#查看表记录,发现id自增了
mysql> select * from student;
+----+--------+------+
| id | name   | sex  |
+----+--------+------+
|  1 | 老白   | male |
|  2 | 小白   | male |
+----+--------+------+
2 rows in set (0.00 sec)

 

指定id

#指定id为4
mysql> insert into student values(4,'asb','female');
Query OK, 1 row affected (0.36 sec)

#指定id为7
mysql> insert into student values(7,'wsb','female');
Query OK, 1 row affected (0.10 sec)

#查看表记录
mysql> select * from student;
+----+--------+--------+
| id | name   | sex    |
+----+--------+--------+
|  1 | 老白   | male   |
|  2 | 小白   | male   |
|  4 | asb    | female |
|  7 | wsb    | female |
+----+--------+--------+
4 rows in set (0.00 sec)

#再次插入一条不指定id的记录,会在之前的最后一条记录继续增长
mysql> insert into student(name) values ('大白');
Query OK, 1 row affected (0.09 sec)

#查看表记录
mysql> select * from student;
+----+--------+--------+
| id | name   | sex    |
+----+--------+--------+
|  1 | 老白   | male   |
|  2 | 小白   | male   |
|  4 | asb    | female |
|  7 | wsb    | female |
|  8 | 大白   | male   |
+----+--------+--------+
5 rows in set (0.00 sec)

 

对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增长

#清空表记录,注意,这不是删除表
mysql> delete from student;
Query OK, 5 rows affected (0.40 sec)

#查看表记录,发现为空
mysql> select * from student;
Empty set (0.00 sec)

#插入一条不指定id的记录
mysql> insert into student(name) values('ysb');
Query OK, 1 row affected (0.10 sec)

#查看表记录,发现id是9。因为上面表的最后一个id伪8
mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  9 | ysb  | male |
+----+------+------+
1 row in set (0.00 sec)

#truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,并重置自动增长值,在删除大表时用它
mysql> truncate student;
Query OK, 0 rows affected (0.28 sec)

#重新插入一条不指定id的记录
mysql> insert into student(name) values('xiaobai');
Query OK, 1 row affected (0.10 sec)

查看表记录,发现id为1
mysql> select * from student;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | xiaobai | male |
+----+---------+------+
1 row in set (0.00 sec)

 

auto_increment_increment和 auto_increment_offset(只做了解)

查看可用的 开头auto_inc的词
mysql> show variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
rows in set (0.02 sec)
# 步长auto_increment_increment,默认为1
# 起始的偏移量auto_increment_offset, 默认是1

 # 设置步长 为会话设置,只在本次连接中有效
 set session auto_increment_increment=5;

 #全局设置步长 都有效。
 set global auto_increment_increment=5;

 # 设置起始偏移量
 set global  auto_increment_offset=3;

#强调:If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 
翻译:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值会被忽略 

# 设置完起始偏移量和步长之后,再次执行show variables like'auto_inc%';
发现跟之前一样,必须先exit,再登录才有效。

mysql> show variables like'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 5     |
| auto_increment_offset    | 3     |
+--------------------------+-------+
rows in set (0.00 sec)

#因为之前有一条记录id=1
mysql> select * from student;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | xiaobai | male |
+----+---------+------+
row in set (0.00 sec)
# 下次插入的时候,从起始位置3开始,每次插入记录id+5
mysql> insert into student(name) values('ma1'),('ma2'),('ma3');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from student;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | xiaobai | male |
|  3 | ma1     | male |
|  8 | ma2     | male |
| 13 | ma3     | male |
+----+---------+------+

auto_increment_increment和 auto_increment_offset
View Code

注意:auto_increment_increment和 auto_increment_offset不要随意更改,保持默认就可以了。改完之后,要还原回来!

 

清空表区分delete和truncate的区别:

delete from t1; #如果有自增id,新增的数据,仍然是以删除前的最后一样作为起始。

truncate table t1;数据量大,删除速度比上一条快,且直接从零开始。

 

6.foreign key

快速理解foreign key

之前创建表的时候都是在一张表中添加记录,比如如下表:

公司有3个部门,但是有1个亿的员工,那意味着部门这个字段需要重复存储,部门名字越长,越浪费。
这个时候,解决方法:

我们完全可以定义一个部门表
然后让员工信息表关联该表,如何关联,即foreign key

我们可以将上表改为如下结构:

此时有两张表,一张是employee表,简称emp表(关联表,也就主表)。一张是department表,简称dep表(被关联表,也叫从表)。

创建两张表操作:

#1.创建表时先创建被关联表,再创建关联表
# 先创建被关联表(dep表)
create table dep(
    id int primary key,
    name varchar(20) not null,
    descripe varchar(20) not null
);

#再创建关联表(emp表)
create table emp(
    id int primary key,
    name varchar(20) not null,
    age int not null,
    dep_id int,
    constraint fk_dep foreign key(dep_id) references dep(id) 
);

#2.插入记录时,先往被关联表中插入记录,再往关联表中插入记录

insert into dep values
(1,'IT','IT技术有限部门'),
(2,'销售部','销售部门'),
(3,'财务部','花钱太多部门');

insert into emp values
(1,'zhangsan',18,1),
(2,'lisi',19,1),
(3,'egon',20,2),
(4,'yuanhao',40,3),
(5,'alex',18,2);

3.删除表
#按道理来说,删除了部门表中的某个部门,员工表的有关联的记录相继删除。
mysql> delete from dep where id=3;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`db5`.`emp`, CONSTRAINT `fk_dep` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`))

#但是先删除员工表的记录之后,再删除当前部门就没有任何问题
mysql> delete from emp where dep_id='3';
Query OK, 1 row affected (0.36 sec)

#查看员工表记录
mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  19 |      1 |
|  3 | egon     |  20 |      2 |
|  5 | alex     |  18 |      2 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)

#删掉部门表中id为3的记录,也就是财务部
mysql> delete from dep where id=3;
Query OK, 1 row affected (0.09 sec)

#查看部分表,发现财务部没有了
mysql> select * from dep;
+----+-----------+----------------------+
| id | name      | descripe             |
+----+-----------+----------------------+
|  1 | IT        | IT技术有限部门       |
|  2 | 销售部    | 销售部门             |
+----+-----------+----------------------+
2 rows in set (0.00 sec)

 

上面的删除表记录的操作比较繁琐,按道理讲,裁掉一个部门,该部门的员工也会被裁掉。其实呢,在建表的时候还有个很重要的内容,叫同步删除,同步更新

接下来将刚建好的两张表全部删除,先删除关联表(emp),再删除被关联表(dep)

接下来:
重复上面的操作建表
注意:在关联表中加入
on delete cascade #同步删除
on update cascade #同步更新

修改emp表:

#删除已存在的表emp和dep
mysql> drop table emp;
Query OK, 0 rows affected (0.19 sec)

mysql> drop table dep;
Query OK, 0 rows affected (0.19 sec)

#创建表dep,结构还是保持不变
create table dep(
    id int primary key,
    name varchar(20) not null,
    descripe varchar(20) not null
);

#创建表emp,结构改变了
create table emp(
    id int primary key,
    name varchar(20) not null,
    age int not null,
    dep_id int,
    constraint fk_dep foreign key(dep_id) references dep(id) 
    on delete cascade 
    on update cascade 
);

#重新插入记录
insert into dep values
(1,'IT','IT技术有限部门'),
(2,'销售部','销售部门'),
(3,'财务部','花钱太多部门');

insert into emp values
(1,'zhangsan',18,1),
(2,'lisi',19,1),
(3,'egon',20,2),
(4,'yuanhao',40,3),
(5,'alex',18,2);

 

接下来的操作,就复合我们正常的生活中的情况了。

#再去删被关联表(dep)的记录,关联表(emp)中的记录也跟着删除
mysql> delete from dep where id=3;
Query OK, 1 row affected (0.09 sec)

#查看表记录,发现财务部删除了
mysql> select * from dep;
+----+-----------+----------------------+
| id | name      | descripe             |
+----+-----------+----------------------+
|  1 | IT        | IT技术有限部门       |
|  2 | 销售部    | 销售部门             |
+----+-----------+----------------------+
2 rows in set (0.00 sec)

#查看员工表记录,dep_id为3的记录都没有了
mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  19 |      1 |
|  3 | egon     |  20 |      2 |
|  5 | alex     |  18 |      2 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)

#再去更改被关联表(dep)的记录,关联表(emp)中的记录也跟着更改
#将部门表中的销售部id改成222
mysql> update dep set id=222 where id=2;
Query OK, 1 row affected (0.12 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#查看部门表,id更改了
mysql> select * from dep;
+-----+-----------+----------------------+
| id  | name      | descripe             |
+-----+-----------+----------------------+
|   1 | IT        | IT技术有限部门       |
| 222 | 销售部    | 销售部门             |
+-----+-----------+----------------------+
2 rows in set (0.00 sec)

#同时,员工表对应的dep_id也被更改了
mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  19 |      1 |
|  3 | egon     |  20 |    222 |
|  5 | alex     |  18 |    222 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)

注意: 

constraint 英文表示约束,后面的名字可以随便。约定成俗,以fk_开头,后面是关联的字段
references 英文表示标记,后面是被关键表。dep(id),表示dep表里面的id字段

 

外键的使用条件:

1.两个表必须是InnoDB表,MyISAM表暂时不支持外键

2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显式建立;

3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以;

外键的好处:

可以使得两张表关联,保证数据的一致性和实现一些级联操作。

 

今日作业:

请创建如下表,并创建相关约束

 关系图如下:

 

答案:

注意,建表顺序不能乱

班级表

CREATE TABLE `class` (
  `cid` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '班级id',
  `caption` varchar(32) DEFAULT NULL COMMENT '班级', 
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='班级表';
View Code

学生表

CREATE TABLE `student` (
  `sid` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '学生id',
  `sname` varchar(32) DEFAULT NULL,
  `gender` enum('','') DEFAULT '' COMMENT '性别',
  `class_id` int(11) unsigned NOT NULL COMMENT '班级id',
  PRIMARY KEY (`sid`),
  constraint fk_class foreign key(class_id) references class(cid)
  on delete cascade
  on update cascade
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生表';
View Code

老师表

CREATE TABLE `teacher` (
  `tid` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '老师id',
  `tname` varchar(32) NOT NULL COMMENT '老师名字',
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='老师表';
View Code

课程表

CREATE TABLE `course` (
  `cid` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '课程id',
  `cname` varchar(32) NOT NULL COMMENT '课程名',
  `tearch_id` int(11) unsigned NOT NULL COMMENT '老师id',
  PRIMARY KEY (`cid`),
  constraint fk_tearch foreign key(tearch_id) references teacher(tid)
  on delete cascade 
  on update cascade 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='课程表';
View Code

成绩表

CREATE TABLE `score` (
  `sid` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '成绩id',
  `student_id` int(11) unsigned NOT NULL COMMENT '学生id',
  `corse_id` int(11) unsigned NOT NULL COMMENT '课程id',
  `number` int(11) NOT NULL DEFAULT '0' COMMENT '成绩',
  PRIMARY KEY (`sid`),
  constraint fk_score_student foreign key(student_id) references student(sid)
  on delete cascade 
  on update cascade,
  constraint fk_score_corse foreign key(corse_id) references course(cid)
  on delete cascade 
  on update cascade
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='成绩表';
View Code

 

posted @ 2018-06-12 15:24  肖祥  阅读(676)  评论(0编辑  收藏  举报