MySQL 视图.存储过程.触发器.函数.事务.动态执行sql

1.MySQL 视图是一张虚拟的表,是查询的结果集合。仅作查询使用

  创建视图:

create view v1 as
select * from coursetostudent
left join course on coursetostudent.course_id = course.cid
left join student on coursetostudent.student_id = student.sid

  删除视图:

  drop view v1;

  修改视图:

alter view v1 as 
select course_name,student_name,age,sid from coursetostudent
left join course on coursetostudent.course_id = course.cid
left join student on coursetostudent.student_id = student.sid

  查询视图:

  select * from v1;

 

2.存储过程: sql语句的集合,调用存储过程,sql语句按顺序执行

   创建存储过程:

delimiter $$        -- 让终端以$$作为结束符

drop procedure if exists proc_p1 $$   -- 如果存在改存储过程,则删除
create procedure proc_p1()      -- 创建存储过程
begin 
    select * from course;      
end $$

delimiter ;         -- 恢复终端以; 作为结束符

call proc_p1();      -- 调用无参数的存储过程

   带参数的存储过程:

    其参数有三类:

      in          仅用于传入参数用

      out        仅用于返回值用

      inout     既可以传入又可以当作返回值

delimiter $$
drop procedure if exists proc_p1 $$
create procedure proc_p1(
in aa int,
inout bb int,
out cc int
)
begin 
    if aa = 1 then 
        set bb = bb + aa;
    elseif aa = 2 then
        set bb = bb * aa;
    else 
        set bb = bb + 3;
    end if;
    set cc = bb + 200;
end $$
delimiter ;

set @m = 2;
set @n = 3;
call proc_p1(3,@m,@n);
select @m,@n;
View Code

 3. pysql 执行存储过程

delimiter $$
drop procedure if exists proc_p1 $$
create procedure proc_p1(
in aa char(10),
inout bb int,
out cc int
)
begin 
declare dd int default 3;
declare ee int;
set ee = 5;
select * from course where course.course_name = aa;
set bb = bb + dd;
set cc = bb * ee;
end $$
delimiter ;

set @m =2;
set @n =3;
call proc_p1('语文',@m,@n);
select @m,@n;
存储过程
#!/usr/bin/env python
# --*-- encoding:utf-8 --*--

import pymysql
# latin-1' codec can't encode character  ...错误   解决方案:use_unicode=True, charset="utf8
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbone', use_unicode=True, charset="utf8")
cursor=conn.cursor(pymysql.cursors.DictCursor)
#执行存储过程
cursor.callproc('proc_p1',args=('语文',2,3))
# 取存储过程的查询结果
result = cursor.fetchall()
#执行获取存储过程的sql
cursor.execute('select @_proc_p1_0, @_proc_p1_1, @_proc_p1_2')
# 取存储过程的返回值
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
py

  将查出来的结果赋值给一个变量  :select into

delimiter $$
drop procedure if exists proc_p2 $$
create procedure proc_p2()
begin 
    declare mm int default 0;
    select course_id into mm from coursetostudent where student_id = 8;
    select course_name from course where cid = mm;
end $$
delimiter ;

call proc_p2();
存储过程

 4.触发器

  对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为。

  创建触发器:

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 插入后
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 删除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 删除后
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新后
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END
View Code

  特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。

使用:

delimiter $$
drop trigger if exists tg_before_insert_one $$
create trigger tg_before_insert_one before insert on course for each row 
begin 
update student set student_name = '张三1' where student_name = '张三';
end $$
delimiter ;

删除触发器:

  drop trigger tg_before_insert_one;

使用触发器:

  insert into course(course_name) values('美术')

delimiter $$
drop trigger if exists tg_before_insert_two;
create trigger tg_before_insert_two before insert on course for each row
begin 
    if new.course_name = '体育' then 
        insert into student(student_name,age) values(new.course_name,19);
    elseif new.course_name = '计算机' then 
        insert into student(student_name,age) values(new.course_name,20);
    else
        insert into student(student_name,age) values(new.course_name,21);
    end if;
end $$
delimiter ;

insert into course(course_name) values('体育');
demo

注:更新本表的触发器:不是使用update,而是set

查询触发器,储存过程,函数:

-- show triggers/g;
-- show procedure status;
-- show create procedure proc_p1;
-- show function status;

 

5.函数。在函数内部无法返回结果集,必须通过select func();调用。

