----------------------------------------------视图---------------------------------------------
视图是什么
#视图是有一条sql语句的查询结果构成的虚拟表 #其不是物理存在的 使用方式与普通表相同
视图的作用
#1.简化sql语句的编写 #2.限制可以查看的数据 可以使用权限来完成 权限某一个库 的某一个表 的某一个字段 例如:一张表存储了所有人的工资 但是每个员工只能看自己的工资信息 那就可以用视图来限制
创建视图
#语法:CREATE VIEW 视图名称 AS SQL语句 #语法:CREATE or repalce] VIEW 视图名称 [(column_list)] AS SQL语句 加上or repiale 时如果已经视图存在相同视图则替换原有视图 column_list指定哪些字段要出现在视图中
视图的增删改查(视图的增删改查会同步到原始表)
视图是一张虚拟表 所以使用方式与普通表没有任何区别 #**查看视图** 1.desc view_name; //查看数据结构 索引信息不会体现在视图中 2.show create view view_name;//查看 创建语句 #**修改视图** alter view view_name as select_statement #**删除视图** drop view view_name
案例之简化sql语句
create database db02 charset utf8; use db02 create table student( s_id int(3), name varchar(20), math float, chinese float ); insert into student values(1,'tom',80,70),(2,'jack',80,80),(3,'rose',60,75); create table stu_info( s_id int(3), class varchar(50), addr varchar(100) ); insert into stu_info values(1,'二班','安徽'),(2,'二班','湖南'),(3,'三班','黑龙江');
#不使用视图,每次查询信息,都需要连接查询 select student.s_id,student.name ,stu_info.class from student,stu_info where student.s_id=stu_info.s_id; #创建视图 create view view_student as select student.s_id,student.name ,stu_info.class from student,stu_info where student.s_id=stu_info.s_id;
#以后再查询,只需要select *from view_student,不需要再每次连接查询,简化代码
案例二、隔离数据(设置权限)
# 创建工资表 create table salarys( id int primary key, name char(10), salary double, dept char(10) ); insert into salarys values (1,"刘强东",900000,"市场"), (2,"马云",800090,"市场"), (3,"李彦宏",989090,"财务"), (4,"马化腾",87879999,"财务");
#设置一个部门都可观看 mysql> create view dept_view as select *from salarys where dept = "财务"; Query OK, 0 rows affected (0.13 sec) mysql> select *from dept_view; +----+-----------+----------+--------+ | id | name | salary | dept | +----+-----------+----------+--------+ | 3 | 李彦宏 | 989090 | 财务 | | 4 | 马化腾 | 87879999 | 财务 | +----+-----------+----------+--------+ 2 rows in set (0.00 sec) #设置仅可自己看自己的薪资 mysql> create view self_view as select *from salarys where name = "李彦宏"; Query OK, 0 rows affected (1.85 sec) mysql> select *from self_view; +----+-----------+--------+--------+ | id | name | salary | dept | +----+-----------+--------+--------+ | 3 | 李彦宏 | 989090 | 财务 | +----+-----------+--------+--------+ 1 row in set (0.01 sec)
--------------------------------------------------------触发器---------------------------------------------------------------------------
### 什么是触发器 触发器是一段与某个表相关的mysql程序 当这个表在某个时间点发生了某种事件时 将会自动执行相应的触发器程序 ### 何时使用触发器 当我们想要在一个表记录被更新时做一些操作时就可以使用触发器 但是我们完全可以在python中来完成这个事情,因为python的扩展性更强,语法更简单 ### 创建触发器 ```mysql 语法: CREATE TRIGGER t_name t_time t_event ON table_name FOR EACH ROW begin stmts..... end ``` 支持的时间点(t_time):时间发生前和发生前后 before|after 支持的事件(t_event): update insert delete 在触发器中可以访问到将被修改的那一行数据 根据事件不同 能访问也不同 update 可用OLD访问旧数据 NEW访问新数据 insert 可用NEW访问新数据 delete 可用OLD访问旧数据 可以将NEW和OLD看做一个对象其中封装了这条数据的所有字段 案例: 有cmd表和错误日志表,需求:在cmd执行失败时自动将信息存储到错误日志表中 ```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 ); # 创建触发器 delimiter // create trigger trigger1 after insert on cmd for each row begin if new.success = "no" then insert into errlog values(null,new.cmd,new.sub_time); end if; end// delimiter ; #往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志 INSERT INTO cmd ( USER, priv, cmd, sub_time, success ) VALUES ('jerry','0755','ls -l /etc',NOW(),'yes'), ('jerry','0755','cat /etc/passwd',NOW(),'no'), ('jerry','0755','useradd xxx',NOW(),'no'), ('jerry','0755','ps aux',NOW(),'yes'); # 查看错误日志表中的记录是否有自动插入 select *from errlog; ``` `delimiter` 用于修改默认的行结束符 ,由于在触发器中有多条sql语句他们需要使用分号来结束,但是触发器是一个整体,所以我们需要先更换默认的结束符,在触发器编写完后在将结束符设置回分号 注意: 1.外键不能触发事件 主表删除了某个主键 从表也会相应删除 但是并不会执行触发器 2.触发器中不能使用事务,不能使用select 查询数据 3.相同时间点的相同事件的触发器 不能同时存在 ### 删除触发器 ```mysql 语法: drop trigger trigger_name; 案例: drop trigger trigger1; ``` 同样的这种需求我们完全可以在python中来完成! mysql最想完成的事情是将所有能处理的逻辑全部放到mysql中,那样一来应用程序开发者的活儿就变少了,相应的数据库管理员的工资就高了,可惜大多中小公司都没有专门的DBA; **疑惑:**修改行结束符后,触发器内的sql语句任然是以分号结束,为什么? 实际上在mysql中输入分号回车,mysql会立即将语句发送给服务器端,修改行结束符仅仅是告诉mysql客户端,语句没有写完,不要立即发送! 练习: 编写触发器用于将更新记录插入另一个表 ```mysql create table blog(id int primary key auto_increment,content text,b_id int,foreign key(b_id) references blog(id),update_time timestamp); create table blogs(id int primary key auto_increment,content text,b_id int,foreign key(b_id) references blog(id),update_time timestamp); delimiter // create trigger t10 before update on blog for each row begin if new.content != old.content then insert into blogs values(null,new.content,new.id,null); end if; end// delimiter ;
-------------------------------------------------------事务---------------------------------------------
#MySQL 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。 #1、在MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务 #2、事务用来管理insert,update,delete语句 #3、事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行
mysql> create table user( -> id int primary key auto_increment, -> name char(32), -> balance int -> ); mysql> insert into user(name,balance) -> values -> ('hby',1000), -> ('pdun',1000), -> ('lb',1000);
#start transaction; 开启事务 update user set balance = balance-100 where name = 'hby'; update user set balance = balance-100 where name = 'pdun'; #rollback; #commit; ------------------------------------------------------------------------ #start transaction; update user set balance = balance-100 where name = 'hby'; update user set balance = balance+100 where name = 'pdun'; #savepoint p; update user set balance = balance+100 where name = 'pdun'; #rollback to p;