目录
数据库概念
数据库分类
网络数据库
层级数据库
关系数据库
关系型数据库
基本概念
典型关系型数据库
SQL介绍
SQL基本介绍
SQL分类
MySQL基本介绍
启动和停止MySQL服务
登录和退出MySQL系统
Mysql服务端架构
数据库基本操作
创建数据库
显示数据库
显示全部
显示部分
显示数据库创建语句
选择数据库
修改数据库
删除数据库
数据表操作
创建数据表
普通创建表
复制已有表结构
显示数据表
显示所有表
匹配显示表
显示表结构
显示表创建语句
设置表属性
修改表结构
删除表结构
数据基础操作
插入操作
查询操作
删除操作
更新操作
字符集
字符编码概念
字符集概念
设置客户端所有字符集
列类型(字段类型)
整数类型
Tinyint
Smallint
Mediumint
Int
Bigint
无符号标识设定
显示长度
小数类型
浮点型
Float
Double
定点数
Decimal
时间日期类型
Date
Time
Datetime
Timestamp
Year
Mysql记录长度
字符串型
Char
Varchar
Text
Enum
Set
列属性
Null属性
默认值
列描述
主键
创建主键
随表创建
表后增加
查看主键
删除主键
复合主键
主键约束
主键分类
自动增长
原理
使用自动增长
修改自动增长
删除自动增长
初始设置
细节问题
唯一键
创建唯一键
查看唯一键
删除唯一键
复合唯一键
表关系
一对一
一对多
多对多
高级数据操作
新增数据
多数据插入
主键冲突
蠕虫复制
更新数据
删除数据
查询数据
From数据源
单表数据
多表数据
动态数据
Where子句
Group by子句
分组统计
多分组
分组排序
回溯统计
Having子句
Order by子句
Limit子句
记录数限制
分页
查询中的运算符
算术运算符
比较运算符
逻辑运算符
In运算符
Is运算符
Like运算符
联合查询
基本概念
应用场景
基本语法
Order by的使用
连接查询
连接查询的意义
连接查询分类
交叉连接
原理
语法
应用
内连接
原理
语法
应用
外连接
原理
语法
应用
Using关键字
原理
语法
子查询
什么是子查询
子查询概念
主查询概念
子查询和主查询的关系
子查询分类
按功能分
按位置分
标量子查询
概念
语法
列子查询
概念
语法
行子查询
概念
行元素
语法
总结
表子查询
概念
语法
Exists子查询
概念
语法
子查询中特定关键字的使用
In
Any
Some
All
整库数据备份与还原
应用场景
应用方案
SQL备份
数据还原
用户权限管理
用户管理
创建用户
删除用户
修改用户密码
权限管理
授予权限:grant
取消权限:revoke
刷新权限:flush
密码丢失的解决方案
外键
外键概念
外键的操作
增加外键
修改&删除外键
外键基本要求
外键约束
约束的基本概念
外键约束的概念
约束作用
视图基本操作
创建视图
使用视图
修改视图
删除视图
事务安全
事务概念
事务基本原理
自动事务
手动事务
开启事务
执行事务
提交事务
回滚点
事务特点
变量
系统变量
会话变量
局部变量
流程结构
If分支
基本语法
复合语法
While循环
基本语法
结构标识符
函数
内置函数
字符串函数
时间函数
数学函数
其他函数
自定义函数
创建函数
查看函数
调用函数
删除函数
注意事项
函数流程结构案例
变量作用域
局部作用域
会话作用域
全局作用域
存储过程
存储过程概念
与函数的区别
相同点
不同点
存储过程操作
创建过程
查看过程
调用过程
删除过程
存储过程的形参类型
In
Out
Inout
触发器
触发器概念
基本概念
作用
触发器优缺点
触发器基本语法
创建触发器
基本语法
触发时机
触发事件
注意事项
查看触发器
触发触发器
删除触发器
触发器应用
记录关键字:new、old
商品自动扣除库存
数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。
数据库:存储数据的仓库
网络数据库是指把数据库技术引入到计算机网络系统中,借助于网络技术将存储于数据库中的大量信息及时发布出去;而计算机网络借助于成熟的数据库技术对网络中的各种数据进行有效管理,并实现用户与网络中的数据库进行实时动态数据交互。
层次结构模型实质上是一种有根结点的定向有序树(在数学中"树"被定义为一个无回的连通图)。
关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
数据库的另外一种区分方式:基于存储介质
存储介质分为两种:磁盘和内存
关系型数据库:存储在磁盘中
非关系型数据库:存储在内存中
关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。关系模型是由埃德加·科德于1970年首先提出的,并配合“科德十二定律”。现如今虽然对此模型有一些批评意见,但它还是数据存储的传统标准。关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成。
关系数据结构:指的数据以什么方式来存储,是一种二维表的形式存储
本质:二维表
姓名 |
年龄 |
身高 |
体重 |
张三 |
30 |
187 |
70 |
李四 |
40 |
|
|
关系操作集合:如何来关联和管理对应的存储数据,SQL指令
获取张三的年纪:已知条件为姓名
Select 年龄 from 二维表 where 姓名 = 张三;
关系完整性约束:数据内部有对应的关联关系,以及数据与数据之间也有对应的关联关系
姓名 |
年龄 |
身高 |
体重 |
张三 |
30 |
187 |
70 |
李四 |
40 |
|
|
表内约束:对应的具体列只能放对应的数据(不能乱放)
表间约束:自然界各实体都是有着对应的关联关系(外键)
Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL、SQLite
小型关系型数据库:Microsoft Access,SQLite
中型关系型数据库:SQL Server,Mysql
大型关系型数据库:Oracle,DB2
Mysql当前跟Oracle是一个公司的:隶属于Oracle
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
SQL就是专门为关系型数据库而设计出来的。
1、 数据查询语言(DQL:Data Query Language):
其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。
专门用于查询数据:代表指令为select/show
2、 数据操作语言(DML:Data Manipulation Language):
其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
专门用于写数据:代表指令为insert,update和delete
3、 事务处理语言(TPL):
它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。(不是所有的关系型数据库都提供事务安全处理)
专门用于事务安全处理:transaction
4、 数据控制语言(DCL):
它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
专门用于权限管理:代表指令为grant和revoke
5、 数据定义语言(DDL):
其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
专门用于结构管理:代表指令create和drop(alter)
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
AB公司被Sun公司收购---》Oracle又收购了Sun公司
1、 Mysql是一种开源免费的数据库产品
2、 Mysql对PHP的支持是最好(wamp或者lamp)
Mysql中用到的操作指令就是SQL指令
Mysql是一种C/S结构:客户端和服务端
服务端对应的软件:Mysqld.exe
命令行方式
通过Windows下打开cmd控制器,然后使用命令进行管理
Net start 服务(mysql):开启服务
Net stop mysql:关闭服务
系统服务方式
前提:在安装的Mysql的时候将mysql添加到Windows的服务中去了
方式1进入服务:
方式2进入服务:通过命令行:services.msc
通过服务对Mysql服务器进行管理
方案1:右键服务,然后选择开启或者停止
方案2:双击服务,进入到服务详情界面,可以点击开启或者停止按钮
通过客户端(mysql.exe)与服务器进行连接认证,就可以进行操作
通常:服务端与客户端不在同一台电脑上
登录
1、 找到mysql.exe(通过cmd控制台:如果在安装的时候指定了mysql.exe所在的路径为环境变量,就可以直接访问;如果没有,那么就必须进入到mysql.exe所在路径)
2、 输入对应的服务器地址:-h:host -h[IP地址/域名]
3、 输入服务器中Mysql监听的端口: -P:port –P:3306
4、 输入用户名:-u:username -u:root
5、 输入密码:-p:password –p:root
连接认证基本语法:
Mysql.exe/mysql -h主机地址 -P端口 -u用户名 -p密码
注意事项
1、 通常端口都可以默认:mysql坚挺的端口通常都是3306
2、 密码的输入可以先输入-p,直接换行,然后再以密文方式输入密码
退出
断开与服务器的连接:通常Mysql提供的服务器数量有限,一旦客户端用完,建议就应该断开连接。
建议方式:使用SQL提供的指令
Exit; //exit带分号
\q; //quit缩写
Quit:
Mysql服务端架构有以下几层构成:
1、 数据库管理系统(最外层):DBMS,专门管理服务器端的所有内容
2、 数据库(第二层):DB,专门用于存储数据的仓库(可以有很多个)
3、 二维数据表(第三层):Table,专门用于存储具体实体的数据
4、 字段(第四层):Field,具体存储某种类型的数据(实际存储单元)
数据库中常用的几个关键字
Row:行
Column:列(field)
数据库是数据存储的最外层(最大单元)
基本语法:create database 数据库名字 [库选项];
库选项:数据库的相关属性
字符集:charset 字符集,代表着当前数据库下的所有表存储的数据默认指定的字符集(如果当前不指定,那么采用DBMS默认的)
校对集:collate 校对集
Create database 数据库名字 charset 字符集名称;
每当用户通过SQL指令创建一个数据库,那么系统就会产生一个对应的存储数据的文件夹(data)
其实,每个数据库文件夹下都有一个opt文件,保存的是对应的数据库选项。
基本语法:show databases;
基本语法:show databases like ‘匹配模式’;
_:匹配当前位置单个字符
%:匹配指定位置多个字符
获取以my开头的全部数据库: ‘my%’;
获取m开头,后面第一个字母不确定,最后为database的数据库;’m_database’;
获取以database结尾的数据库:’%database’;
基本语法:show create database 数据库名字;
为什么要选择数据库?因为数据是存储到数据表,表存在数据库下。如果要操作数据,那么必须进入到对应的数据库才行。
基本语法:use 数据库名字;
修改数据库字符集(库选项):字符集和校对集
基本语法:alter database 数据库名字 charset = 字符集;
一旦修改成功,那么对应的opt文件中就会体现
是否可以修改数据库名字?mysql5.5之前是可以修改的rename命令;但是5.5之后就不可以。
基本语法:drop database 数据库名字;
删除虽简单,但是切记要做好安全操作:确保里面数据没有问题。(重要)
删除数据库之后:对应的存储数据的文件夹也会被删除(opt文件也被删除)
基本语法:create table 表名(字段名 字段类型 [字段属性], 字段名 字段类型 [字段属性],…) [表选项]
以上错误说明:表必须放到对应的数据库下:有两种方式可以将表挂入到指定的数据库下
1、 在数据表名字前面加上数据库名字,用“.”连接即可:数据库.数据表
2、在创建数据表之前先进入到某个具体的数据库即可:use 数据库名字;
表选项:与数据库选项类似
Engine:存储引擎,mysql提供的具体存储数据的方式,默认有一个innodb(5.5以前默认是myisam)
Charset:字符集,只对当前自己表有效(级别比数据库高)
Collate:校对集
从已经存在的表复制一份(只复制结构:如果表中有数据不复制)
基本语法:create table 新表名 like 表名; //只要使用数据库.表名,就可以在任何数据库下访问其他数据库的表名
每当一张数据表创建,那么就会在对应的数据库下创建一些文件(与存储引擎有关)
注意:这个结构文件来自于innodb存储引擎,innodb存储引擎所有的文件都存储在外部的ibdata文件中
基本语法:show tables;
基本语法:show tables like ‘匹配模式’;
本质含义:显示表中所包含的字段信息(名字,类型,属性等)
Describe 表名
Desc 表名
show columns from 表名
查看数据表创建时的语句:此语句看到的结果已经不是用户之前自己输入的。
基本语法:show create table 表名;
Mysql中有多种语句结束符
;与\g所表示的效果是一样的,都是字段在上排横着,下面跟对应的数据
\G字段在左侧竖着,数据在右侧横着
表属性指的就是表选项:engine,charset和collate
基本语法:alter table 表名 表选项 [=] 值;
注意:如果数据库已经确定了,里面有很多数据了,不要轻易修改表选项(字符集影响不大)
修改表名:rename table 旧表名 to 新表名
修改表选项:alter table 表名 表选项 [=] 新值
新增字段:alter table 表名 add [column] 新字段名 列类型 [列属性] [位置first/after 字段名]
字段位置:字段想要存放的位置
First:在某某之前(最前面),第一个字段
After 字段名:放在某个具体的字段之后(默认的)
修改字段名:alter table 表名 change 旧字段名 新字段名 字段类型 [列属性] [新位置]
修改字段类型(属性):alter table 表名 modify 字段名 新类型 [新属性] [新位置]
删除字段:alter table 表名 drop 字段名
基础语法:drop table 表名[,表名2…],可以同时删除多个数据表
批量删除表
本质含义:将数据以SQL的形式存储到指定的数据表(字段)里面
基本语法:向表中指定字段插入数据
Insert into 表名[(字段列表)] values(对应字段列表)
1、 注意:后面(values中)对应的值列表只需要与前面的字段列表相对应即可(不一定与表结构完全一致)
2、 注意:字段列表并不一定非要有所有的表中字段
基本语法:向表中所有字段插入数据
Insert into 表名 values(对应表结构) //值列表必须与字段列表一致
查询表中全部数据:select * from 表名; //*表示匹配所有的字段
查询表中部分字段:select 字段列表 from 表名; //字段列表使用逗号“,”隔开
简单条件查询数据:select 字段列表/* from 表名 where 字段名 = 值; //mysql中没有==符号
基本语法:delete from 表名 [where 条件]; //如果没有where条件:意味着系统会自动删除该表所有数据(慎用)
更新:将数据进行修改(通常是修改部分字段数据)
基本语法:update 表名 set 字段名 = 新值 [where 条件];//如果没有where条件,那么所有的表中对应的那个字段都会被修改成统一值。
字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
在计算机中所看到的任何内容都是字符构成的。
字符编码(character code)是计算机针对各种符号,在计算机中的一种二进制存储代号。
字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同。
常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。
如果直接通过cmd下的mysql.exe进行中文数据插入,那么可能出错
出错原因:
1、 用户是通过mysql.exe来操作mysqld.exe
2、 真正的SQL执行是Mysqld.exe来执行
3、 mysql.exe将数据传入mysqld.exe的时候,没有告知其对应的符号规则(字符集),而mysqld也没有能力自己判断,就会使用自己默认的(字符集)
解决方案:mysql.exe客户端在进行数据操作之前将自己所使用的字符集告诉mysqld
Cmd下的mysql.exe默认都只有一个字符集:GBK
Mysql.exe如果告知Mysqld.exe对应的字符集类型为gbk?
快捷方式:set names 字符集
重新进行数据插入:中文(GBK)
深层原理:客户端,服务端,连接层(show variables like ‘character_set_%’)
Mysql.exe与Mysqld.exe之间的处理关系一共分为三层
客户端传入数据给服务端:client:character_set_client
服务端返回数据给客户端:server:character_set_results
客户端与服务端之间的连接:connection:character_set_connection
Set names 字符集的本质:就是一次性打通三层关系的字符集,变得一致。
在系统中有三个变量来记录着这三个关系对应的字符集:show variables like ‘character_set_%’;
查看一个新的客户端的对应的字符集关系
修改服务器端变量的值
Set 变量名 = 值;
重新进行数据插入和查看的结果:插入OK,但是查看乱码
修改结果字符集为GBK
Connection只是为了更方便客户端与服务端进行字符集转换而设。
Set names gbk;
Set character_set_client = gbk; //为了让服务器识别客户端传来的数据
Set character_set_connection = gbk;//更好的帮助客户端与服务端之间进行字符集转换
Set character_set_results = gbk;//为了告诉客户端服务端所有的返回的数据字符集
迷你整形,系统采用一个字节来保存的整形:一个字节 = 8位,最大能表示的数值是0-255
小整形,系统采用两个字节来保存的整形:能表示0-65535之间
中整形,采用三个字节来保存数据。
整形(标准整形),采用四个字节来保存数据。
大整形,采用八个字节来保存数据。
1、 创建数据表
2、 插入合理数据
3、 插入错误数据(超出对应的数据范围)
4、 错误原因:并不是说tinyint没有这么大的空间,而是因为mysql默认的为整形增加负数。
实际表示的区间为-128,127
实际应用中,应该根据对应的数据的范围来选定对应的整形类型:通常使用的比较多的TINYINT和int。
无符号:表示存储的数据在当前字段中,没有负数(只有正数,区间为0-255)
基本语法:在类型之后加上一个 unsigned
显示长度:指数据(整型)在数据显示的时候,到底可以显示多长位。
Tinyint(3): 表示最长可以显示3位,unsigned说明只能是正数,0-255永远不会超过三个长度
Tinyint(4):表示最长可以显示4位,-128~127
显示长度只是代表了数据是否可以达到指定的长度,但是不会自动满足到指定长度:如果想要数据显示的时候,保持最高位(显示长度),那么还需要给字段增加一个zerofill属性才可以。
Zerofill:从左侧开始填充0(左侧不会改变数值大小),所以负数的时候就不能使用zerofill,一旦使用zerofill就相当于确定该字段为unsigned
数据显示的时候,zerofill会在左侧填充0到指定位:如果不足3位,那么填充到3位,如果本身已经够了或者超出,那么就不在填充。
显示长度可以自己设定:超出长度(但是不超出范围)不会影响,只会对不够长度的进行补充(显示长度)
专门用来存储小数的
在Mysql中将小数类型又分为两类:浮点型和定点型
浮点型又称之为精度类型:是一种有可能丢失精度的数据类型,数据有可能不那么准确(由其是在超出范围的时候)
浮点型之所以能够存储较大的数值(不精确),原因就是利用存储数据的位来存储指数
整型:所有位都为1
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
计算结果:
浮点型:有部分用于存储数据,有部分用于存指数
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
前三位转换成十进制之后用作10的指数: 10^7 * 数据值
Float又称之为单精度类型:系统提供4个字节用来存储数据,但是能表示的数据范围比整型大的多,大概是10^38;只能保证大概7个左右的精度(如果数据在7位数以内,那么基本是准确的,但是如果超过7位数,那么就是不准确的)
基本语法
Float:表示不指定小数位的浮点数
Float(M,D):表示一共存储M个有效数字,其中小数部分占D位
Float(10,2):整数部分为8位,小数部分为2位
1、 创建一个数据表保存浮点数据
2、 存入数据:合法数据
注意:如果数据精度丢失,那么浮点型是按照四舍五入的方式进行计算
3、 插入数据,超出大小
4、 数据长度刚好满足条件,但是会超出精度
说明:用户不能插入数据直接超过指定的整数部分长度,但是如果是系统自动进位导致,系统可以承担。
5、浮点数可以采用科学计数法来存储数据
浮点数的应用:通常是用来保存一些数量特别大,大到可以不用那么精确的数据。
Double又称之为双精度:系统用8个字节来存储数据,表示的范围更大,10^308次方,但是精度也只有15位左右。
定点数:能够保证数据精确的小数(小数部分可能不精确,超出长度会四舍五入),整数部分一定精确
Decimal定点数:系统自动根据存储的数据来分配存储空间,每大概9个数就会分配四个字节来进行存储,同时小数和整数部分是分开的。
Decimal(M,D):M表示总长度,最大值不能超过65,D代表小数部分长度,最长不能超过30。
1、 创建表:与浮点数对比
2、 插入正常数据
3、 插入最大数据
4、 尝试定点数进行四舍五入
定点数的应用:如果涉及到钱的时候有可能使用定点数
日期类型:系统使用三个字节来存储数据,对应的格式为:YYYY-mm-dd,能表示的范围是从1000-01-01 到9999-12-12,初始值为0000-00-00
时间类型:能够表示某个指定的时间,但是系统同样是提供3个字节来存储,对应的格式为:HH:ii:ss,但是mysql中的time类型能够表示时间范围要大的多,能表示从-838:59:59~838:59:59,在mysql中具体的用处是用来描述时间段。
日期时间类型:就是将前面的date和time合并起来,表示的时间,使用8个字节存储数据,格式为YYYY-mm-dd HH:ii:ss,能表示的区间1000-01-01 00:00:00 到9999-12-12 23:59:59,其可以为0值:0000-00-00 00:00:00
时间戳类型:mysql中的时间戳只是表示从格林威治时间开始,但是其格式依然是:YYYY-mm-dd HH:ii:ss
年类型:占用一个字节来保存,能表示1900~2155年,但是year有两种数据插入方式:0~99和四位数的具体年
1、 创建对应的时间日期类型的数据表
2、 插入数据:正常数据
3、 year的特殊性:可以采用两位数的数据插入,也可以采用四位数的年份插入
4、 year进行两位数插入的时候,有一个区间划分,零界点为69和70:当输入69以下,那么系统时间为20+数字,如果是70以上,那配系统时间为19+数字
5、 timestamp当对应的数据被修改的时候,会自动更新(这个被修改的数据不是自己)
6、 time类型特殊性:本质是用来表示时间区间(当前时间之后的多少个小时),能表示的范围比较大
7、 在进行时间类型录入的时候(time)还可以使用一个简单的日期代替时间,在时间格式之前加一个空格,然后指定一个数字(可以是负数):系统会自动将该数字转换成天数 * 24小时,再加上后面的时间。
PHP中有着非常强大的时间日期转换函数:date将时间戳转换成想要的格式,strtotime又可以将很多格式转换成对应的时间戳。PHP通常不需要数据库来帮助处理这么复杂的时间日期,所以通常配合PHP的时候,时间的保存通常使用时间戳(真正),从而用整型来保存。字符串型
在mysql中,有一项规定:mysql的记录长度(record == 行row)总长度不能超过65535个字节。
Varchar能够存储的理论值为65535个字符:字符在不同的字符集下可能占用多个字节。
1、 创建表:证明varchar在mysql中能够达到的理论值(utf8和GBK)
Varchar除了存储的数据本身要占用空间:还需要额外的空间来保存记录长度
2、 计算在utf8和GBK下对应的varchar能够存储的长度
Utf8 最多只能存储21844个字符
GBK最多只能存储32766个字符
定长字符:指定长度之后,系统一定会分配指定的空间用于存储数据
基本语法:char(L),L代表字符数(中文与英文字母一样),L长度为0到255
变长字符:指定长度之后,系统会根据实际存储的数据来计算长度,分配合适的长度(数据没有超出长度)
基本语法:Varchar(L),L代表字符数,L的长度理论值位0到65535
因为varchar要记录数据长度(系统根据数据长度自动分配空间),所以每个varchar数据产生后,系统都会在数据后面增加1-2个字节的额外开销:是用来保存数据所占用的空间长度
如果数据本身小于127个字符:额外开销一个字节;如果大于127个,就开销两个字节
Char和varchar数据存储对比(utf8,一个字符都会占用3个字节)
存储数据 |
Char(2) |
Varchar(2) |
Char所占字节 |
Varchar所占字节 |
A |
A |
A |
2 * 3 = 6 |
1 * 3 + 1 = 4 |
AB |
AB |
AB |
2 * 3 = 6 |
2 * 3 + 1 = 7 |
Char和varchar的区别
1、 char一定会使用指定的空间,varchar是根据数据来定空间
2、 char的数据查询效率比varchar高:varchar是需要通过后面的记录数来计算
如果确定数据一定是占指定长度,那么使用char类型;
如果不确定数据到底有多少,那么使用varchar类型;
如果数据长度超过255个字符,不论是否固定长度,都会使用text,不再使用char和varchar
文本类型:本质上mysql提供了两种文本类型
Text:存储普通的字符文本
Blob:存储二进制文本(图片,文件),一般都不会使用blob来存储文件本身,通常是使用一个链接来指向对应的文件本身。
Text:系统中提供的四种text
Tinytext:系统使用一个字节来保存,实际能够存储的数据为:2 ^ 8 + 1
Text:使用两个字节保存,实际存储为:2 ^ 16 + 2
Mediumtext:使用三个字节保存,实际存储为:2 ^ 24 + 3
Longtext:使用四个字节保存,实际存储为:2 ^ 32 + 4
注意:
1、 在选择对应的存储文本的时候,不用刻意去选择text类型,系统会自动根据存储的数据长度来选择合适的文本类型。
2、 在选择字符存储的时候,如果数据超过255个字符,那么一定选择text存储
枚举类型:在数据插入之前,先设定几个项,这几个项就是可能最终出现的数据结果。
如果确定某个字段的数据只有那么几个值:如性别,男、女、保密,系统就可以在设定字段的时候规定当前字段只能存放固定的几个值:使用枚举
基本语法:enum(数据值1,数据值2…)
系统提供了1到2个字节来存储枚举数据:通过计算enum列举的具体值来选择实际的存储空间:如果数据值列表在255个以内,那么一个字节就够,如果超过255但是小于65535,那么系统采用两个字节保存。
1、 创建表
2、 插入数据:合法数据,字段对应的值必须是设定表的时候所确定的值
3、 错误数据:enum有规范数据的功能,能够保证插入的数据必须是设定的范围,其他类型都不可以
4、 枚举enum的存储原理:实际上字段上所存储的值并不是真正的字符串,而是字符串对应的下标:当系统设定枚举类型的时候,会给枚举中每个元素定义一个下标,这个下标规则从1开始
Enum(1=>‘男’,2=>’女’,3=>’保密’)
特性:在mysql中系统是自动进行类型转换的:如果数据碰到“+、-、*、/”系统就会自动将数据转换成数值:而普通字符串转换成数值为0
Select 字段名 + 0 from 表名;
5、 既然实际enum字段存储的结果是数值:那么在进行数据插入的时候,就可以使用对应的数值来进行。
枚举的意义:
1、 规范数据本身,限定只能插入规定的数据项
2、 节省存储空间
集合:是一种将多个数据选项可以同时保存的数据类型,本质是将指定的项按照对应的二进制位来进行控制:1表示该选项被选中,0表示该选项没有被选中。
基本语法:set(‘值1’,’值2’,’值3’…)
系统为set提供了多个字节进行保存,但是系统会自动计算来选择具体的存储单元
1个字节:set只能有8个选项
2个字节:set只能有16个选项
3个字节:set只能表示24个选项
8个字节:set可以表示64个选项
Set和enum一样,最终存储到数据字段中的依然是数字而不是真实的字符串
1、 创建表
2、 插入数据:可以插入多个数据,就是在数据插入的字符串中,使用对应的逗号“,”将选项进行隔开
3、 数据选项所在的数据与数据插入的顺序无关:最终都会变成选项对应的顺序
4、 分析数据存储的方式
4.1 系统将对应的数据选项(设计)按照顺序进行编排:从第一个开始进行占位,每一个都对应一个二进制位。
4.2 数据在存储的时候,如果被选中,那么对应的位的值就为1,否则为0
4.3 系统在进行存储的时候会自动将得到的最终的二进制颠倒过来,然后再进行转换成十进制存储
5、 查看数据:按照自动转换成数值来查看
6、 既然是数值,那么就可以插入数值来代替实际插入数据
注意:数字插入的前提是对应的二进制位上都有对应的数据项
Set集合的意义:
1、 规范数据
2、 节省存储空间
Enum:单选框
Set:复选框
列属性又称之为字段属性,在mysql中一共有6个属性:null,默认值,列描述,主键,唯一键和自动增长
NULL属性:代表字段为空
如果对应的值为YES表示该字段可以为NULL
注意:
1、 在设计表的时候,尽量不要让数据为空
2、 Mysql的记录长度为65535个字节,如果一个表中有字段允许为NULL,那么系统就会设计保留一个字节来存储NULL,最终有效存储长度为65534个字节。
Default:默认值,当字段被设计的时候,如果允许默认条件下,用户不进行数据的插入,那么就可以使用事先准备好的数据来填充:通常填充的是NULL
测试:不给当前字段提供数据值
Default关键字的另外一层使用:显示的告知字段使用默认值:在进行数据插入的时候,对字段值直接使用default
列描述:comment,是专门用于给开发人员进行维护的一个注释说明
基本语法:comment ‘字段描述’;
查看Comment:必须通过查看表创建语句
顾名思义:主要的键,primary key,在一张表中,有且只有一个字段,里面的值具有唯一性
系统提供了两种增加主键的方式
1、 方案1:直接在需要当做主键的字段之后,增加primary key属性来确定主键
2、 方案2:在所有字段之后增加primary key选项:primary key(字段信息)
基本语法:alter table 表名 add primary key(字段);
方案1:查看表结构
方案2:查看表的创建语句
基本语法:alter table 表名 drop primary key;
案例:有一张学生选修课表:一个学生可以选修多个选修课,一个选修课也可以由多个学生来选:但是一个学生在一个选修课中只有一个成绩。
主键一旦增加,那么对对应的字段有数据要求
1、 当前字段对应的数据不能为空;
2、 当前字段对应的数据不能有任何重复
主键分类采用的是主键所对应的字段的业务意义分类
业务主键:主键所在的字段,具有业务意义(学生ID,课程ID)
逻辑主键:自然增长的整型(应用广泛)
自动增长:auto_increment,当给定某个字段该属性之后,该列的数据在没有提供确定数据的时候,系统会根据之前已经存在的数据进行自动增加后,填充数据。
通常自动增长用于逻辑主键。
自动增长的原理:
1、 在系统中有维护一组数据,用来保存当前使用了自动增长属性的字段,记住当前对应的数据值,再给定一个指定的步长
2、 当用户进行数据插入的时候,如果没有给定值,系统在原始值上再加上步长变成新的数据
3、 自动增长的触发:给定属性的字段没有提供值
4、 自动增长只适用于数值
基本语法:在字段之后增加一个属性auto_increment
插入数据:触发自动增长,不能给定具体值
1、 查看自增长:自增长一旦触发使用之后,会自动的在表选项中增加一个选项(一张表最多只能拥有一个自增长)
2、 表选项可以通过修改表结构来实现
Alter table 表名 auto_increment = 值;
删除自增长:就是在字段属性之后不再保留auto_increment,当用户修改自增长所在字段时,如果没有看到auto_increment属性,系统会自动清除该自增长
在系统中,有一组变量用来维护自增长的初始值和步长
Show variables like ‘auto_increment%’;
1、 一张表只有一个自增长:自增长会上升到表选项中
2、 如果数据插入中没有触发自增长(给定了数据),那么自增长不会表现
3、 自增长修改的时候,值可以较大,但是不能比当前已有的自增长字段的值小
唯一键:unique key,用来保证对应的字段中的数据唯一的。
主键也可以用来保证字段数据唯一性,但是一张表只有一个主键。
1、 唯一键在一张表中可以有多个。
2、 唯一键允许字段数据为NULL,NULL可以有多个(NULL不参与比较)
创建唯一键与创建主键非常类似
1、 直接在表字段之后增加唯一键标识符:unique[ key]
2、 在所有的字段之后使用unique key(字段列表);
3、 在创建完表之后也可以增加唯一键
alter table 表名 add unique key(字段列表);
唯一键是属性,可以通过查看表结构来实现
唯一键效果:在不为空的情况下,不允许重复
在查看表创建语句的时候,会看到与主键不同的一点:多出一个“名字”
一个表中允许存在多个唯一键:假设命令为主键一样:alter table 表名 drop unique key;//错误的
Index关键字:索引,唯一键是索引一种(提升查询效率)
删除的基本语法:alter table 表名 drop index 唯一键名字;
修改唯一键:先删除后增加
唯一键与主键一样可以使用多个字段来共同保证唯一性;
一般主键都是单一字段(逻辑主键),而其他需要唯一性的内容都是由唯一键来处理。
表关系:表与表之间(实体)有什么样的关系,每种关系应该如何设计表结构。
一对一:一张表中的一条记录与另外一张表中最多有一条明确的关系:通常,此设计方案保证两张表中使用同样的主键即可
学生表
学生ID(PRI) |
姓名 |
年龄 |
性别 |
籍贯 |
婚否 |
住址 |
|
|
|
|
|
|
|
表的使用过程中:常用的信息会经常去查询,而不常用的信息会偶尔才会用到。
解决方案:将两张表拆分,常见的放一张表,不常见的放一张表
常用表
学生ID(PRI) |
姓名 |
年龄 |
性别 |
|
|
|
|
不常用表
学生ID(PRI) |
籍贯 |
婚否 |
住址 |
|
|
|
|
一对多,通常也叫作多对一的关系。通常一对多的关系设计的方案,在“多”关系的表中去维护一个字段,这个字段是“一”关系的主键。
母亲表
母亲ID |
姓名 |
年龄 |
身高 |
M1 |
|
|
|
M2 |
|
|
|
孩子表
孩子ID |
姓名 |
年龄 |
身高
|
母亲ID |
K1 |
|
|
|
M1 |
K2 |
|
|
|
M1 |
多对多:一张表中的一条记录在另外一张表中可以匹配到多条记录,反过来也一样。
多对多的关系如果按照多对一的关系维护:就会出现一个字段中有多个其他表的主键,在访问的时候就会带来不便。
既然通过两张表自己增加字段解决不了问题,那么就通过第三张表来解决。
师生关系
1、 一个老师教过多个班级的学生;
2、 一个学生听过多个老师讲的课;
首先得有两个实体:老师表和学生表
从中间设计一张表:维护两张表对应的联系:每一种联系都包含
多对多解决方案;增加一个中间表,让中间表与对应的其他表形成两个多对一的关系:多对一的解决方案是在“多”表中增加“一”表对应的主键字段。
只要写一次insert指令,但是可以直接插入多条记录
基本语法:insert into 表名 [(字段列表)] values(值列表), (值列表)…;
主键冲突:在有的表中,使用的是业务主键(字段有业务含义),但是往往在进行数据插入的时候,又不确定数据表中是否已经存在对应的主键。
主键冲突的解决方案:
1、 主键冲突更新:
类似插入数据语法,如果插入的过程中主键冲突,那么采用更新方法。
Insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值;
2、 主键冲突替换:
当主键冲突之后,干掉原来的数据,重新插入进去。
Replace into [(字段列表)] values(值列表);
蠕虫复制:一分为二,成倍的增加。从已有的数据中获取数据,并且将获取到的数据插入到数据表中。
基本语法:
Insert into 表名 [(字段列表)] select */字段列表 from 表;
注意:
1、 蠕虫复制的确通常是重复数据,没有太大业务意义:可以在短期内快速增加表的数据量,从而可以测试表的压力,还可以通过大量数据来测试表的效率(索引)
2、 蠕虫复制虽好,但是要注意主键冲突。
1、 在更新数据的时候,特别要注意:通常一定是跟随条件更新
Update 表名 set 字段名 = 新值 where 判断条件;
2、 如果没有条件,是全表更新数据。但是可以使用limit 来限制更新的数量;
Update 表名 set 字段名 = 新值 [where 判断条件] limit 数量;
改变4个a变成e
Update my_simple set name = ‘e’ where name = ‘a’ limit 4;
1、 删除数据的时候尽量不要全部删除,应该使用where进行 判定;
2、 删除数据的时候可以使用limit来限制要删除的具体数量
Delete删除数据的时候无法重置auto_increment
Mysql有一个能够重置表选项中的自增长的语法;
Truncate 表名; ==è drop -à create
完整的查询指令:
Select select选项 字段列表 from 数据源 where条件 group by分组 having条件 order by排序 limit限制;
Select选项:系统该如何对待查询得到的结果
All:默认的,表示保存所有的记录
Distinct:去重,去除重复的记录,只保留一条(所有的字段都相同)
字段列表:有的时候需要从多张表获取数据,在获取数据的时候,可能存在不同表中有同名的字段,需要将同名的字段命名成不同名的:别名 alias
基本语法:字段名 [as] 别名
From是为前面的查询提供数据:数据源只要是一个符合二维表结构的数据即可。
From 表名;
从多张表获取数据,基本语法:from 表1,表2…
结果:两张表的记录数相乘,字段数拼接
本质:从第一张表取出一条记录,去拼凑第二张表的所有记录,保留所有结果。得到的结果在数学上有一个专业的说法:笛卡尔积,这个结果出了给数据库造成压力,没有其他意义:应该尽量避免出现笛卡尔积。
From后面跟的数据不是一个实体表,而是一个从表中查询出来得到的二维结果表(子查询)。
基本语法:from (select 字段列表 from 表) as 别名;
Where字句:用来从数据表获取数据的时候,然后进行条件筛选。
数据获取原理:针对表去对应的磁盘处获取所有的记录(一条条),where的作用就是在拿到一条结果就开始进行判断,判断是否符合条件:如果符合就保存下来,如果不符合直接舍弃(不放到内存中)
Where是通过运算符进行结果比较来判断数据。
Group by表示分组的含义:根据指定的字段,将数据进行分组:分组的目标是为了统计
基本语法: group by 字段名;
Group by是为了分组后进行数据统计的,如果只是想看数据显示,那么group by没什么含义:group by将数据按照指定的字段分组之后,只会保留每组的第一条记录。
利用一些统计函数:(聚合函数)
count():统计每组中的数量,如果统计目标是字段,那么不统计为空NULL字段,如果为*那么代表统计记录
avg():求平均值
sum():求和
max():求最大值
min():求最小值
Group_concat():为了将分组中指定的字段进行合并(字符串拼接)
将数据按照某个字段进行分组之后,对已经分组的数据进行再次分组
基本语法:group by 字段1,字段2; //先按照字段1进行排序,之后将结果再按照字段2进行排序,以此类推。
Mysql中,分组默认有排序的功能:按照分组字段进行排序,默认是升序
基本语法:group by 字段 [asc|desc],字段 [asc|desc]
当分组进行多分组之后,往上统计的过程中,需要进行层层上报,将这种层层上报统计的过程称之为回溯统计:每一次分组向上统计的过程都会产生一次新的统计数据,而且当前数据对应的分组字段为NULL。
基本语法:group by 字段 [asc|desc] with rollup;
多分组回溯统计
Having的本质和where一样,是用来进行数据条件筛选。
1、 Having是在group by子句之后:可以针对分组数据进行统计筛选,但是where不行
查询班级人数大于等于4个以上的班级
Where不能使用聚合函数:聚合函数是用在group by分组的时候,where已经运行完毕
Having在group by分组之后,可以使用聚合函数或者字段别名(where是从表中取出数据,别名是在数据进入到内存之后才有的)
强调:having是在group by之后,group by是在where之后:where的时候表示将数据从磁盘拿到内存,where之后的所有操作都是内存操作。
Order by排序:根据校对规则对数据进行排序
基本语法:order by 字段 [asc|desc]; //asc升序,默认的
Order by也可以像group by一样进行多字段排序:先按照第一个字段进行排序,然后再按照第二个字段进行排序。
Order by 字段1 规则,字段2 规则;
Limit限制子句:主要是用来限制记录数量获取
纯粹的限制获取的数量:从第一条到指定的数量
基本语法: limt 数量;
Limit通常在查询的时候如果限定为一条记录的时候,使用的比较多:有时候获取多条记录并不能解决业务问题,但是会增加服务器的压力。
利用limit来限制获取指定区间的数据。
基本语法:limit offset,length; //offset偏移量:从哪开始,length就是具体的获取多少条记录
Mysql中记录的数量从0开始
Limit 0,2; 表示获取前两条记录
注意:limit后面的length表示最多获取对应数量,但是如果数量不够,系统不会强求
+、-、*、/、%
基本算术运算:通常不在条件中使用,而是用于结果运算(select 字段中)
>、>=、<、<=、=、<>
通常是用来在条件中进行限定结果
=:在mysql中,没有对应的 ==比较符号,就是使用=来进行相等判断
<=>:相等比较
特殊应用:就是在字段结果中进行比较运算
在条件判断的时候,还有有对应的比较运算符:计算区间
Between 条件1 and 条件2;
Between中条件1必须小于条件2,反过来不可以
and、or、not
and:逻辑与
or:逻辑或
not:逻辑非
In:在什么里面,是用来替代=,当结果不是一个值,而是一个结果集的时候
基本语法: in (结果1,结果2,结果3…),只要当前条件在结果集中出现过,那么就成立
Is是专门用来判断字段是否为NULL的运算符
基本语法:is null / is not null
Like运算符:是用来进行模糊匹配(匹配字符串)
基本语法:like ‘匹配模式’;
匹配模式中,有两种占位符:
_:匹配对应的单个字符
%:匹配多个字符
联合查询是可合并多个相似的选择查询的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合到一起,使用谓词为UNION或UNION ALL。
联合查询:将多个查询的结果合并到一起(纵向合并):字段数不变,多个查询的记录数合并。
1、 将同一张表中不同的结果(需要对应多条查询语句来实现),合并到一起展示数据
男生身高升序排序,女生身高降序排序
2、 最常见:在数据量大的情况下,会对表进行分表操作,需要对每张表进行部分数据统计,使用联合查询来讲数据存放到一起显示。
QQ1表获取在线数据
QQ2表获取在线数据 ---》将所有在线的数据显示出来
基本语法:
Select 语句
Union [union 选项]
Select 语句;
Union选项:与select选项基本一样
Distinct:去重,去掉完全重复的数据(默认的)
All:保存所有的结果
注意细节:union理论上只要保证字段数一样,不需要每次拿到的数据对应的字段类型一致。永远只保留第一个select语句对应的字段名字。
1、 在联合查询中,如果要使用order by,那么对应的select语句必须使用括号括起来
正确的语法:加上括号
2、 orderby在联合查询中若要生效,必须配合使用limit:而limit后面必须跟对应的限制数量(通常可以使用一个较大的值:大于对应表的记录数)
连接查询:将多张表连到一起进行查询(会导致记录数行和字段数列发生改变)
在关系型数据库设计过程中,实体(表)与实体之间是存在很多联系的。在关系型数据库表的设计过程中,遵循着关系来设计:一对一,一对多和多对多,通常在实际操作的过程中,需要利用这层关系来保证数据的完整性。
连接查询一共有以下几类:
交叉连接
内连接
外连接:左外连接(左连接)和右外连接(右连接)
自然连接
交叉连接:将两张表的数据与另外一张表彼此交叉
1、 从第一张表依次取出每一条记录
2、 取出每一条记录之后,与另外一张表的全部记录挨个匹配
3、 没有任何匹配条件,所有的结果都会进行保留
4、 记录数 = 第一张表记录数 * 第二张表记录数;字段数 = 第一张表字段数 + 第二张表字段数(笛卡尔积)
基本语法:表1 cross join 表2;
交叉连接产生的结果是笛卡尔积,没有实际应用。
本质:from 表1,表2;
内连接:inner join,从一张表中取出所有的记录去另外一张表中匹配:利用匹配条件进行匹配,成功了则保留,失败了放弃。
1、 从第一张表中取出一条记录,然后去另外一张表中进行匹配
2、 利用匹配条件进行匹配:
2.1 匹配到:保留,继续向下匹配
2.2 匹配失败:向下继续,如果全表匹配失败,结束
基本语法:表1 [inner] join 表2 on 匹配条件;
1、 如果内连接没有条件(允许),那么其实就是交叉连接(避免)
2、 使用匹配条件进行匹配
3、 因为表的设计通常容易产生同名字段,尤其是ID,所以为了避免重名出现错误,通常使用表名.字段名,来确保唯一性
4、 通常,如果条件中使用到对应的表名,而表名通常比较长,所以可以通过表别名来简化
5、 内连接匹配的时候,必须保证匹配到才会保存
6、 内连接因为不强制必须使用匹配条件(on)因此可以在数据匹配完成之后,使用where条件来限制,效果与on一样(建议使用on)
内连接通常是在对数据有精确要求的地方使用:必须保证两种表中都能进行数据匹配。
外链接:outer join,按照某一张表作为主表(表中所有记录在最后都会保留),根据条件去连接另外一张表,从而得到目标数据。
外连接分为两种:左外连接(left join),右外连接(right join)
左连接:左表是主表
右连接:右表是主表
1、 确定连接主表:左连接就是left join左边的表为主表;right join就是右边为主表
2、 拿主表的每一条记录,去匹配另外一张表(从表)的每一条记录
3、 如果满足匹配条件:保留;不满足即不保留
4、 如果主表记录在从表中一条都没有匹配成功,那么也要保留该记录:从表对应的字段值都未NULL
基本语法:
左连接:主表 left join 从表 on 连接条件;
右连接:从表 right join 主表 on连接条件;
左连接对应的主表数据在左边;右连接对应的主表数据在右边:
右连接查看数据
特点
1、 外连接中主表数据记录一定会保存:连接之后不会出现记录数少于主表(内连接可能)
2、 左连接和右连接其实可以互相转换,但是数据对应的位置(表顺序)会改变
非常常用的一种获取的数据方式:作为数据获取对应主表以及其他数据(关联)
是在连接查询中用来代替对应的on关键字的,进行条件匹配。
1、 在连接查询时,使用on的地方用using代替
2、 使用using的前提是对应的两张表连接的字段是同名(类似自然连接自动匹配)
3、 如果使用using关键字,那么对应的同名字段,最终在结果中只会保留一个。
基本语法:表1 [inner,left,right] join 表2 using(同名字段列表); //连接字段
子查询:sub query
子查询是一种常用计算机语言SELECT-SQL语言中嵌套查询下层的程序模块。当一个查询是另一个查询的条件时,称之为子查询。
子查询:指在一条select语句中,嵌入了另外一条select语句,那么被嵌入的select语句称之为子查询语句。
主查询:主要的查询对象,第一条select语句,确定的用户所有获取的数据目标(数据源),以及要具体得到的字段信息。
1、 子查询是嵌入到主查询中的;
2、 子查询的辅助主查询的:要么作为条件,要么作为数据源
3、 子查询其实可以独立存在:是一条完整的select语句
标量子查询:子查询返回的结果是一个数据(一行一列)
列子查询:返回的结果是一列(一列多行)
行子查询:返回的结果是一行(一行多列)
表子查询:返回的结果是多行多列(多行多列)
Exists子查询:返回的结果1或者0(类似布尔操作)
Where子查询:子查询出现的位置在where条件中
From子查询:子查询出现的位置在from数据源中(做数据源)
标量子查询:子查询得到结果是一个数据(一行一列)
基本语法:select * from 数据源 where 条件判断 =/<> (select 字段名 from 数据源 where 条件判断); //子查询得到的结果只有一个值
列子查询:子查询得到的结果是一列数据(一列多行)
基本语法:
主查询 where 条件 in (列子查询);
行子查询:子查询返回的结果是一行多列
行元素:字段元素是指一个字段对应的值,行元素对应的就是多个字段:多个字段合起来作为一个元素参与运算,把这种情况称之为行元素。
基本语法:
主查询 where 条件[(构造一个行元素)] = (行子查询);
已经学过三个子查询:常见的三个子查询
标量子查询、列子查询和行子查询:都属于where子查询
表子查询:子查询返回的结果是多行多列,表子查询与行子查询非常相似,只是行子查询需要产生行元素,而表子查询没有。
行子查询是用于where条件判断:where子查询
表子查询是用于from数据源:from子查询
基本语法:
Select 字段表 from (表子查询) as 别名 [where] [group by] [having] [order by] [limit];
Exists子查询:查询返回的结果只有0或者1,1代表成立,0代表不成立
基本语法:where exists(查询语句); //exists就是根据查询得到的结果进行判断:如果结果存在,那么返回1,否则返回0
Where 1:永远为真
主查询 where 条件 in (列子查询);
任意一个
= any(列子查询):条件在查询结果中有任意一个匹配即可,等价于in
<>any(列子查询):条件在查询结果中不等于任意一个
1 =any(1,2,3) ===== true
1 <>any(1,2,3) ===== true
与any完全一样:在国外,some与any的正面含义一致,但是否定就大不相同:not any与not some
开发者为了让对应的使用者不要在语法上纠结:重新设计了some
= all(列子查询):等于里面所有
<>all(列子查询):不等于其中所有
All数据展示
如果对应的匹配字段有NULL,那么不参与匹配
整库数据备份也叫SQL数据备份:备份的结果都是SQL指令
在Mysql中提供了一个专门用于备份SQL的客户端:mysqldump.exe
SQL备份是一种mysql非常常见的备份与还原方式,SQL备份不只是备份数据,还备份对应的SQL指令(表结构):即便是数据库遭到毁灭性的破坏(数据库被删),那么利用SQL备份依然可以实现数据还原。
SQL备份因为需要备份结构,因此产生的备份文件特别大,因此不适合特大型数据备份,也不适合数据变换频繁型数据库备份。
SQL备份用到的是专门的备份客户端,因此还没与数据库服务器进行连接。
基本语法:mysqldump/mysqldump.exe -hPup 数据库名字 [表1 [表2…]] > 备份文件地址
备份可以有三种形式:
1、 整库备份(只需要提供数据库名字)
2、 单表备份:数据库后面跟一张表
3、 多表备份:数据库后跟多张表
查看备份的成果
查看备份文件中的具体内容
Mysql提供了多种方式来实现:两种
Mysqldump备份的数据中没有关于数据库本身的操作,都是针对表级别的操作:当进行数据(SQL还原),必须指定数据库
1、 利用mysql.exe客户端:没有登录之前,可以直接用该客户端进行数据还原
Mysql.exe –hPup 数据库 < 文件位置
2、 在SQL指令,提供了一种导入SQL指令的方式
Source SQL文件位置; //必须先进入到对应的数据库
3、 人为操作:打开备份文件,复制所有SQL指令,然后到mysql.exe客户端中去粘贴执行。(不推荐)
用户权限管理:在不同的项目中给不同的角色(开发者)不同的操作权限,为了保证数据库数据的安全。
通常,一个用户的密码不会长期不变,所以需要经常性的变更数据库用户密码来确保用户本身安全(mysql客户端用户)
Mysql需要客户端进行连接认证才能进行服务器操作:需要用户信息。Mysql中所有的用户信息都是保存在mysql数据库下的user表中。
默认的,在安装Mysql的时候,如果不选择创建匿名用户,那么意味着所有的用户只有一个:root超级用户
在mysql中,对用的用户管理中,是由对应的Host和User共同组成主键来区分用户。
User:代表用户的用户名
Host:代表本质是允许访问的客户端(IP或者主机地址)。如果host使用%代表所有的用户(客户端)都可以访问
理论上讲可以采用两种方式创建用户:
1、 直接使用root用户在mysql.user表中插入记录(不推荐)
2、 专门创建用户的SQL指令
基本语法:create user 用户名 identified by ‘明文密码’;
用户:用户名@主机地址
主机地址:’’ / ‘%’
查看mysql.user表中是否存在新增的用户
简化版创建用户(谁都可以访问,不需要密码)
当用户创建完成之后,用户是否可以使用?
注意:mysql中user是带着host本身的(具有唯一性)
基本语法:drop user 用户名@host;
Mysql中提供了多种修改的方式:基本上都必须使用对应提供的一个系统函数:password(),需要靠该函数对密码进行加密处理。
1、 使用专门的修改密码的指令
基本语法:set password for 用户 = password(‘新的明文密码’);
修改后的数据测试
2、 使用更新语句update来修改表
基本语法:update mysql.user set password = password(‘新的明文密码’) where user = ‘’ and host= ‘’;
在mysql中将权限管理分为三类:
1、 数据权限:增删改查(select\update\delete\insert)
2、 结构权限:结构操作(create\drop)
3、 管理权限:权限管理(create user\grant\revoke):通常只给管理员如此权限
将权限分配给指定的用户
基本语法:grant 权限列表 on 数据库/*.表名/* to 用户;
权限列表:使用逗号分隔,但是可以使用all privileges代表全部权限
数据库.表名:可以是单表(数据库名字.表名),可以是具体某个数据库(数据库.*),也可以整库(*.*)
用户被分配权限以后不需要退出就可以看到效果
具体权限查看:单表权限只能看到数据库中的一张表
权限回收:将权限从用户手中收回
基本语法:revoke 权限列表/all privileges on 数据库/*.表/* from 用户;
权限回收,同样不需要刷新,用户马上就会感受到
Flush:刷新,将当前对用户的权限操作,进行一个刷新,将操作的具体内容同步到对应的表中。
基本语法:flush privileges;
如果忘记了root用户密码,就需要去找回或者重置root用户密码
1、 停止服务
2、 重新启动服务:mysqld.exe –skip-grant-tables //启动服务器但是跳过权限
3、 当前启动的服务器没有权限概念:非常危险,任何客户端,不需要任何用户信息都可以直接登录,而且是root权限:新开客户端,使用mysql.exe登录即可
4、 修改root用户的密码:指定 用户名@host
5、 赶紧关闭服务器,重启服务
如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。外键又称作外关键字。
外键:foreign key
一张表(A)中有一个字段,保存的值指向另外一张表(B)的主键
B:主表
A:从表
Mysql中提供了两种方式增加外键
1、 方案1:在创建表的时候增加外键(类似主键)
基本语法:在字段之后增加一条语句
[constraint `外键名`] foreign key(外键字段) references 主表(主键);
MUL:多索引,外键本身是一个索引,外键要求外键字段本身也是一种普通索引
2、 方案2:在创建表后增加外键
Alter table 从表 add [constraint `外键名`] foreign key(外键字段) references 主表(主键);
外键名字可以指定
外键不允许修改,只能先删除后增加
基本语法:alter table 从表 drop foreign key 外键名字;
外键不能删除产生的普通索引,只会删除外键自己
如果想删除对应的索引:alter table 表名 drop index 索引名字;
1、 外键字段需要保证与关联的主表的主键字段类型完全一致;
2、 基本属性也要相同
3、 如果是在表后增加外键,对数据还有一定的要求(从表数据与主表的关联关系)
4、 外键只能使用innodb存储引擎:myisam不支持
外键约束:通过建立外键关系之后,对主表和从表都会有一定的数据约束效率。
1、 当一个外键产生时:外键所在的表(从表)会受制于主表数据的存在从而导致数据不能进行某些不符合规范的操作(不能插入主表不存在的数据);
2、 如果一张表被其他表外键引入,那么该表的数据操作就不能随意:必须保证从表数据的有效性(不能随便删除一个被从表引入的记录)
可以在创建外键的时候,对外键约束进行选择性的操作。
基本语法: add foreign key(外键字段) references 主表(主键) on 约束模式;
约束模式有三种:
1、 district:严格模式,默认的,不允许操作
2、 cascade:级联模式,一起操作,主表变化,从表数据跟着变化
3、 set null:置空模式,主表变化(删除),从表对应记录设置为空:前提是从表中对应的外键字段允许为空
外键约束主要约束的对象是主表操作:从表就是不能插入主表不存在的数据
通常在进行约束时候的时候,需要指定操作:update和delete
常用的约束模式: on update cascade, on delete set null,更新级联,删除置空
更新模式
删除模式
保证数据的完整性:主表与从表的数据要一致
正是因为外键有非常强大的数据约束作用,而且可能导致数据在后台变化的不可控。导致程序在进行设计开发逻辑的时候,没有办法去很好的把握数据(业务),所以外键比较少使用。
视图的本质是SQL指令(select语句)
基本语法:create view 视图名字 as select指令; //可以是单表数据,也可以是连接查询,联合查询或者子查询
查看视图结构:视图本身是虚拟表,所以关于表的一些操作都适用于视图
Show tables/show create table[view]/desc 视图名字;
视图是一张虚拟表:可以直接把视图当做“表”操作,但是视图本身没有数据,是临时执行select语句得到对应的结果。视图主要用户查询操作。
基本语法:select 字段列表 from 视图名字 [子句];
修改视图:本质是修改视图对应的查询语句
基本语法:alter view 视图名字 as 新select指令;
基本语法:drop view 视图名字;
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言书写的用户程序的执行所引起。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
基本原理:Mysql允许将事务统一进行管理(存储引擎INNODB),将用户所做的操作,暂时保存起来,不直接放到数据表(更新),等到用于确认结果之后再进行操作。
事务在mysql中通常是自动提交的,但是也可以使用手动事务。
自动事务:autocommit,当客户端发送一条SQL指令(写操作:增删改)给服务器的时候,服务器在执行之后,不用等待用户反馈结果,会自动将结果同步到数据表。
证明:利用两个客户端,一个客户端执行SQL指令,另外一个客户端查看执行结果
自动事务:系统做了额外的步骤来帮助用户操作,系统是通过变量来控制的。Autocommit
Show variables like ‘autocommit%’;
关闭自动事务:关闭之后系统就不在帮助用户提交结果了
Set autocommit = Off;
查看执行结果
一旦自动事务关闭,那么需要用户提供是否同步的命令
Commit:提交(同步到数据表:事务也会被清空)
Rollback:回滚(清空之前的操作,不要了)
事务没有提交的对比查看:在执行事务端的客户端中,系统在进行数据查看的时候会利用事务日志中保存的结果对数据进行加工
通常,我们不会关闭自动事务:这样操作太麻烦。因此只会在需要使用事务处理的时候,才会进行操作(手动事务)
手动事务:不管是开始还是过程还是结束都需要用户(程序员),手动的发送事务操作指令来实现。
手动事务对应的命令:
1、 start transaction; //开启事务:从这条语句开始,后面的所有语句都不会直接写入到数据表(保存在事务日志中)
2、 事务处理:多个写指令构成
3、 事务提交:commit/rollback,到这个时候所有的事务才算结束
将多个连续的但是是一个整体的SQL指令,逐一执行
1、 事务操作1:新增数据
2、 事务操作2:更新数据
确认提交:commit,数据写到数据表(清空)
回滚操作:rollback,所有数据无效并清空
回滚点:savepoint,当有一系列事务操作时,而其中的步骤如果成功了,没有必要重新来过,可以在某个点(成功),设置一个记号(回滚点),然后如果后面有失败,那么可以回到这个记号位置。
增加回滚点:savepoint 回滚点名字; //字母数字和下划线构成
回到回滚点:rollback to 回滚点名字; //那个记号(回滚点)之后的所有操作没有了
注意:在一个事务处理中,如果有很多个步骤,那么可以设置多个回滚点。但是如果回到了前面的回滚点,后面的回滚点就失效;
1、 增加回滚点操作
2、 出现错误步骤
3、 回到正确点:回滚
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
事务从start transaction起到提交事务(commit或者rollback),要么所有的操作都成功,要么就是所有的操作都失败;
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
数据表中的数据修改,要么是所有操作一次性修改,要么是根本不懂
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
如果一个客户端在使用事务操作一个数据(可能是一行/整表)的时候,另外一个客户端不能对该数据进行操作
什么时候是行被隔离?什么时候是整表被隔离?
说明:如果条件中使用了索引(主键),那么系统是根据主键直接找到某条记录,这个时候与其他记录无关,那么只隔离一条记录;反之,如果说系统是通过全表检索(每一条记录都去检查:没有索引),被检索的所有数据都会被锁定(整表)
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
Mysql本质是一种编程语言,需要很多变量来保存数据。Mysql中很多的属性控制都是通过mysql中固有的变量来实现的。
系统内部定义的变量,系统变量针对所有用户(MySQL客户端)有效。
查看系统所有变量:show variables [like ‘pattern’];
Mysql允许用户使用select查询变量的数据值(系统变量)
基本语法:select @@变量名;
修改系统变量:分为两种修改方式
1、 局部修改(会话级别):只针对当前自己客户端当次连接有效
基本语法:set 变量名 = 新值;
2、 全局修改:针对所有的客户端,“所有时刻”都有效
基本语法:set global 变量名 = 值; || set @@global.变量名 = 值;
全局修改之后:所有连接的客户端并没发现改变?全局修改只针对新客户端生效(正在连着的无效)
注意:如果想要本次连接对应的变量修改有效,那么不能使用全局修改,只能使用会话级别修改(set 变量名 = 值);
会话变量也称之为用户变量,会话变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效。
定义用户变量:set @变量名 = 值;
在mysql中因为没有比较符号==,所以是用=代替比较符号:有时候在赋值的时候,会报错:mysql为了避免系统分不清是赋值还是比较:特定增加一个变量的赋值符号: :=
Set @变量名 := 值;
Mysql是专门存储数据的:允许将数据从表中取出存储到变量中:查询得到的数据必须只能是一行数据(一个变量对应一个字段值):Mysql没有数组。
1、 赋值且查看赋值过程:select @变量1 := 字段1,@变量2 := 字段2 from 数据表 where 条件;
错误语法:就是因为使用=,系统会当做比较符号来处理
正确处理:使用:=
2、 只赋值,不看过程:select 字段1,字段2… from 数据源 where条件 into @变量1,@变量2…
查看变量:select @变量名;
作用范围在begin到end语句块之间。在该语句块里设置的变量,declare语句专门用于定义局部变量。
1、 局部变量是使用declare关键字声明
2、 局部变量declare语句出现的位置一定是在begin和end之间(beginend是在大型语句块中使用:函数/存储过程/触发器)
3、 声明语法:declare 变量名 数据类型 [属性];
流程结构:代码的执行顺序
If在Mysql中有两种基本用法
1、 用在select查询当中,当做一种条件来进行判断
基本语法:if(条件,为真结果,为假结果)
2、 用在复杂的语句块中(函数/存储过程/触发器)
基本语法
If 条件表达式 then
满足条件要执行的语句;
End if;
复合语法:代码的判断存在两面性,两面都有对应的代码执行。
基本语法:
If 条件表达式 then
满足条件要执行的语句;
Else
不满足条件要执行的语句;
//如果还有其他分支(细分),可以在里面再使用if
If 条件表达式 then
//满足要执行的语句
End if;
End if;
循环体都是需要在大型代码块中使用
基本语法
While 条件 do
要循环执行的代码;
End while;
结构标识符:为某些特定的结构进行命名,然后为的是在某些地方使用名字
基本语法
标识名字:While 条件 do
循环体
End while [标识名字];
标识符的存在主要是为了循环体中使用循环控制。在mysql中没有continue和break,有自己的关键字替代:
Iterate:迭代,就是以下的代码不执行,重新开始循环(continue)
Leave:离开,整个循环终止(break)
标识名字:While 条件 do
If 条件判断 then
循环控制;
Iterate/leave 标识名字;
End if;
循环体
End while [标识名字];
在mysql中,函数分为两类:系统函数(内置函数)和自定义函数
不管是内置函数还是用户自定义函数,都是使用select 函数名(参数列表);
Char_length():判断字符串的字符数
Length():判断字符串的字节数(与字符集)
Concat():连接字符串
Instr():判断字符在目标字符串中是否存在,存在返回其位置,不存在返回0
Lcase():全部小写
Left():从左侧开始截取,直到指定位置(位置如果超过长度,截取所有)
Ltrim():消除左边对应的空格
Mid():从中间指定位置开始截取,如果不指定截取长度,直接到最后
Now():返回当前时间,日期 时间
Curdate():返回当前日期
Curtime():返回当前时间
Datediff():判断两个日期之间的天数差距,参数日期必须使用字符串格式(用引号)
Date_add(日期,interval 时间数字 type):进行时间的增加
Type:day/hour/minute/second
Unix_timestamp():获取时间戳
From_unixtime():将指定时间戳转换成对应的日期时间格式
Abs():绝对值
Ceiling():向上取整
Floor():向下取整
Pow():求指数,谁的多少次方
Rand():获取一个随机数(0-1之间)
Round():四舍五入函数
Md5():对数据进行md5加密(mysql中的md5与其他任何地方的md5加密出来的内容是完全相同的)
Version():获取版本号
Databse():显示当前所在数据库
UUID():生成一个唯一标识符(自增长):自增长是单表唯一,UUID是整库(数据唯一同时空间唯一)
自定义函数:用户自己定义的函数
函数:实现某种功能的语句块(由多条语句组成)
1、 函数内部的每条指令都是一个独立的个体:需要符合语句定义规范:需要语句结束符分号;
2、 函数是一个整体,而且函数是在调用的时候才会被执行,那么当设计函数的时候,意味着整体不能被中断;
3、 Mysql一旦见到语句结束符分号,就会自动开始执行
解决方案:在定义函数之前,尝试修改临时的语句结束符
基本语法:delimiter
修改临时语句结束符:delimiter 新符号[可以使用系统非内置即可$$]
中间为正常SQL指令:使用分号结束(系统不会执行:不认识分号)
使用新符号结束
修改回语句结束符:delimiter ;
自定义函数包含几个要素:function关键字,函数名,参数(形参和实参[可选]),确认函数返回值类型,函数体,返回值
函数定义基本语法:
修改语句结束符
Create function 函数名(形参) returns 返回值类型
Begin
//函数体
Return 返回值数据; //数据必须与结构中定义的返回值类型一致
End
语句结束符
修改语句结束符(改回来)
并不是所有的函数都需要begin和end:如果函数体本身只有一条指令(return),那么可以省略begin和end
形参:在mysql中需要为函数的形参指定数据类型(形参本身可以有多个)
基本语法:变量名 字段类型
1、 可以通过查看function状态,查看所有的函数
Show function status [like ‘pattern’];
2、 查看函数的创建语句:show create function 函数名字;
自定义函数的调用与内置函数的调用是一样的:select 函数名(实参列表);
删除函数:drop function 函数名;
1、 自定义函数是属于用户级别的:只有当前客户端对应的数据库中可以使用
2、 可以在不同的数据库下看到对应的函数,但是不可以调用
3、 自定义函数:通常是为了将多行代码集合到一起解决一个重复性的问题
4、 函数因为必须规范返回值:那么在函数内部不能使用select指令:select一旦执行就会得到一个结果(result set):select 字段 into @变量;(唯一可用)
需求:从1开始,直到用户传入的对应的值为止,自动求和:凡是5的倍数都不要。
设计:
1、 创建函数
2、 需要一个形参:确定要累加到什么位置
3、 需要定义一个变量来保存对应的结果:set @变量名;
使用局部变量来操作:此结果是在函数内部使用
Declare 变量名 类型 [= 默认值];
4、 内部需要一个循环来实现迭代累加
5、 循环内部需要进行条件判断控制:5的倍数
6、 函数必须有返回值
定义函数结构完成
调用函数:select 函数名(实参);
变量作用域:变量能够使用的区域范围
使用declare关键字声明(在结构体内:函数/存储过程/触发器),而且只能在结构体内部使用
1、 declare关键字声明的变量没有任何符号修饰,就是普通字符串,如果在外部访问该变量,系统会自动认为是字段
用户定义的,使用@符号定义的变量,使用set关键字
会话作用域:在当前用户当次连接有效,只要在本连接之中,任何地方都可以使用(可以在结构内部,也可以跨库)
会话变量可以在函数内部使用
会话变量可以跨库
所有的客户端所有的连接都有效:需要使用全局符号来定义
Set global 变量名 = 值;
Set @@global.变量名 = 值;
通常,在SQL编程的时候,不会使用自定义变量来控制全局。一般都是定义会话变量或者在结构中使用局部变量来解决问题。
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译(效率比较高),用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象(针对SQL编程而言)。
存储过程:简称过程
1、 存储过程和函数目的都是为了可重复地执行操作数据库的sql语句的集合。
2、 存储过程函数都是一次编译,后续执行
1、标识符不同。函数的标识符为FUNCTION,过程为:PROCEDURE。
2、函数中有返回值,且必须返回,而过程没有返回值。
3、过程无返回值类型,不能将结果直接赋值给变量;函数有返回值类型,调用时,除在select中,必须将返回值赋给变量。
4、函数可以在select语句中直接使用,而过程不能:函数是使用select调用,过程不是。
基本语法
Create procedure 过程名字([参数列表])
Begin
过程体
End
结束符
如果过程体中只有一条指令,那么可以省略begin和end
过程基本上也可以完成函数对应的所有功能
查看过程与查看函数完全一样:除了关键字
查看全部存储过程:show procedure status [like ‘pattern’];
查看过程创建语句:show create procedure 过程名字;
过程:没有返回值,select不可能调用
调用过程有专门的语法:call 过程名([实参列表]);
基本语法:drop procedure 过程名字;
存储过程也允许提供参数(形参和实参):存储的参数也和函数一样,需要指定其类型。
但是存储过程对参数还有额外的要求:自己的参数分类
表示参数从外部传入到里面使用(过程内部使用):可以是直接数据也可以是保存数据的变量
表示参数是从过程里面把数据保存到变量中,交给外部使用:传入的必须是变量
如果说传入的out变量本身在外部有数据,那么在进入过程之后,第一件事就是被清空,设为NULL
数据可以从外部传入到过程内部使用,同时内部操作之后,又会将数据返还给外部。
参数使用级别语法(形参)
过程类型 变量名 数据类型; //in int_1 int
分析结果:out类型的数据会被清空,其他正常
在执行过程之后,再次查看会话变量(外部)
触发器是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。
触发器:trigger,是一种非常接近于js中的事件的知识。提前给某张表的所有记录(行)绑定一段代码,如果改行的操作满足条件(触发),这段提前准备好的代码就会自动执行。
1、可在写入数据表前,强制检验或转换数据。(保证数据安全)
2、触发器发生错误时,异动的结果会被撤销。(如果触发器执行错误,那么前面用户已经执行成功的操作也会被撤销:事务安全)
3、部分数据库管理系统可以针对数据定义语言(DDL)使用触发器,称为DDL触发器。
4、可依照特定的情况,替换异动的指令 (INSTEAD OF)。(mysql不支持)
优点
1、 触发器可通过数据库中的相关表实现级联更改。(如果某张表的数据改变,可以利用触发器来实现其他表的无痕操作[用户不知道])
2、 保证数据安全:进行安全校验
缺点
1、 对触发器过分的依赖,势必影响数据库的结构,同时增加了维护的复杂程度。
2、 造成数据在程序层面不可控。(PHP层)
Create trigger 触发器名字 触发时机 触发事件 on 表 for each row
Begin
End
触发对象:on 表 for each row,触发器绑定实质是表中的所有行,因此当每一行发生指定的改变的时候,就会触发触发器。
触发时机:每张表中对应的行都会有不同的状态,当SQL指令发生的时候,都会令行中数据发生改变,每一行总会有两种状态:数据操作前和操作后
Before:在表中数据发生改变前的状态
After:在表中数据已经发生改变后的状态
触发事件:mysql中触发器针对的目标是数据发生改变,对应的操作只有写操作(增删改)
Insert:插入操作
Update:更新操作
Delete:删除操作
一张表中,每一个触发时机绑定的触发事件对应的触发器类型只能有一个:一张表中只能有一个对应after insert触发器
因此,一张表中最多的触发器只能有6个:before insert,before update,before delete,after insert,after update,after delete
需求:有两张表,一张是商品表,一张是订单表(保留商品ID),每次订单生成,商品表中对应的库存就应该发生变化。
1、 创建两张表:商品表和订单表
2、 创建触发器:如果订单表发生数据插入,对应的商品就应该减少库存
Create trigger 名字 after insert on my_orders for each row
1、 查看全部触发器
Show triggers;
2、 查看触发器的创建语句
Show create trigger 触发器名字;
想办法让触发器执行:让触发器指定的表中,对应的时机发生对应的操作即可。
1、 表为my_orders
2、 在插入之后
3、 插入操作
基本语法:drop trigger 触发器名字;
触发器针对的是数据表中的每条记录(每行),每行在数据操作前后都有一个对应的状态,触发器在执行之前就将对应的状态获取到了,将没有操作之前的状态(数据)都保存到old关键字中,而操作后的状态都放到new中。
在触发器中,可以通过old和new来获取绑定表中对应的记录数据。
基本语法:关键字.字段名
Old和new并不是所有触发器都有:
Insert:插入前全为空,没有old
Delete:清空数据,没有new
验证结果
如果库存数量没有商品订单多怎么办?
操作目标:订单表,操作时机:下单前;操作事件:插入
结果验证