数据库mysql

一、前戏:

在学习Mysql之前,我们先来想一下一开始做的登录注册案例,当时我们把用户的信息保存到一个文件中:

#用户名 |密码
root|123321 alex|123123

上面文件内容的规则是我自己定义的,你要想用我这个程序,必须按照我的规则去执行,但凡不是这个规则,就没有交流的余地。

在一开始的时候文件格式的规定是没有规范的,后面学到模块的时候逐渐知道了目录规则,我们会把文件放到db目录下。

类似下面目录结构:

 

对于上面db目录中,是可以存放多个文件的,并且文件中可以有多行数据。

 

那么问大家一个问题,如果说上面那个软件是我写好的,在一台服务器或者一台机器上安装了我写好的软件。

现在有张三和李四两个人都安装了我这个软件,张三注册了一个用户,李四也注册了一个用户,那么自己注册的用户应该是自己用的。那么这两个用户是不共享的,

所以这个软件证明我写的不太好,它不能共享,这种类似单机的软件是不好的。

然后呢,我现在将我写的这个软件中目录修改一下,将db目录移除。现在将单机程序(自己的DB)改变成也是单机程序(公用DB)。

 

那么之前给大家介绍过,凡是交互操作,是离不开scoket的,那么现在我这边有个公用DB和一个scoket服务端,然后在张三和李四那边有scoket客户端。张三和李四此时输入用户名和密码,现在我这边scoket服务端某个目录接收用户输入的用户名和密码,看一下该用户名存在不存在,如果存在返回true,如果不存在返回false。也就是说重点的内容我们把db目录放到某台服务器上。

那么上面这个例子呢,其实就给大家慢慢的引出来mysql了,mysql呢其实就一个软件,这个软件安装到某台电脑上或者某台服务器上,那么现在只要我告诉它创建一个文件目录或者创建文件,那么mysql就自动帮我们创建了,比如说我们再在文件中添加一条数据,那么它也帮我们完成。

 

总结一句话:其实mysql就是用于管理我们的文件的一个软件。

 

那么对于mysql这个软件来说有两个软件

复制代码
---服务器软件
     - socket服务端
     - 本地文件操作
   - 解析指令(mysql语句) ---客户端软件 - socket客户端 - 发送指令
   - 解析指令(mysql语句)
复制代码

解释:

对于服务器软件中的socket服务器是一直开着,客户端得需要连接,并且还有创建文件、删除文件等等的操作

对于客户端软件中的scoket客户端,我们得需要发送指令去命令scoket服务端对文件进行操作。

 

大家应该知道ftp的项目,上传项目和下载项目的命令是不一样的。那么对于mysql中的客户端和服务端也会有些指令的操作,那么在这两个端中应该是有解析指令的过程,这个指令只有mysql这个软件知道,这种指令就是mysql语句。

再想想我们写的html、css、js.这些好比就是我们客户端写好的语法,然后浏览器充当了服务端的角色去解析我们的的语法,最后来渲染出来结果。

 

接下来我们要学习这些技能:

- 安装 服务端和客户端
- 连接
- 学习SOL语句规则:命令服务端做任何的操作

 

 

 

二、概述

什么是数据(Data)

复制代码
描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字、图片,图像、声音、语言等,数据由多种表现形式,它们都可以经过数字化后存入计算机

在计算机中描述一个事物,就需要抽取这一事物的典型特征,组成一条记录,就相当于文件里的一行内容,如:

1 xiaomage,male,18,1999,山东,计算机系,2017,oldboy
复制代码

 

单纯的一条记录并没有任何意义,如果我们按逗号作为分隔,依次定义各个字段的意思,相当于定义表的标题

这样通过表格我们很清楚的知道了某人的详细信息。

 

什么是数据库(DataBase,简称DB)

数据库即存放数据的仓库,只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的

过去人们将数据存放在文件柜里,现在数据量庞大,已经不再适用

数据库是长期存放在计算机内、有组织、可共享的数据即可。

数据库中的数据按一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种 用户共享

 

什么是数据库管理系统(DataBase Management System)

在了解了Data与DB的概念后,如何科学地组织和存储数据,如何高效获取和维护数据成了关键

这就用到了一个系统软件---数据库管理系统

如MySQL、Oracle、SQLite、Access、MS SQL Server

