Java:38-MySQL索引和视图和存储过程

MySQL索引和视图和存储过程

代码-----------------------------
对于我们数据库的表,都是以文件存储的方式存在

在这里插入图片描述

在这里插入图片描述

/*
	索引(包含约束,不写索引名,那么索引名就是对应字段名,主键不显示索引名)概念
		我们可以通过对数据表中的字段创建索引 来提高查询速度
	
	常见的索引的分类
		主键索引 (primary key) 主键是一个唯一性的索引 每个表中只能有一个主键
		唯一索引 (unique) 索引列的所有数据只能出现一次,必须是唯一
		普通索引 (index) 最常见的索引 作用就是提高对数据的访问速度
		
	表对应的索引被保存在一个索引文件中, 如果对数据进行增删改操作,那么mysql就需要对索引进行更新(这个时候需要考虑索引的性能了,索引多,那么增删改可能会久一点,所以索引的好处基本只是针对查询,而不是增删改(对他们是坏处))
		//为什么会这样呢,这就不得不说明一下索引的原理了,通常索引的创建是指对该添加索引的字段进行一个优化,比如使用树(一般搜索的都是B+树),这种树,通常平衡,且是一定范围,在查询时,是可以根据这个树来查询的,他比全部扫描或者说类似的数组扫描是要快的,还有,该树最后会有一个链表连接的类似数组,其实就是链表(连接叶子节点),他的作用在于范围查询(虽然很多人认为他是索引的真正情况,这也并非没有道理,并且可能也会认为查询也是(因为他有顺序(前提如果也存在对应的数组的话),但是对比这样的树来说,通常还是类似的,所以说他是真正情况也不为过,所以大多数是使用树,可能有设置使用链表的(一般是有序链表,可能生成有序数组,具体看代码,那么在这种情况可以认为他是索引的真正情况),或者有其有序数组的))
	
*/

/*
	主键索引的创建
		1.创建表的时候 直接添加主键
		2.创建表之后 添加索引 使用 DDL
*/
CREATE TABLE demo01( 
    did INT, 
    dname VARCHAR(20),
    hobby VARCHAR(30)
);
-- 为demo01表添加 主键索引
ALTER TABLE demo01 ADD PRIMARY KEY (did);

/*
	唯一索引的创建
		create unique index 索引名 on 表名(列名(长度))
*/

-- 为demo01表的 hobby字段添加唯一索引
CREATE UNIQUE INDEX ind_hobby ON demo01(hobby);

-- 添加唯一索引的列,列的所有值都只能出现一次
INSERT INTO demo01 VALUES(1,'tom','篮球');

-- Duplicate entry '篮球' for key 'ind_hobby'
-- 唯一索引保证了数据的唯一性, 同时也提升了查询效率
INSERT INTO demo01 VALUES(2,'jack','篮球');


/*
	普通索引的创建
		1.create index 索引名 on 表名(列名[长度])
		2.ALTER TABLE 表名 ADD INDEX 索引名 (列名)
*/
-- 为 demo01表中的 dname字段添加普通索引
ALTER TABLE demo01 ADD INDEX ind_dname(dname);

/*
	删除索引
		ALTER  TABLE 表名  DROP INDEX 索引名;
*/
-- 删除dname字段上的索引
ALTER TABLE demo01 DROP INDEX ind_dname;


-- 导入测试索引.sql 文件
-- 地址:
/*
链接:https://pan.baidu.com/s/15wVEFP0Dkvft4oMwUgDGFg 
提取码:alsk 
*/

-- test_index 表中有 500万条数据
SELECT COUNT(*) FROM test_index;

-- 通过id查询一条数据
SELECT * FROM test_index WHERE id = 100001;

-- 通过 dname字段查询 耗时2秒左右
SELECT * FROM test_index WHERE dname = 'name5200';

-- 执行分组查询 dname没有添加索引 36秒
SELECT * FROM test_index GROUP BY dname;

-- dname字段添加索引
ALTER TABLE test_index ADD INDEX dname_indx(dname);

SELECT * FROM test_index GROUP BY dname;

