视图 触发器 事物 储存过程 内置函数 流控制

---恢复内容开始---

视图

视图
什么是视图?
,将这种虚拟表保存下来
它就变成了一个视图

为什么要用视图?
当频繁需要用到多张表的连表结果,你就可以事先生成好视图
之后直接调用即可,避免了反复写连表操作的sql语句


如何使用?
    create view teacher_course as select * from teacher INNER JOIN course
    on teacher.tid = course.teacher_id;
    1.视图只有表结构,视图中的数据还是来源于原来的表
2.不要改动视图表中的数据
3.一般情况下不会频繁的使用视图来写业务逻辑
触发器
到达某个条件自动触发
当你在对数据进行增 删 改的情况下会自动触发触发器的运行

触发器分为六种情况
增前 增后 删前 删后 改前 改后
固定语法结构
create trigger 触发器的名字 after/before insert/update/delete on 表名 for each row
begin
sql语句
end

delimiter 只对当前窗口有效

 可以修改MySQL默认的结束符(;)
            delimiter $$  # 只对当前窗口有效
            create trigger tri_before_insert_user before insert on user for each row
            begin
                select * from user
            end $$
            delimiter ;
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 $$  # 将mysql默认的结束符由;换成$$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then  # 新记录都会被MySQL封装成NEW对象
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;  # 结束之后记得再改回来,不然后面结束符就都是$$了

#往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
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');

# 查询errlog表记录
select * from errlog;
# 删除触发器
drop trigger tri_after_insert_cmd;
事务 有4个属性:原子性、一致性、隔离性、持久性 ACID 特性

什么是事务

​   开启一个事务可以包含一些sql语句,这些sql语句要么同时成功
​    要么一个都别想成功,称之为事务的原子性

 

事务的作用

        保证了对数据操作的数据安全性

案例:用交行的卡操作建行ATM机给工商的账户转钱

原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,
并发执行的各个事务之间不能互相干扰。 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
接下来的其他操作或故障不应该对其有任何影响。
如何开启事务
start transaction 必出要先开启事务才能 执行事务
事务回滚
rollback
永久性更改
commit
create table user(
id int primary key auto_increment,
name char(32),
balance int
);

insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000);

# 修改数据之前先开启事务操作
start transaction;

# 修改操作
update user set balance=900 where name='wsb'; #买支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #卖家拿到90元

# 回滚到上一个状态
rollback;

# 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
commit;
"""开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作"""

# 站在python代码的角度,应该实现的伪代码逻辑,
try:
    update user set balance=900 where name='wsb'; #买支付100元
    update user set balance=1010 where name='egon'; #中介拿走10元
    update user set balance=1090 where name='ysb'; #卖家拿到90元
except 异常:
    rollback;
else:
    commit;

# 那如何检测异常?
存储过程  
就类似于python中的自定义函数

内部封装了操作数据库的sql语句,后续想要实现相应的操作 只需要调用存储过程即可
    语法结果
        delimiter $$
        create procedure p1()
        begin
            select * from user;
        end $$
        delimiter ;

call p1() 相当于加括号调用
  带参数的
        delimiter $$
        create procedure p1(
            in m int,  # 不能被返回出去
            in n int,
            out res int,  # 可以被返回
            inout xxx int,  # 既可以进又可以出
        )
        begin
            select * from user;
        end $$
        delimiter ;
大前提:存储过程在哪个库下面创建的只能在对应的库下面才能使用!!!

set @res 就相当于设置了一个全局变量
delimiter $$
create procedure p1(
    in m int,  # in表示这个参数必须只能是传入不能被返回出去
    in n int,
    out res int  # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
)
begin
    select tname from teacher where tid > m and tid < n;
    set res=0;  # 就类似于是一个标志位 用来标识存储器是否执行成功
end $$
delimiter ;

set @res = 10   # 设置一个变量与值的绑定关系

调用存储过程 将变量@res传入

之后通过
select @res
查看存储过程执行完成后的返回结果
pymysql 中 的存储过程  cursor.callproc('函数名',(参数 不用设置全局变量))
import pymysql

conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = '123',
    database = 'day38',
    charset = 'utf8',
    autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# call p1()  mysql中调用
# callproc()  pymysql中调用
cursor.callproc('p1',(1,5,10))
# 内部自动用变量名存储了对应的值
print(cursor.fetchall())
"""
@_p1_0=1
@_p1_1=5
@_p1_2=10

会自动把传入的参数 设置为 这几个 @_存储过程名_索引值
""" cursor.execute('select @_p1_0') print(cursor.fetchall()) cursor.execute('select @_p1_1') print(cursor.fetchall()) cursor.execute('select @_p1_2') print(cursor.fetchall())
存储过程与事务使用举例(了解)
delimiter //
create PROCEDURE p5(
    OUT p_return_code tinyint
)
BEGIN
    DECLARE exit handler for sqlexception
    BEGIN
        -- ERROR
        set p_return_code = 1;
        rollback;
    END;


  DECLARE exit handler for sqlwarning
  BEGIN
      -- WARNING
      set p_return_code = 2;
      rollback;
  END;

  START TRANSACTION;
      update user set balance=900 where id =1;
      update user123 set balance=1010 where id = 2;
      update user set balance=1090 where id =3;
  COMMIT;

  -- SUCCESS
  set p_return_code = 0; #0代表执行成功


END //
delimiter ;
函数
你可以看成内置函数

注意与存储过程的区别,mysql内置的函数只能在sql语句中使用!

参考博客:<http://www.cnblogs.com/linhaifeng/articles/7495918.html#_label2>

CREATE TABLE blog (
    id INT PRIMARY KEY auto_increment,
    NAME CHAR (32),
    sub_time datetime
);

INSERT INTO blog (NAME, sub_time)
VALUES
    ('第1篇','2015-03-01 11:31:21'),
    ('第2篇','2015-03-11 16:31:21'),
    ('第3篇','2016-07-01 10:21:31'),
    ('第4篇','2016-07-22 09:23:21'),
    ('第5篇','2016-07-23 10:11:11'),
    ('第6篇','2016-07-25 11:21:31'),
    ('第7篇','2017-03-01 15:33:21'),
    ('第8篇','2017-03-01 17:32:21'),
    ('第9篇','2017-03-01 18:31:21');

select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
流程控制 
if
# if条件语句
delimiter //
CREATE PROCEDURE proc_if ()
BEGIN
    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END //
delimiter ;


while
delimiter //
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;  声明一个关键字叫 num
        SET num = num + 1 ;
    END WHILE ;

END //
delimiter ;



















---恢复内容结束---

猜你喜欢

转载自www.cnblogs.com/lddragon/p/11404771.html