mysql主要用于大型门户,例如搜狗、新浪等,它主要的优势就是开放源代码,因为开放源代码这个数据库是免费的,他现在是甲骨文公司的产品。
oracle主要用于银行、铁路、飞机场等。该数据库功能强大,软件费用高。也是甲骨文公司的产品。
sql server是微软公司的产品,主要应用于大中型企业,如联想、方正等。

数据库服务器、数据管理系统、数据库、表与记录的关系(重点理解!!!)

记录:1 xxx 324245234 22(多个字段的信息组成一条记录,即文件中的一行内容)

表:student,scholl,class_list(即文件)

数据库:oldboy_stu(即文件夹)

数据库管理系统:如mysql(是一个软件)

数据库服务器:一台计算机(对内存要求比较高)

 

总结:

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

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

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

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

 

 

 

 

三、安装和基本管理

 

本节掌握内容:

  • mysql的安装、启动

  • mysql破解密码

  • 统一字符编码

 

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司。MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。

 

mysql是什么?

mysql就是一个基于socket编写的C/S架构的软件

数据库管理软件分类

复制代码
分两大类:
  关系型:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql语句通用
  非关系型:mongodb,redis,memcache

可以简单的理解为:
    关系型数据库需要有表结构
    非关系型数据库是key-value存储的,没有表结构
复制代码

 

mysql的下载安装

想要使用MySQL来存储并保存数据,则需要做几件事情:

  a. 安装MySQL服务端
  b. 安装MySQL客户端
  b. 【客户端】连接【服务端】
  c. 【客户端】发送命令给【服务端MySQL】服务的接受命令并执行相应操作(增删改查等)

下载地址:

 

window版本

1、官网去下载

 

2、针对操作系统的不同下载不同的版本

 

 

3.解压

如果想要让MySQL安装在指定目录,那么就将解压后的文件夹移动到指定目录,如:C:\mysql-5.6.40-winx64

4.添加环境变量

【右键计算机】--》【属性】--》【高级系统设置】--》【高级】--》【环境变量】--》【在第二个内容框中找到 变量名为Path 的一行,双击】 --> 【将MySQL的bin目录路径追加到变值值中,用 ; 分割】

 

5.初始化

 

1
mysqld --initialize-insecure

 

 6.启动mysql服务

mysqld #启动MySQL服务

 

7.启动mysql客户端并连接mysql服务端(新开一个cmd窗口)

mysql -u root -p # 连接MySQL服务器

 

上一步解决了一些问题,但不够彻底,因为在执行【mysqd】启动MySQL服务器时,当前终端会被hang住,那么做一下设置即可解决此问题,即将MySQL服务制作成windows服务

复制代码
注意:--install前,必须用mysql启动命令的绝对路径
# 制作MySQL的Windows服务,在终端执行此命令:
"c:\mysql-5.6.40-winx64\bin\mysqld" --install

# 移除MySQL的Windows服务,在终端执行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --remove


注册成服务之后,以后再启动和关闭MySQL服务时,仅需执行如下命令:
# 启动MySQL服务
net start mysql

# 关闭MySQL服务
net stop mysql
复制代码

 

windows下登录设置密码

 

打开终端,输入mysql

输入mysql提供的函数:select user(); # 查看当前登录的账号

当前登录的默认账号为ODBC@localhost

 

 

如果想切到root账号登录

执行命令:

mysql -uroot -p

再查看当前用户:

select user();

管理员为root(拥有最高权限,管理员账号),密码为空,以无密码的方式登录了管理员账号,是非常危险的一件事情,所以要为管理员账号设置密码

设置管理员root账号密码为123

C:\Users\mjj>mysqladmin -uroot -p password "123"  #设置初始密码 由于原密码为空,因此-p可以不用

ps:⚠️不用管它。翻译为:在命令行界面使用密码不安全,暴露在终端当中。

 

然后再登录账号,不输入密码则会出现如下结果:

 再次执行如下操作:

 

再查看一下当前登录的账号:

 

如果想将原始密码123,设置新密码为456

C:\Users\mjj>mysqladmin -uroot -p"123" password "456"  #修改mysql密码,因为已经有密码了,所以必须输入原密码才能设置新密码

 依次执行如下操作:

mysql -uroot -p456

select user();

 

密码忘记——破解密码

 

跳过授权方式,直接登录!!

0.以管理员身份打开cmd

 

2.停掉mysql服务端