/*
	索引的总结
		创建索引的原则
			优先选择为 经常出现在 查询条件或者排序 分组后面的字段 创建索引.
		
	索引的优点
		1.可以大大的提高查询速度
		2.减少查询中分组和排序的时间
		3.通过创建唯一索引保证数据的唯一性
		
	索引缺点
		1.创建和维护索引需要时间,数据量越大 时间越长.
		2.表中的数据进行增删改操作时,索引也需要进行维护,降低了维护的速度
		3.索引文件需要占据磁盘空间
*/
-- 注意:对于之前所说的约束,其实是一种作用,我们在创建那些约束时,实际上是创建索引
-- 而这些索引帮我们实现了对数据的约束,从而我们也叫约束
-- 就如not null约束,这个不是索引,但他对数据进行了一种作用,让他不为空
-- 唯一索引
-- 对表字段添加unique约束的方式
-- 在创建表时,自占一行的写上 unique key 索引名 (字段名(长度)),key和索引名和长度可以省略
-- 若写上长度,该列必须为字符串的类型,否则报错
-- 也可在字段后面加上unique,后面可以加多个unique不影响,即不报错
-- 因为多次声明,最后的结果还是一个结果,那就是唯一,与主键不同,因为主键只能有一个,而unique可以有多个
-- create unique index 索引名字 on 表(列(长度)),这个长度,若要写上,该列必须为字符串的类型,否则报错
-- 可以理解为创建唯一索引在表的列上
-- alter table 表名 add unique(列名)
-- alter table 表名 add unique key (列名)
-- alter table 表名 add unique key 索引名 (列名)
-- 其中key和索引名,可以不写,若索引名不写的话,则索引名就是对应字段名,主键不显示索引名
-- 由于字段后面可以加unique,那么就可以用修改操作,来实现添加unique等
-- alter table 表名 modify id int unique
-- alter table 表名 change id cid int unique
-- 注意:必须要可以在字段后面加的修饰才可用修改操作来加,否则加不了
-- 因为修改操作,本就是对创建表的一种修补,创建表时,可以加,那么就可以加
-- 而且无论是什么索引,在修改字段名时,对应的索引括号里面的字段名都会变成修改后的字段名
-- 如原来表primary key(id),然后alter table 表名 change id cid int
-- 那么primary key(id),就会变成primary key(cid)
-- index 英文意思:索引
-- 普通索引
-- 在创建表时,自占一行的写上 index(key) 索引名 (字段名(长度)),索引名和长度可以省略
-- 若写上长度,该列必须为字符串的类型,否则报错
-- create index 索引名字 on 表(列(长度))
-- alter table 表名 add index (列名(长度)),或者alter table 表名 add index 索引名 (列名(长度))
-- alter table 表名 add key (列名(长度)),或者alter table 表名 add key 索引名 (列名(长度))
-- 索引名和长度可以省略,若写上长度,该列必须为字符串的类型,否则报错
-- 注意:在创建表时,添加主键的primary key可以直接写key,即省略primary来创建主键
-- key 英文意思:钥匙
-- 删除索引,只要有索引名的,都可以这样删除
-- alter table 表名 drop index(key) 索引名,这样删除有索引名的
-- 因为创建unique索引时,有索引名,那么就可以这样删除
-- 对于mysql的value和values
-- 插入单行的时候使用values,在插入多行的时候使用value
-- 因为在插入单行时values速度快一些,插入多行时value快一些
-- 单行(values快):
-- insert into 表名 (id) values(1);
-- insert into 表名 (id) values(2);
-- 多行(value快):
-- insert into 表名 (id) value(1),(2);
-- 插入几行数据看不出来,但可以插入大量数据看出来
-- 实验数据地址:https://blog.csdn.net/qq_44813090/article/details/105307720
-- 由于在一些很多数据时,相关操作尽可能的提高速度,于是索引出现了,当有大量数据时
-- 你要查询对应的字段值的那一条数据,他会根据你的表找过去,若你这个字段是有索引的
-- 那么查询的速度就会快很多(具体参考B+树,数据结构可以参考99章博客(可能还要后面几篇)),否则没有索引的话,就会慢很多,特别是分组,会消耗大量的使间,这就是索引的好处
-- 在限制你的其他操作的同时(约束),也加快了查询速度
-- 其实无论是修饰(包括索引)还是其他的,都是作用于所有数据
-- 所以当你要操作(如修改,增加,删除)这些修饰或者其他的东西时,会操作所有数据
-- 即最好是在创建完表后,将需要的东西给操作(如修改,增加,删除)完
-- 这样当数据够多时,就不用中途操作(如修改,增加,删除)了
-- 当然,在操作(如修改,增加,删除)单条数据时,会将那些修饰(包括索引)或者其他东西,都会作用到操作后的数据
/*
	什么是视图
		视图是由查询结果形成的一张虚拟的表.
	
	视图的作用
		如果某个查询的结果出现的十分频繁,并且查询语法比较复杂.
		那么这个时候,就可以根据这条查询语句构建一张视图 方便查询
		
	视图的语法
		create view 视图名[字段列表] as select 查询语句;
		
		view 表示视图
		字段列表 一般跟后面的查询语句 相同
		as select 查询语句 表示给视图提供数据的 查询语句
*/
-- 创建视图
-- 对应的表在上一章博客
-- 1.查询所有商品和商品对应分类的信息
SELECT * FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`;

-- 2.根据上面的查询语句 构建一张视图
CREATE VIEW products_category_view AS
SELECT * FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`;