CHAR_LENGTH(str)
        返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
        对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。

    CONCAT(str1,str2,...)
        字符串拼接
        如有任何一个参数为NULL ,则返回值为 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定义连接符)
        CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

    CONV(N,from_base,to_base)
        进制转换
        例如:
            SELECT CONV('a',16,2); 表示将 a 由16进制转换为2进制字符串表示

    FORMAT(X,D)
        将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
        例如:
            SELECT FORMAT(12332.1,4); 结果为: '12,332.1000'
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替换位置其实位置
            len:替换的长度
            newstr:新字符串
        特别的:
            如果pos超过原字符串长度,则返回原字符串
            如果len超过原字符串长度,则由新字符串完全替换
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一个出现位置。

    LEFT(str,len)
        返回字符串str 从开始的len位置的子序列字符。

    LOWER(str)
        变小写

    UPPER(str)
        变大写

    LTRIM(str)
        返回字符串 str ,其引导空格字符被删除。
    RTRIM(str)
        返回字符串 str ,结尾空格字符被删去。
    SUBSTRING(str,pos,len)
        获取字符串子序列

    LOCATE(substr,str,pos)
        获取子序列索引位置

    REPEAT(str,count)
        返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。
        若 count <= 0,则返回一个空字符串。
        若str 或 countNULL,则返回 NULLREPLACE(str,from_str,to_str)
        返回字符串str 以及所有被字符串to_str替代的字符串from_str 。
    REVERSE(str)
        返回字符串 str ,顺序和字符顺序相反。
    RIGHT(str,len)
        从字符串str 开始,返回从后边开始len个字符组成的子序列

    SPACE(N)
        返回一个由N空格组成的字符串。

    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

        mysql> SELECT SUBSTRING('Quadratically',5);
            -> 'ratically'

        mysql> SELECT SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'

        mysql> SELECT SUBSTRING('Quadratically',5,6);
            -> 'ratica'

        mysql> SELECT SUBSTRING('Sakila', -3);
            -> 'ila'

        mysql> SELECT SUBSTRING('Sakila', -5, 3);
            -> 'aki'

        mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
            -> 'ki'

    TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str)
        返回字符串 str , 其中所有remstr 前缀和/或后缀都已被删除。若分类符BOTH、LEADIN或TRAILING中没有一个是给定的,则假设为BOTH 。 remstr 为可选项,在未指定情况下,可删除空格。

        mysql> SELECT TRIM('  bar   ');
                -> 'bar'

        mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
                -> 'barxxx'

        mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
                -> 'bar'

        mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
                -> 'barx'

部分内置函数
部分内置函数

自定义函数:

delimiter $$
drop function if exists func $$
create function func(
aa int ,
bb int 
)
returns int
begin 
declare cc int default 5;
declare dd int;
set cc = 6;
set dd = aa + bb + cc;
return(dd);
end $$
delimiter ;

删除函数: drop function func;

执行函数:

# 获取返回值
declare @i VARCHAR(32);
select UPPER('abcdefg') into @i;
SELECT @i;


# 在查询中使用
select func(11,cid),cid from course;

 

6.事务 :多个sql语句 作为原子性操作,只要某一个sql语句出错,则回滚到最初的状态,保证数据库的完整性

  包含事务的存储过程:类似于try except

delimiter $$
drop procedure if exists p1;
create PROCEDURE p1(
    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 assert = assert-10 where username = 'abc';
    update user set assert = assert+10 where username = 'bcd';
  COMMIT; 
 
  -- SUCCESS 
  set p_return_code = 0; 
 
  END $$
delimiter ;

执行调用:

set @res = 0;
call p1(@res);
select @res;

 

7.条件,循环,动态执行SQL

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 ;
if条件
delimiter $$
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END $$
delimiter ;
while 循环
delimiter $$
CREATE PROCEDURE proc_repeat ()
BEGIN

    DECLARE i INT ;
    SET i = 0 ;
    repeat
        select i;
        set i = i + 1;
        until i >= 5
    end repeat;

END $$
delimiter ;
repeat循环
delimiter $$
CREATE PROCEDURE proc_loop ()
BEGIN
    
    declare i int default 0;
    loop_label: loop
        select i;
        set i=i+1;
        if i>=5 then
            leave loop_label;
            end if;
    end loop;

END $$
delimiter ;
loop 循环

动态执行sql:也可以防止sql注入

delimiter $$
DROP PROCEDURE IF EXISTS proc_sql  $$
CREATE PROCEDURE proc_sql ()
BEGIN
    declare p1 int;
    set p1 = 11;
    set @p1 = p1;

    PREPARE prod FROM 'select * from tb2 where nid > ?';
    EXECUTE prod USING @p1;
    DEALLOCATE prepare prod; 

END $$
delimiter ;
动态执行sql

 demo:

delimiter $$
DROP PROCEDURE IF EXISTS proc_sql  $$
CREATE PROCEDURE proc_sql (
in str_sql char(100),
in cid int(5)
)
BEGIN
        set @strsql = str_sql;
        set @cid = cid;
    PREPARE prod FROM @strsql;
    EXECUTE prod USING @cid;
    DEALLOCATE prepare prod; 

END $$
delimiter ;
存储过程
import pymysql

conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbone',use_unicode=True, charset="utf8")
cursor=conn.cursor(pymysql.cursors.DictCursor)
strsql = 'select * from course where cid > ?'
cursor.callproc('proc_sql',(strsql,3))
result = cursor.fetchall();
print(result)
conn.commit()
cursor.close()
conn.close()
py

 

 mysql变量:
  http://www.cnblogs.com/zhuawang/p/4090916.html

posted @ 2017-06-05 20:35  1916  阅读(260)  评论(0)    收藏  举报