C:\WINDOWS\system32>net stop mysql
MySQL 服务正在停止.
MySQL 服务已成功停止。

3.执行如下命令跳过授权表

复制代码
#跳过授权表
C:\WINDOWS\system32>mysqld --skip-grant-tables
2018-06-09 17:12:38 0 [Warning] Insecure configuration for --secure-file-priv: Current value does not restrict location of generated files. Consider setting it to a valid, non-empty path.
2018-06-09 17:12:38 0 [Note] mysqld (mysqld 5.6.40) starting as process 6052 ...4.
复制代码

 4.再次查看

5. 现在可以任意的更改密码,执行如下命令

 update mysql.user set authentication_string =password('') where User='root'; 

 

6.刷新权限,执行命令

flush privileges;

7.退出mysql。执行命令:exit,

 

8.让用户去加载权限,以管理员身份进入cmd,查看当前mysql进程

1
tasklist |findstr mysql  #查看当前mysql的进程

 

9.杀死当前的进程,执行如下命令

taskkill /F /PID 6052  # 杀死当前的进程pid

10.再次执行如下操作,还原

 

统一字符编码

进入mysql客户端,执行\s

 

 

为了统一字符编码,请执行如下操作:

(1)my.ini文件是mysql的配置文件,

在C:\mysql-5.6.40-winx64文件下创建my.ini文件

(2)将如下代码拷贝保存。

    

复制代码
#mysql5.5以上:修改方式为
    [mysqld]
    character-set-server=utf8
    collation-server=utf8_general_ci
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8
复制代码

 

(3)以管理员身份重启服务,执行如下命令 

复制代码
C:\Windows\system32>net stop MySQL
MySQL 服务正在停止..
MySQL 服务已成功停止。

C:\Windows\system32>net start MySQL
MySQL 服务正在启动 .
MySQL 服务已经启动成功。
复制代码

(4)在cmd中输入mysql进入mysql环境,执行\s,显示如下信息,表示成功

 

 

 

四、初始mysql语句

 

本节课先对mysql的基本语法初体验。

操作文件夹(库)

create database db1 charset utf8;

# 查看当前创建的数据库
show create database db1;
# 查看所有的数据库
show databases;

alter database db1 charset gbk;

drop database db1;

 

 

 

操作文件(表)

use db1; #切换文件夹

select database(); #查看当前所在文件夹

create table t1(id int,name char);

查 

复制代码
#查看当前的这张t1表
show create table t1;

# 查看所有的表
show tables;

# 查看表的详细信息
desc t1;
复制代码

# modify修改的意思
alter table t1 modify name char(6);
# 改变name为大写的NAME
alter table t1 change name NAMA char(7);

# 删除表
drop table t1;

 

 

操作文件内容(记录)

 增

# 插入一条数据,规定id,name数据leilei
insert t1(id,name) values(1,"mjj01"),(2,"mjj02"),(3,"mjj03");

 查

select id from db1.t1;
select id,name from db1.t1;
select * from db1.t1; 

update db1.t1 set name='zhangsan';
update db1.t1 set name='alex' where id=2;

 删

delete from t1;
delete from t1 where id=2;

 

 

五、库的操作

 

本节重点:

  • 掌握库的增删改查

 

一、系统数据库

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

show databases;

nformation_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息、列信息、权限信息、字符信息等
performance_schema: MySQL 5.5开始新增一个数据库:主要用于收集数据库服务器性能参数,记录处理查询请求时发生的各种事件、锁等现象
mysql: 授权库,主要存储系统用户的权限信息
test: MySQL数据库系统自动创建的测试数据库

二、创建数据库

1、求救语法:

help create database;

2、创建数据库语法

CREATE DATABASE 数据库名 charset utf8;

3、数据库命名规则:

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

三、数据库相关操作

复制代码
#查看数据库
show databases;
#查看当前库
show create database db1;
#查看所在的库
select database();

#选择数据库
use 数据库名

#删除数据库
DROP DATABASE 数据库名;
# 修改数据库
alter database db1 charset utf8;
复制代码

 

四、了解内容

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

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

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

 

 

 

六、表的操作

06-表的操作

 

本节掌握

  • 存储引擎介绍(了解)
  • 表的增删改查

一、存储引擎(了解)

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

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

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

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

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

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

 

二、mysql支持的存储引擎