-- 操作视图 就相当于操作一张 只读表
SELECT * FROM products_category_view;


-- 使用视图进行查询操作

-- 查询各个分类下的商品平均价格
/*
	1.查询哪些表 分类表 商品表
	2.查询条件是什么  分组操作
	3.要查询的字段	平均价格,分类名
	4.多表的连接条件 category_id = cid
*/

-- 使用多表方式查询
SELECT 
	c.`cname`,
	AVG(p.`price`)
FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`
GROUP BY c.`cname`;


-- 通过视图查询
SELECT 
	pc.`cname`,
	AVG(pc.`price`)
FROM products_category_view pc GROUP BY pc.`cname`;


-- 查询鞋服分类下最贵的商品的全部信息
-- 多表查询
-- 1.查询鞋服分类中 最高的商品价格
SELECT 
	MAX(p.`price`)
FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid` 
WHERE c.`cname` = '鞋服';

-- 2.进行子查询 将上面的查询结果作为条件
SELECT 
	*
FROM products p LEFT JOIN category c 
ON p.`category_id` = c.`cid`
WHERE c.`cname` = '鞋服' AND p.`price` = 
(
	SELECT 
		MAX(p.`price`)
	FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid` 
	WHERE c.`cname` = '鞋服'
);

-- 通过视图查询
SELECT 
	*
FROM products_category_view pc 
WHERE pc.`cname` = '鞋服' AND pc.`price` = 
(
-- 子查询 求出鞋服分类下的最高价格
SELECT MAX(pc.`price`) FROM products_category_view pc 
WHERE pc.`cname` = '鞋服' ); 


/*
	视图与表的区别
		1.视图是建立在表的基础之上
		2.通过视图 不要进行增删改操作,视图主要就是用来简化查询
		3.删除视图 表不受影响,删除表 视图就不在起作用了.
*/
-- 在有些数据库的名称中会出现下划线"_",可以看作是连接的意思,假设有两张表,如表1,表2
-- 那么创建的视图可以是"表1_表2_view",这样就可以知道该视图由什么组成,所以通常情况下,下划线"_"
-- 是算连接表的,但这只是一种规范而已,并没有对数据库进行一些操作,即没有实际作用
-- 视图就是将查询的表,进行存储起来
-- 如create view 视图名 as 查询语句,对于查询表字段名时,as是用来设置查询结果字段的
-- 而不是查询表字段名时,而对于表来说,as是设置别名的,操作时都要用这个别名,而创建视图时的as
-- 是将查询语句给该视图,使得查看视图时,是操作这个语句,可以看出,这三个as表示结果不同
-- 即不可完全参照英文意思,因为这是编程,不是英文,意思可能会改变的,即可能不会一模一样
-- 如char在java里表示字符,而英文意思表示烧焦
-- character在java里表示字符包装类,而英文意思表示字符
-- 但也有些相同的
-- 如private在java里表示私有的,在英文意思里也表示私有的
-- 那么以后操作这个视图时,虽然可以用视图名来表示一个表了,但是最终结果是该语句的结果
-- 若该语句所对应表有损坏,且影响了该语句的查询,则会出现不同结果或者报错,若没有影响,就不会
-- 且该视图只能查询,即只能读,因为是一个语句,那么就不可以进行其他操作(如增加,修改,删除)
/*
	存储过程其实就是一堆 SQL 语句的合并。中间加入了一些逻辑控制。
	
	存储过程的优缺点
		优点
			1.调试完成就可以稳定运行 (在业务需求相对稳定情况)
			2.存储过程可以减少 业务系统与数据库的交互
			因为存储过程是在数据库里的,执行时,数据库直接执行
			而当自己写的代码不在数据库服务器里写时的(若在的话则不影响)
			通过连接来进行远程执行,会有连接(业务系统与数据库)交互,即有延时
		
		缺点
			1.互联网项目中 较少使用存储过程,因为 业务需求变化太快
			2.存储过程的移植十分困难.
			
*/
# 商品表
CREATE TABLE goods(
  gid INT,
  NAME VARCHAR(20),
  num INT  -- 库存
);

#订单表
CREATE TABLE orders(
  oid INT,
  gid INT,
  price INT -- 订单价格
);

# 向商品表中添加3条数据
INSERT INTO goods VALUES(1,'奶茶',20);
INSERT INTO goods VALUES(2,'绿茶',100);
INSERT INTO goods VALUES(3,'花茶',25);

/*
	创建存储过程方式1:
		
	语法格式
		delimiter $$ -- 声明语句的结束符号 自定义 ||
		create procedure 存储过程名称() -- 声明存储过程
		begin   -- 开始编写存储过程
		
			-- 要执行的SQL
			
		end $$ -- 存储过程结束
*/

-- 编写存储过程, 查询所有商品数据
DELIMITER $$
CREATE PROCEDURE goods_proc()
BEGIN 
	-- 查询商品数据
	SELECT * FROM goods;
END $$

-- 调用存储过程 call
CALL goods_proc;


/*
	存储过程创建方式2: 创建一个接收参数的存储过程
	
	语法格式
		create procedure 存储过程名(IN 参数名 参数类型)
*/

-- 创建存储过程 接收一个商品id, 根据id删除数据
DELIMITER $$
CREATE PROCEDURE goods_proc02(IN goods_id INT)
BEGIN 
	-- 根据id删除商品数据
	DELETE FROM goods WHERE gid = goods_id;
END $$

-- 调用存储过程 传递参数
CALL goods_proc02(1);

/*
	存储过程创建方式3 获取存储过程的返回值
	
	1.变量的赋值
		SET @变量名 = 值
	2.OUT 输出参数
		OUT 变量名 数据类型
*/

-- 向订单表 插入一条数据, 返回1,表示插入成功
DELIMITER $$
CREATE PROCEDURE orders_proc(IN o_oid INT,IN o_gid INT ,IN o_price INT,OUT out_num INT)
BEGIN 
	-- 执行插入操作
	INSERT INTO orders VALUES(o_oid,o_gid,o_price);
	-- 设置 out_num 值为1
	SET @out_num = 1;
	
	-- 返回 out_num
	SELECT @out_num;  -- 在外面也可以这样,也就是说select是可以找很多种情况的
END $$

-- 调用存储过程 获取返回值
CALL orders_proc(1,2,50,@out_num);
-- 存储过程与视图不同,视图是存储语句,而存储过程是存类似于java的方法,只所以是类似,是因为无参时
-- 存储过程可以不写括号,而java无论什么情况下都必须写括号
-- 且存储过程的返回值写在参数里,而java的返回值写在方法名前面
-- 即视图在看数据时,是执行语句,可以直接点击视图来看,而存储过程看数据时,是执行方法,必须执行方法,才可以看
-- 即视图可以看做赋值,而存储过程可以看做创建方法
-- 创建存储过程方式
-- delimiter $$ -- 声明语句的结束符号 自定义 ||(也可以将$$变为这两个竖线,即自定义的)
-- 只所以要声明结束符号,是因为要执行的sql里有分号,即必须要声明结束符号
-- 否则会报错,因为被要执行的sql的分号结束了
-- create procedure 存储过程名称() -- 声明存储过程,()存放的是参数
-- 与字段名的字段类型一样,只不过不可以加修饰
-- 如(in 参数名 参数类型,out 参数名 参数类型),其中参数之间用逗号隔开
-- 且可以写多个参数,即in和out可以写多个
-- in表示获得的参数,即输入的参数
-- 可以在代码里操作输入的参数,只作用于代码里(即存储过程里,或者begin和end之间)
-- 而out表示返回值,即输出的参数
-- 该参数只能获得数据,如select count(id) into 输出的参数 from 表名;
-- 就将表查询的多少条数据的结果给该参数了,若没有获得数据,那么该参数就为null
-- 代码里不可操作输出的参数
-- 通常用@用户变量当这个参数,即没有进行设置的用户变量,默认为null
-- 但是当这个参数也要慎重考虑,因为输出的参数如果没有获得数据的话,会为null,使得你传入的参数也为null了
-- 可以理解成相当于java的引用变量,改变参数的值,那么他的地址内容就变了,于是就改变了@用户变量指向的内容
-- begin   -- 开始编写存储过程
-- 这个中间是要执行的sql语句,可以有多条语句,即可以有多个分号,一个分号代表一条语句
-- 但执行时
-- 若代码符合sql语句,那么不会报错,且会执行(可以进行增加,修改,删除等操作)
-- 若不符合,或者是有错误的代码(表名错误),则会报错
-- 只是查询时,只会显示第一条查询语句所执行的结果,注意是第一条查询语句
-- 即前面的代码只要没有查询的代码,那么后面只要出现了查询语句,即select,那么这就算第一条
-- 创建存储过程中,sql不关键代码错误不会报错(不关键代码:不是关键字的代码,如表名)
-- 若你写了代码,则必须要用分号结尾该一条语句,否则报错(适用于所有使用begin和end的代码)
-- 或者什么语句也不写,即空白,这样虽然不报错,但是什么也没有操作,不建议使用
-- 由于是语句,那么也可以设置变量,如set @a = 1;,这样的变量,实际上,修改表的时候也可以操作
-- 如SET @s = 4;,先设置一个变量,@@为系统变量,@为用户变量
-- @作用于当前窗口
-- 局部变量declare除外,相当于可以加修饰的参数,也可以声明多次,如declare a,b,声明a和b参数
-- 后面就是类型和修饰了,修饰可以不加,只作用于内部,如存储过程的begin和end之间
-- 若要使用这个变量,必须先声明该变量,即不可声明在其他的语句下面,否则报错
-- @@作用于全部窗口
-- 会话变量除外,会话变量是系统变量的一种,只作用于当前窗口,只有全局变量才可以作用于全部窗口
-- UPDATE 表名 SET id = @s WHERE id =  2;,这样id就设置成4了,当然存储过程也可以设置,且也作用于当前窗口
-- 注意:begin和end之间是可以执行多条语句的
-- end $$ -- 存储过程结束
-- 然后,call 存储过程名称();,就可以执行存储过程了,若无参的话,括号可以省略,否则不可省略
-- 且要注意,参数是用来操作的,即相当于一个你写入的数,那么必须符合sql里的代码,如:id = 参数名,id是整型的
-- 若参数名的值你设置一个字符串,那么明显id是不符合的,相当于你直接写id = 输入的字符串,即会报错
-- 若你输入的字符串的内容是数字,那么mysql在判断时,会转化成整型,这样的话,就不会报错了
-- 否则的话是转化不了的,如'a'
-- 必须要有结束符,所有代码都需要结束符,除非工具自动给你提供
-- 如sqlyon可视化界面(工具)可以不写分号结束符,会提供给你,即自动给你加上分号结束符
-- delimiter 英文意思:分隔符
-- procedure 英文意思:步骤
-- begin 英文意思:开始
-- call 英文意思:呼叫,用来调用存储过程,后面接存储过程的名字
-- in 英文意思:进入
-- out 英文意思:出去
-- into 英文意思:进入
/*
	触发器
		当我们执行一条sql语句的时候,这条sql语句的执行会自动去触发执行其他的sql语句。
	
	触发器创建的四个要素
		1. 监视地点(table) 
		2. 监视事件(insert/update/delete)  
		3. 触发时间(before/after)  
		4. 触发事件(insert/update/delete) 
	
	创建触发器
	语法结构
		delimiter $ -- 自定义结束符号
		create trigger  触发器名
		after/before(insert/update/delete) -- 触发的时机 和监视的事件
		on tableName -- 触发器所在表
		for each row -- 固定写法 表示行触发器
		begin
			-- 被触发的事件
		end $
*/
-- 向商品表中插入数据
INSERT INTO goods VALUES(4,'book',40);


-- 需求: 在下订单的时候,对应的商品的库存量要相应的减少,卖出商品之后减少库存量
/*
	监视的表 orders
	监视的事件 insert
	触发的时间 after
	触发的事件 update
*/
-- 1.修改结束符号
DELIMITER $
-- 2.创建触发器
CREATE TRIGGER t1
-- 3.设置触发的时间 以及监视的事件 监视的表
AFTER INSERT ON orders
-- 4.行触发器
FOR EACH ROW
-- 5.触发后要执行的操作
BEGIN
	-- 执行修改库存的操作 订单+1 库存-1
	UPDATE goods SET num = num - 1 WHERE gid = 4;
END $

-- 向orders表插入一个订单
INSERT INTO orders VALUES(1,4,25);
-- 注意:对于一些可视化界面,是可以不用设置结束符号的
-- 他们规定在触发器和存储过程里面的或者其他代码不参与结束的操作
-- 即分号不参加了,但也可以设置,但有些必须设置结束符号
-- 除非本来就是分号结尾了,当然也可以设置分号为结束符号,只不过没必要,因为没有这样的规定
-- 最主要的是有些工具默认结束符号为分号,那么在没有设置结束符号时,有些代码会报错
-- 因为代码不完整了,如触发器中没设置结束符号时,begin结束的不是end了,被分号拦截了
-- 且设置结束符的话可以让代码更加的整洁
-- 也更加的可以确定在哪里结束
-- 触发器的创建方式 
-- delimiter $ -- 自定义结束符号
-- create trigger  触发器名
-- after/before 触发的时机
-- 区别:before的insert和update可以在begin和end之间使用new,new就是你要操作的数据,如原来表的id为4
-- 你增加一个id为5的数据或者修改id为4的数据变为5时,那么new.id就是这个5
-- 即new就是用来存放你对当前表的操作变化的数据
-- 可以看成是你输入的数据,即你准备要改变表的那个数据,但是不可以用old,即不可以操作原来表的数据
-- 而delete则没有操作的数据,所以不可以用new,但需要获得原来表的内容,那么就用old.id
-- old存放着当前表的所有数据,这样就获得表的id数据
-- 即为4,其中update也可以用old
-- 即before的new使用者是insert,old的使用者是delete,而update可以都使用
-- 注意:若要修改new.对应字段,那么必须使用set new.对应字段,因为set代表着设置,否则识别不了你的操作
-- 这个与java不一样,因为不是同一种语言,且只有insert和update可以修改,delete修改不了
-- 因为delete不可以用new,且old是不可以修改的,因为触发器不可对当前表操作
-- 就如不可以对当前表进行增删改操作一样
-- 对于after的insert只可以使用new,但不可修改,update可以使用new和old,但都不能修改
-- delete只可以使用old,且也不能修改
-- 因为new是使用操作变化的数据,而after则是操作表数据之后的操作,所以没有new,因为你先对表操作完了
-- 而old是不可对当前表进行操作,所以也不可以用
-- 即after则new和old都不可修改
-- 总结:
-- before
-- insert可使用new,修改new,不可使用old,不可修改old
-- update可使用new,修改new,可使用old,不可修改old
-- delete不可使用new,不可修改new,可使用old,不可修改old
-- after
-- insert可使用new,不可修改new,不可使用old,不可修改old
-- update可使用new,不可修改new,可使用old,不可修改old
-- delete不可使用new,不可修改new,可使用old,不可修改old
-- 由于after是先完成数据的增删改,再触发,触发的语句晚于监视的增删改操作,且不可修改你输入的数据
-- 那么就无法影响前面的增删改动作
-- 也就是说先插入订单记录(我要20个),再更新商品的数量(只有10个),这时数量可能会出现错误结果,如负数(-10)
-- 而before是先完成触发,再增删改,触发的语句先于监视的增删改,我们就有机会判断(修改输入的数据)
-- 修改即将发生的操作,由于先后的顺序
-- 使得before和after对输入的数据是否有操作的时候,即在前的可以操作,在后的操作不到了
-- 即可以理解为before是对当前表的约束(可以修改),也可以对其他表进行操作
-- 而after只能对其他表进行操作(不可修改,但可以用new)
-- insert/update/delete 监视的事件
-- on tableName -- 触发器所在表
-- for each row -- 固定写法 表示行触发器
-- begin
-- 被触发的事件,sql语句,可以使用if和end if操作(只要是begin和end的都可以使用)
-- 使用方式 if 条件语句 then 中间的操作 end if;,这里也是分号结尾的,mysql规定if操作这样写
-- then 英文意思:然后,当if判断为真,就执行then后面的代码,否则不执行,且then后面的代码必须有操作
-- 即增加操作,修改操作,删除操作,或者变量之间的操作等等,查询操作不可以
-- 否则没有操作的话,创建触发器就会报错
-- 注意:虽然增加操作,修改操作,和删除操作不会有错误,但是运行的时候,不可操作本表,因为怕你有可能会嵌套
-- 所以规定,在表的触发器里,不可对本表进行增删改操作,防止嵌套产生
-- 之所以创建触发器不报错,是因为表名可以随便写
-- 因为sql不关键代码错误不会报错(不关键代码:不是关键字的代码,如表名)
-- 注意:当你设置一个变量,如set @a = 10;,那么再次使用@a时,不可直接@a = 11,否则报错
-- 必须重新set @a = 11,因为在数据库里,第一次的set是定义变量再设置值,之后的set就是单纯的设置值了
-- 若没有set的话,是识别不了你要干什么的,而有set,就知道你要设置值了,这是mysql的规定,对任意变量都是如此
-- 这里给出一个提示功能,如signal SQLSTATE 'HY000' SET mysql_errno = 22, message_text = 'aa';
-- aa表示提示的信息,当执行到这里时,无论是before还是after都会终止前面的操作,即类似于回滚,让表回到原样
-- 只所以是这样的,是因为before和after都不算完全执行完,虽然after是执行增删改操作后触发的,
-- 但是只有当你完全执行完后,当前表和其他表的操作才执行完毕
-- 理解:通常我们在进行增删改操作时,数据到表会经过一系列底层,然后在最后确定,然后表数据(文件)改变
-- 而before和after类似于,对数据的约束,每当一行(for each row,每一行)数据要到表去时
-- 先进行before,然后到一个中转站
-- 最后通过after,在最后确定,然后表数据改变
-- 就如你开门(before),进去(增删改),还要关门(after),才算完全进入,类似于事务一样的操作
-- end $
-- signal 英文意思:信号
-- sqlstale 没英文意思,但可以理解为"错误的sql",而后面的'HY000',是固定的
-- 可以写'HY000'-'HY009'之间,包括两边
-- mysql_errno 没英文意思,但可以理解为"错误的编号",即22错误号,基本可以写很大
-- 但太大了(或者没有找到对应错误号,如'a')的话则默认为1231
-- message_text 没英文意思,但可以理解为"错误的信息",即'aa'就是错误信息,给你看的错误信息
-- 如'学号过大',那么发生错误时(执行到这里就会提示),就显示学号过大
-- 在这里不难发现,整型可以转化为字符串类型,而数字字符串(只有数字,如'1')可以转化整型
-- 但字母字符串(有字母的都算,如'01a')不可以
-- 注意:字符串'1.1'变为整型为1,变为字符串不会,整型1.1变为整型也是1
-- trigger 英文意思:触发
-- after 英文意思:在...后
-- brfore 英文意思:在…以前
-- for each 英文意思:每个
-- row 英文意思:一行
-- 注意:设置结束符时如delimiter ##,那么就会作用于整个窗口,除非你选中执行(使用的是sqlyog工具)
-- 若用光标执行,则执行##之间的代码(delimiter ##不执行也可以,但必须有,会自动识别)
-- set 变量名 = concat(变量1,变量2);,用在begin和end里
-- 可以将变量1和变量2合并起来(形成字符串),并赋值给该变量名
-- 注意:mysql的变量的类型与他的值有关,即可以随便赋值
/*
	DCL 创建用户
	语法结构
		create user '用户名'@'主机名' identified by '密码';
*/

-- 创建 admin1 用户,只能在 localhost 这个服务器登录 mysql 服务器,密码为 123456
CREATE USER 'admin1'@'localhost' IDENTIFIED BY '123456';

-- user 英文意思:用户
-- identified by 英文意思:密码

-- 创建 admin2 用户可以在任何电脑上登录 mysql 服务器,密码为 123456
CREATE USER 'admin2'@'%'  IDENTIFIED BY '123456'; -- %表示在任意电脑都可以登录

/*
	用户的授权
	语法格式
		grant 权限1,权限2 ... on 数据库名.表 to '用户名'@'主机名'
*/
-- 需要权限才会存在对应的数据库展示,自行测试就知道了
--  给 admin1 用户分配对 db4 数据库中 products 表的 操作权限:查询 
GRANT SELECT ON db4.`products` TO 'admin1'@'localhost';
-- 也可以修改用户密码
-- 比如GRANT SELECT ON db4.`products` TO 'admin1'@'localhost' IDENTIFIED BY '1234567';
-- 这样也就变成了1234567这个密码了,也就只能使用1234567登录了,而不是123456
-- 当然,他也可以理解为添加用户,即内涵了CREATE USER这个操作以及修改操作
-- 所以如果没有该admin1用户,他也会操作添加该用户

-- 除此之外,通常来说,可以理解为授予权限对哪个地方,并给哪个用户
-- grant 英文意思:授予
-- 给 admin2 用户分配所有权限,对所有数据库的所有表
GRANT ALL ON *.* TO 'admin2'@'%'
-- all:所有权限,*.*:任何数据库的任何表
-- 查询 商品表
SELECT * FROM products;

-- 插入商品数据
-- INSERT command denied to user 'admin1'@'localhost' for table 'products'
-- admin1用户只有查询权限
INSERT INTO products VALUES('p010','小鸟伏特加',3000,1,NULL);


/*
	查看用户权限
	语法格式
		show grants for '用户名'@'主机名';
*/

-- 查看root用户的权限
SHOW GRANTS FOR 'root'@'localhost';

-- 查看 admin1 用户的权限
SHOW GRANTS FOR 'admin1'@'localhost';

-- 删除用户
DROP USER 'admin1'@'localhost';

-- 查询用户
SELECT * FROM USER;
-- 创建用户
-- CREATE USER 'admin1'@'localhost' IDENTIFIED BY '123456';
-- user 英文意思:用户
-- identified by 英文意思:密码
-- 在数据库名称为mysql的数据库里,有个user表,存放的就是你的用户,你创建用户后,这里就有你创建的用户数据了
-- 其中localhost代表着只能在localhost这个服务器登录mysql服务器
-- 可以改成%,则可以在任何电脑上登录mysql服务器
-- 授予权限方式,grant 权限1,权限2 ... on 数据库名.表 to '用户名'@'主机名'
-- grant 英文意思:授予
-- 权限可以为增删改查等等,如select,若为all,则代表所有权限
-- 而"数据库名.表"是对应位置,若为*.*则是所有数据库的所有表
-- 当你指定对应的数据库名.表时,那么新建连接使用这个用户时,就会有你指定的数据库和对应的表
-- 注意通常情况下,需要指定到表,否则报错,若权限为all,那么指定任何位置都不会报错,因为显示mysql数据库
-- 只要你指定到表,那么无论权限如何(无权限除外),新建该连接时
-- 就会有对应的数据库和表(除非你删了,那么下次进入该连接时,就没了)
-- 查看权限方式
-- show grants for '用户名'@'主机名';
-- 展示用户名创建时的sql语句
-- show 英文意思:展示
-- for 英文意思:对于
-- grants 英文意思:允许
-- 注意:所有数据库是由用户共享的,即其中一个用户删除数据库的数据时(如表),那么其他用户也就没有该数据了
-- 因为都指向文件,当没有权限时,如usage,当无权限时,无论你指定什么表,也不会在你连接后,有该表(而且没有也怎么指定呢)
-- 因为只有连接数据库和查询information_schema的权限了,这是底线,不可再低
-- 删除用户
-- deop user '用户名'@'主机名';
-- 查询用户
-- select * from user;
-- 注意:'用户名'@'主机名',之间的@的两边不可有空格,即他们是一体的

在这里插入图片描述

-- 其中mysqldump是不是一个sql命令,而是一个工具,就如java里面的javac.exe,而mysql里面就是mysqldump.exe
-- 都是可执行文件,这里就知道环境变量的好处了,若你没有设置环境变量,那么你就必须要到bin目录下
-- 也就是mysqldump.exe所在的目录下才可执行,即需要dos窗口
-- 而设置了环境变量,那么就可以在任何目录执行mysqldump.exe这个可执行文件了
-- 当然,若你先创建dos窗口,然后更改环境变量,那么dos窗口并没有受影响
-- 因为dos窗口只会与创建他的哪个时候的环境变量的影响,可以理解为我走了一条路,然后你砸掉
-- 但我走过的哪个时候的路并没有受影响,即dos窗口是先读取环境变量的,后更改的与我先读取的数据不一样,所以无影响
-- 备份操作方式 mysqldump -uroot -p123456 db2 > F:/db02.sql
-- 后面是设置将db2的所有表数据,都变成sql语句,名字是db02
-- 若db02.sql直接写出db02,那么就是一个文件,若写成db02.txt,那就是文本文档
-- 即这里是写你存放的方式,所以只要是可以执行的文件,类型不作要求,但最好还是sql类型的,好分辨
-- 还原操作方式 source F:/db02.sql,source虽然是sql命令,但需要在dos窗口里执行,而sqlyog不可以执行
-- 且与use一样,可以不加分号,若db02.sql变为db02也可以,只要是可以执行的文件,类型不作要求
-- 但最好还是sql类型的,好分辨
-- 注意:手动的备份,会有数据库的创建,而命令备份,没有数据库的创建,所以用命令时,需要创建数据库
-- 注意:对于mysql同样的操作(如命令),执行时,会覆盖
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值