1.视图:
什么是视图:
视图是有一张或多张表的查询结果构成的一张虚拟表
create view dept_view as select *from dept;
为什么使用视图:
使用权限控制 只能开放某一列的数据访问 对于目前的查看工资而言是没有意义的
我们使用虎能够查看整条语句
1.多次使用时,可以简化书写
2.隔离数据,可以修改原表中的数据;但是我们一般不会这么做。
总结:mysql可以分担程序中的部分逻辑,但这样一来后续的维护变得麻烦;如果需要改表结构,
那意味着视图也需要相应修改,没有直接在sql语句中修改方便
查询条件下的数据:
slect *from emp inner join dept on emp.d_id = dept.id;
建立查询虚拟表(在sql中存放的是语句,修改源代码会同步视图中;修改虚拟表时,原表同步):
create view dept_view as select *from salarys(原表) where dept="财务"
2.触发器:
什么是触发器:
触发器是一段与表有关的mysql程序 当这个表在某个时间点发生了某种事件时 将会自动执行相
应的触发器程序何时使用触发器。
触发器中无法使用事物。
准备数据:
CREATE TABLE cmd (
id INT PRIMARY KEY auto_increment,
USER CHAR (32),
priv CHAR (10),
cmd CHAR (64),
sub_time datetime, #提交时间
success enum ('yes', 'no') #0代表执行失败
);
#错误日志表
CREATE TABLE errlog (
id INT PRIMARY KEY auto_increment,
err_cmd CHAR (64),
err_time datetime
);
举例建立一个触发器
create trigger cmd_insert_triger after insert on cmd for each row
begin
if new.success = "no" then
insert into errlog values(null,new.cmd.sub_time);#直接;默认结束 单语句未完成 需更改;意义
end if;
end//
delimiter // # delimiter先重新设置一个 行结束符号
插入数据:
INSERT INTO cmd (
USER,
priv,
cmd,
sub_time,
success
)
VALUES
('egon','0755','ls -l /etc',NOW(),'yes'),
('egon','0755','cat /etc/passwd',NOW(),'no'),
('egon','0755','useradd xxx',NOW(),'no'),
('egon','0755','ps aux',NOW(),'yes');
查看错误日志表中的记录是否有自动插入:
select *from errlog;
注意:
1:外键不能触发事件 主表删除了某个主键 从表也会相应删除 但是并不会执行触发器
2:触发器中不能使用事物时间点 即相同时间,相同事件的触发器 不能同时存在
触发器删除语法:
drop trigger trigger_name;
3.事物:
什么是事物:
事务是逻辑上的一组操作,要么都成功,要么都失败。
什么时候使用事物
当需要保证一堆sql 要么都成功要么都失败时。
事物的使用:
start transaction; # 开启事物,在这条语句之后的sql将处在同一事务,并不会立即修改数据库
commit; # 提交事务,让这个事物中的sql立即执行数据的操作
rollback; # 回滚事务,取消这个事物,这个事物不会对数据库中的数据产生任何影响转账过程中发生
异常
注意:#开启事物后只要执行commit 或者 rollback 事物就结束了。
事物的特点:
1. 原子性:事务是一组不可分割的单位,要么同时成功,要么同时不成功;
2. 一致性:事物前后的数据完整性应该保持一致,(数据库的完整性:如果数据库在某一时间点下,所有的
数据都符合所有的约束,则称数据库为完整性的状态);
3. 隔离性: 事物的隔离性是指多个用户并发访问数据时,一个用户的事物不能被其它用户的事务所干扰,
多个并发事务之间数据要相互隔离
4. 持久性:持久性是指一个事物一旦被提交,它对数据的改变就是永久性的,接下来即使数据库发生故障
也不应该对其有任何影响
转账举例:
start transaction;
update account set money = money -1000 where name ="刘大牛";
rollback;
#准备数据
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
insert into account values(1,'赵大儿子',1000);
insert into account values(2,'刘大牛',1000);
insert into account values(3,'猪头三',1000);
insert into account values(4,'王进',1000);
insert into account values(5,'黄卉',1000);
# 赵大儿子刘大牛佳转账1000块
# 未使用事务
update account set money = money - 1000 where id = 1;
update account set moneys = money - 1000 where id = 1; # money打错了导致执行失败
在pymysql中使用事务处理:待补充:
import pymysql
conn=pymysql.connect(
user="root",
password="root",
database="day48",
charset="utf8"
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
#cursor.execute("delete from account")
sql1 = 'update account set money = money - 1000 where id = 1;'
sql2 = 'update account set moneys = money + 1000 where id = 2;' # money打错了导致执行失败
try:
cursor.execute(sql)
cursor.execute(sql2)
conn.commit()
except:
conn.rollback()
把你需要放在同意事务的sql执行 放在try中 最后加上commit
如果捕获到异常则执行rollback
在mysql客户端中,如果遇到了sql语句
什么是脏读?
读取一个事物未提交的数据
什么是不可重复度?
一个事物在查询,一个在updata 第一次查 和第二次查有可能数据不一致
什么是幻读
一个事物在查 另一个insert 或 delete 第一次查 和第二次查有可能数据不一致
事物的用户隔离:
read uncommitted:不做任何隔离,可能会脏读,幻读
read committed:可以防止脏读,但不能防止不可重复读和幻读
Repeatable read:可以防止脏读和不可重复读,但无法防止幻读
Serializable:数据库运行实现串行化,可以避免以上所有数据问题,但会降低性能
修改隔离级别:
select @@tx_isolation;--查询当前级别
set[session|global] transaction isolation level .... ;修改级别
实例:
set global transaction isolation level Repeatable read ;
4.存储过程:
什么是存储过程?
存储过程是一组任意的sql语句集合,存储在mysql中,调用存储过程时将会执行其包含的
所有sql语句;与python中函数类似;
为什么使用存储过程?
回顾触发器与视图都是为了简化应用程序中sql语句的书写,但是还是需要编写,而存储过
程中可以包含任何的sql语句,包括视图,事务,流程控制等,这样一来,应用程序可以从sql语句
中完全解放,mysql可以替代应用程序完成数据相关的的逻辑处理!
三种开发方式对比:
1.数据库操作全都放在mysql中,应用程序不需要编写sql语句 直接调用存储过程
优点:1.应用程序开发者工作量降低
2.提高程序的执行效率 因为网络io减少了
1.查询用户名是否存在的sql
2.根据查询结果 在发送一条注册的sql语句
一共经历两次网络访问
换成存储过程的话 只需要一次网络访问
缺点:学习成本高,扩展性,维护性差;部门间沟通成本高。
2.应用程序完全自己编写sql语句
优点:扩展性,维护性高;部门间沟通成本低。
缺点:工作量大,sql语句的优化需要应用程序开发发完成
今后常用:
3.使用ORM(对象关系映射)框架,可以直接使用面向对象的方式完成对数据库的CRUD;
简单来讲就是帮你封装了sql语句的生成。
优点:不需要写sql语句,开发效率高。不需要考虑sql优化问题。
缺点:执行效率略低于第二种方式 完全可以忽略不记。
删除存储过程:
drop procedure p1;
在mysql中创建一个存储过程:
create table stu (id int,name char(10));
insert into stu values(1,'egon'),
(2,'alex'),
(3,'kive'),
(4,'kive1'),
(5,'kive2'),
(6,'kive3'),
(7,'aaci');
set @res=11;
delimiter//
create procedure p1(in n int,in m int,out res int)
begin
select *from stu where id>n and id<m;
set res=0;
end//
delimiter ;
select @res;
call p1(2,5,@res);
select @res;#查看
在pymysql中使用事务处理:
import pymysql
conn=pymysql.connect(
user="root",
password="root",
database="day48",
charset="utf8"
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.callproc("p1",(2,5,1))#在pymysql中会给参数全部创建对应的变量
#命名方式 @_p1_0 @_p1_1 @_p1_2
print(cursor.fetchall())#如果过程中包含多个查询语句 得到的是第一个查询语句
#的结果
cursor.execute("select @_p1_2")
print(cursor.fetchone())
注:在pymython中是自动实现事务的
5.函数:
自定义函数语法:
CREATE FUNCTION f_name(paramters)
returns dataType
return value;
例子:
create function addf(a int,b int)
returens int
return a+b;
# 执行函数
select addf(1,2)
注意:在定义函数的时候 只能写mysql的逻辑语言 但不能出现sql语句
mysql 有自己的编程语言
sql 结构化语句
6.数据的备份与恢复
使用mysqldump -uroot -p密码 db_name [table_name,,,]>fileName.sql
#示例:
#单库备份
mysqldump -uroot -p123 db1 > db1.sql
mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql
#多库备份
mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql
#备份所有库
mysqldump -uroot -p123 --all-databases > all.sql
1.退出数据库后
mysql -u -p < filename.sql;
2.不用退出数据库
2.1 创建空数据库
2.2选择数据库
2.3然后使用source filename; 来进行还原
use db1;
source /root/db1.sql
数据库迁移:
务必保证在相同版本之间迁移:
# mysqldump -h 源IP -uroot -p123 --databases db1 | mysql -h 目标IP -uroot -p456
7.流程控制
if语句的使用:
if 条件 then 语句; end if;
第二种 if elseif if 条件 then 语句1; elseif 条件 then 语句2; else 语句3; end if;
案例:编写过程 实现 输入一个整数type 范围 1 - 2 输出 type=1 or type=2 or type=other;
create procedure showType(in type int,out result char(20))
begin
if type = 1 then
set result = "type = 1";
elseif type = 2 then
set result = "type = 2";
else
set result = "type = other";
end if;
end
CASE 语句:
大体意思与Swtich一样的 你给我一个值 我对它进行选择 然后执行匹配上的语句 语法:
create procedure caseTest(in type int)
begin
CASE type
when 1 then select "type = 1";
when 2 then select "type = 2";
else select "type = other";
end case;
end
定义变量:
declare 变量名 类型 default 值; 例如: declare i int default 0;
WHILE循环
循环输出10次hello mysql
create procedure showHello()
begin
declare i int default 0;
while i < 10 do
select "hello mysql";
set i = i + 1;
end while;
end
LOOP循环的:
没有条件 需要自己定义结束语句 语法:
输出十次hello mysql;
create procedure showloop()
begin
declare i int default 0;
aloop: LOOP
select "hello loop";
set i = i + 1;
if i > 9 then leave aloop;
end if;
end LOOP aloop;
end
REPEAT循环:
#类似do while
#输出10次hello repeat
create procedure showRepeat()
begin
declare i int default 0;
repeat
select "hello repeat";
set i = i + 1;
until i > 9
end repeat;
end
#输出0-100之间的奇数
create procedure showjishu()
begin
declare i int default 0;
aloop: loop
set i = i + 1;
if i >= 101 then leave aloop; end if;
if i % 2 = 0 then iterate aloop; end if;
select i;
end loop aloop;
end