mysql> show engines\G;# 查看所有支持的引擎
mysql> show variables like 'storage_engine%'; # 查看正在使用的存储引擎

 

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

4、Memory 存储引擎

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

5、Infobright 存储引擎

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

6、NTSE 存储引擎

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

7、BLACKHOLE

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

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

 

指定表类型/存储引擎

create table t1(id int)engine=innodb;# 默认不写就是innodb

 

小练习:

创建四张表,分别使用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.02 sec)

mysql>

复制代码

 

(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.16 sec)
复制代码

(3)查看表的详细结构

复制代码
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 |
+------+-------+------+
复制代码

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

# 这就是复制表的操作(既复制了表结构,又复制了记录)
mysql> create table b1 select * from db2.a1;
Query OK, 2 rows affected (0.03 sec)

(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.05 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.02 sec)

#查看表结构中的数据,发现是空数据
mysql> select * from b2;
Empty set (0.00 sec)
复制代码

 

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

复制代码
mysql> create table b3 like db2.a1;
Query OK, 0 rows affected (0.01 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.02 sec)

mysql> select * from db3.b3;
Empty set (0.00 sec)
复制代码

 

7.删除表:

drop table 表名;

 

 

七、数据类型

 

介绍

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

详细参考链接: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[(m)] [unsigned] [zerofill]

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

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



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

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



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

 

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

复制代码
============有符号tinyint==============
# 创建数据库db4
create database db4 charset utf8;

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

# 创建t1 规定x字段为tinyint数据类型(默认是有符号的)
mysql> create table t1(x tinyint);

# 验证,插入-1这个数
mysql>   insert into t1 values(-1);

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

#执行如下操作,会发现报错。因为有符号范围在(-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);

# 报错,超出范围
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.00 sec)
复制代码

 

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

复制代码
mysql> create table t3(id int(1) unsigned);

#插入255555记录也是可以的
mysql> insert into t3 values(255555);

mysql> select * from t3;
+--------+
| id     |
+--------+
| 255555 |
+--------+
ps:以上操作还不能够验证,再来一张表验证用zerofill 用0填充

# zerofill 用0填充
mysql> create table t4(id int(5) unsigned zerofill);


mysql> insert into t4 value(1);
Query OK, 1 row affected (0.00 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类型建表:
mysql> create table t5(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
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.03 sec)

#2验证DOUBLE类型建表:
mysql> create table t6(x double(255,30)); #建表成功
Query OK, 0 rows affected (0.03 sec)

#3验证deimal类型建表:
mysql> create table t7(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t7(x decimal(66,30));
ERROR 1426 (42000): Too big precision 66 specified for column 'x'. Maximum is 65.
mysql> create table t7(x decimal(65,30)); #建表成功
Query OK, 0 rows affected (0.00 sec)
复制代码

验证三种类型的精度:

复制代码
# 分别对三张表插入相应的记录
mysql> insert into t5 values(1.1111111111111111111111111111111);#小数点后31个1
Query OK, 1 row affected (0.01 sec)

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

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

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

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

mysql> select * from t7; #精度始终准确,d为30,于是只留了30位小数
+----------------------------------+
| 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

 

复制代码
mysql> create table t8(born_year year);#无论year指定何种宽度,最后都默认是year(4)
Query OK, 0 rows affected (0.03 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.01 sec) mysql> insert into t8 values -> (1905), -> (2018); Query OK, 2 rows affected (0.00 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.06 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.14 sec)

# 调用mysql自带的now()函数,获取当前类型指定的时间 如下结构 mysql> insert into t9 values(now(),now(),now()); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> select * from t9; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2018-06-09 | 09:35:20 | 2018-06-09 09:35:20 | +------------+----------+---------------------+ 1 row in set (0.00 sec)
复制代码

 

3、timestamp(了解即可)

 

复制代码
mysql>  create table t10(time timestamp);
Query OK, 0 rows affected (0.06 sec)

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

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

mysql>  select * from t10;
+------+
| time |
+------+
| NULL |
| NULL |
+------+

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

mysql> select * from t10;
+---------------------+
| time                |
+---------------------+
| 2018-06-09 09:44:48 |
+---------------------+
1 row in set (0.01 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语句中没有指定该列的更新值,则默认更新为当前时间。
复制代码

 

 

注意事项

 

复制代码
============注意啦,注意啦,注意啦===========
#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 |
+------+
复制代码

 

 

综合练习:

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

 

复制代码
mysql> create table student(
    -> id int,
    -> name varchar(20),
    -> born_year year,
    -> birth date,
    -> class_time time,
    -> reg_time datetime
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> 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");
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

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)
复制代码

 

 

 

八、数据类型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让其现出原形。

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

# char存放的是5个字符,而varchar存4个字符
mysql>  insert into t1 values('你瞅啥 ','你瞅啥 ');
Query OK, 1 row affected (0.01 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.02 sec)

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

#查看当前mysql的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.02 sec)
复制代码

总结:

 View Code

 

 

枚举类型和集合类型

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

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

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

复制代码
mysql> 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') #在指定范围内,多选多
    -> );
Query OK, 0 rows affected (0.03 sec)


mysql> insert into consumer values
    -> (1,'赵云','male','vip2','read,study'),
    -> (2,'赵云2','other','vip4','play');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from consumer;
+------+---------+-------+-------+------------+
| id   | name    | sex   | level | fav        |
+------+---------+-------+-------+------------+
|    1 | 赵云    | male  | vip2  | read,study |
|    2 | 赵云2   | other | 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 defalut 2,
    num int not null

);

 

验证1:

 

 默认值可以为空

 

 

验证2:

 设置not null,插入值时不能为空

 

验证3:

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

 

小练习:

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

复制代码
mysql> 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'
    -> );
Query OK, 0 rows affected (0.01 sec)

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

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

 

3、unique

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

 

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

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

 

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

复制代码
#第一种创建unique的方式
#例子1:
create table department(
    id int,
    name char(10) unique
);
mysql> insert into department values(1,'it'),(2,'it');
ERROR 1062 (23000): Duplicate entry 'it' for key 'name'

#例子2:
create table department(
    id int unique,
    name char(10) unique
);
insert into department values(1,'it'),(2,'sale');

#第二种创建unique的方式
create table department(
    id int,
    name char(10) ,
    unique(id),
    unique(name)
);
insert into department values(1,'it'),(2,'sale');
复制代码

 

联合唯一:

复制代码
# 创建services表
mysql> create table services(
    -> id int,
    -> ip char(15),
    -> port int,
    -> unique(id),
    -> unique(ip,port)
    -> );
Query OK, 0 rows affected (0.05 sec)

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.01 sec)

#联合唯一,只要两列记录,有一列不同,既符合联合唯一的约束
mysql> insert into services values
    -> (1,'192,168,11,23',80),
    -> (2,'192,168,11,23',81),
    -> (3,'192,168,11,25',80);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

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)

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存储引擎来说,一张表必须有一个主键。

单列主键

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

insert into t14 values
(1,'xiaoma'),
(2,'xiaohong');

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)
);
mysql> create table t15(
    -> id int not null unique,
    -> name char(16)
    -> );
Query OK, 0 rows affected (0.01 sec)

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.02 sec)
复制代码

 

复合主键

 验证复合主键的使用

 

5.auto_increment

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

 

(重点)验证:

 不指定id,则自动增长

 

 也可以指定id

 

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

 

了解:

 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表(被关联表,也叫从表)。

 

创建两张表操作:

 View Code

 

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

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

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

修改emp表:

复制代码
create table emp(
    id int primary key,
    name varchar(20) not null,
    age int not null,
    dep_id int,
    dforeign key(dep_id) references dep(id) 
    on delete cascade #同步删除
    on update cascade #同步更新
);
复制代码

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

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

mysql> select * from dep;
+----+-----------+----------------------+
| id | name      | descripe             |
+----+-----------+----------------------+
|  1 | IT        | IT技术有限部门       |
|  2 | 销售部    | 销售部门             |
+----+-----------+----------------------+
2 rows in set (0.00 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)

#再去更改被关联表(dep)的记录,关联表(emp)中的记录也跟着更改

mysql> update dep set id=222 where id=2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# 赶紧去查看一下两张表是否都被删除了,是否都被更改了
mysql> select * from dep;
+-----+-----------+----------------------+
| id  | name      | descripe             |
+-----+-----------+----------------------+
|   1 | IT        | IT技术有限部门       |
| 222 | 销售部    | 销售部门             |
+-----+-----------+----------------------+
2 rows in set (0.00 sec)

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)
复制代码

 

 

 

 

十、外键的变种

本节重点:

  • 如何找出两张表之间的关系
  • 表的三种关系

 

一、介绍

因为有foreign key的约束,使得两张表形成了三种了关系:

  • 多对一
  • 多对多
  • 一对一

二、重点理解如果找出两张表之间的关系

复制代码
分析步骤:
#1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)

#2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)

#3、总结:
#多对一:
如果只有步骤1成立,则是左表多对一右表
如果只有步骤2成立,则是右表多对一左表

#多对多
如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系

#一对一:
如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可
复制代码

 

三、表的三种关系

(1)书和出版社

  一对多(或多对一):一个出版社可以出版多本书。看图说话。

  关联方式:foreign key

 

 

复制代码
create table press(
    id int primary key auto_increment,
    name varchar(20)
);

create table book(
    id int primary key auto_increment,
    name varchar(20),
    press_id int not null,
         constraint fk_book_press foreign key(press_id) references press(id)
    on delete cascade
    on update cascade
);

# 先往被关联表中插入记录
insert into press(name) values
('北京工业地雷出版社'),
('人民音乐不好听出版社'),
('知识产权没有用出版社')
;

# 再往关联表中插入记录
insert into book(name,press_id) values
('九阳神功',1),
('九阴真经',2),
('九阴白骨爪',2),
('独孤九剑',3),
('降龙十巴掌',2),
('葵花宝典',3)
;

查询结果:
mysql> select * from book;
+----+-----------------+----------+
| id | name            | press_id |
+----+-----------------+----------+
|  1 | 九阳神功        |        1 |
|  2 | 九阴真经        |        2 |
|  3 | 九阴白骨爪      |        2 |
|  4 | 独孤九剑        |        3 |
|  5 | 降龙十巴掌      |        2 |
|  6 | 葵花宝典        |        3 |
+----+-----------------+----------+
6 rows in set (0.00 sec)

mysql> select * from press;
+----+--------------------------------+
| id | name                           |
+----+--------------------------------+
|  1 | 北京工业地雷出版社             |
|  2 | 人民音乐不好听出版社           |
|  3 | 知识产权没有用出版社           |
+----+--------------------------------+
3 rows in set (0.00 sec)
复制代码

 

(2)作者和书籍的关系

  多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多。看图说话。

  关联方式:foreign key+一张新的表

 

 

复制代码
# 创建被关联表author表,之前的book表在讲多对一的关系已创建
create table author(
    id int primary key auto_increment,
    name varchar(20)
);
#这张表就存放了author表和book表的关系,即查询二者的关系查这表就可以了
create table author2book(
    id int not null unique auto_increment,
    author_id int not null,
    book_id int not null,
    constraint fk_author foreign key(author_id) references author(id)
    on delete cascade
    on update cascade,
    constraint fk_book foreign key(book_id) references book(id)
    on delete cascade
    on update cascade,
    primary key(author_id,book_id)
);
#插入四个作者,id依次排开
insert into author(name) values('egon'),('alex'),('wusir'),('yuanhao');

# 每个作者的代表作
egon: 九阳神功、九阴真经、九阴白骨爪、独孤九剑、降龙十巴掌、葵花宝典
alex: 九阳神功、葵花宝典
wusir:独孤九剑、降龙十巴掌、葵花宝典
yuanhao:九阳神功

# 在author2book表中插入相应的数据

insert into author2book(author_id,book_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(2,1),
(2,6),
(3,4),
(3,5),
(3,6),
(4,1)
;
# 现在就可以查author2book对应的作者和书的关系了
mysql> select * from author2book;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  1 |         1 |       1 |
|  2 |         1 |       2 |
|  3 |         1 |       3 |
|  4 |         1 |       4 |
|  5 |         1 |       5 |
|  6 |         1 |       6 |
|  7 |         2 |       1 |
|  8 |         2 |       6 |
|  9 |         3 |       4 |
| 10 |         3 |       5 |
| 11 |         3 |       6 |
| 12 |         4 |       1 |
+----+-----------+---------+
12 rows in set (0.00 sec)
复制代码

 

 

(3)用户和博客

  一对一:一个用户只能注册一个博客,即一对一的关系。看图说话

  关联方式:foreign key+unique

 

 

 

用户表和博客表(一对一关系)

 

 

posted @ 2018-06-12 14:46  越学越优秀  阅读(855)  评论(0编辑  收藏  举报