该系统Support职员报告在双击查看该学业时报上边

2019-10-05 作者:数据库   |   浏览(74)

转载自:

1.WITH ROLLUP:在分组的基础上进行统计数据。

什么是存储过程

简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;

ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用;

今天遇到这样一个问题:一个系统的作业需要给系统Support人员开放SQL Agent下作业的查看、执行权限。数据库版本为SQL Server 2014 SP2,给这个系统Support人员的NT账号授予msdb数据库下面权限后:

什么是触发器

简单的说,就是一张表发生了某件事(插入、删除、更新操作),然后自动触发了预先编写好的若干条SQL语句的执行;

例子:首先在name字段上进行分组,然后在分组的基础上进行统计

有哪些特性

有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;

函数的普遍特性:模块化,封装,代码复用;

速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;

 

 

特点及作用

特点:触发事件的操作和触发器里的SQL语句是一个事务操作,具有原子性,要么全部执行,要么都不执行;

作用:保证数据的完整性,起到约束的作用;

mysql> SELECT name, SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
 -------- -------------- 
| name   | singin_count |
 -------- -------------- 
| 小丽 |            2 |
| 小明 |            7 |
| 小王 |            7 |
| NULL |           16 |
 -------- -------------- 
4 rows in set (0.00 sec)

2.coalesce 
select coalesce(a,b,c);

存储过程的基本格式如下:

小鱼儿玄机30码姐妹 1

-- 声明结束符
-- 创建存储过程
DELIMITER $  -- 声明存储过程的结束符
CREATE PROCEDURE pro_test()    --存储过程名称(参数列表)
BEGIN
    -- 可以写多个sql语句;      -- sql语句 流程控制
    SELECT * FROM employee;
END $  -- 结束 结束符

-- 执行存储过程
CALL pro_test();   -- CALL 存储过程名称(参数);

-- 删除存储过程
DROP PROCEDURE pro_test;

参数:
IN:   表示输入参数,可以携带数据带存储过程中
OUT: 表示输出参数,可以从存储过程中返回结果
INOUT: 表示输入输出参数,既可以输入功能,也可以输出功能

小鱼儿玄机30码姐妹 2

 

1. 带有输入参数的存储过程

小鱼儿玄机30码姐妹,    需求:传入一个员工的id,查询员工信息

小鱼儿玄机30码姐妹 3

DELIMITER $
CREATE PROCEDURE pro_findById(IN eid INT)  -- IN: 输入参数
BEGIN
    SELECT * FROM employee WHERE id=eid;
END $ 

-- 调用
CALL pro_findById(4);

小鱼儿玄机30码姐妹 4

 

2. 带有输出参数的存储过程

DELIMITER $
CREATE PROCEDURE pro_testOut(OUT str VARCHAR(20))  -- OUT:输出参数
BEGIN
        -- 给参数赋值
    SET str='hellojava';
END $

如何接受返回参数的值呢?这里涉及到MySQL的变量

 

MySQL变量一共有三种:

全局变量

全局变量又叫内置变量,是mysql数据库内置的变量 ,对所有连接都起作用。

查看所有全局变量: show variables

查看某个全局变量: select @@变量名

修改全局变量: set 变量名=新值

character_set_client: mysql服务器的接收数据的编码

character_set_results:mysql服务器输出数据的编码

 

会话变量

只存在于当前客户端与数据库服务器端的一次连接当中。如果连接断开,那么会话变量全部丢失!

定义会话变量: set @变量=值

查看会话变量: select @变量

局部变量

在存储过程中使用的变量就叫局部变量。只要存储过程执行完毕,局部变量就丢失。

 

回到上面这个存储过程,如何接受返回参数的值呢?

定义一个会话变量name, 使用name会话变量接收存储过程的返回值

CALL pro_testOut(@NAME);

查看变量值

SELECT @NAME;

 

3. 带有输入输出参数的存储过程

小鱼儿玄机30码姐妹 5

DELIMITER $
CREATE PROCEDURE pro_testInOut(INOUT n INT)  -- INOUT: 输入输出参数
BEGIN
   -- 查看变量
   SELECT n;
   SET n =500;
END $

-- 调用
SET @n=10;

CALL pro_testInOut(@n);

SELECT @n;

小鱼儿玄机30码姐妹 6

 

4. 带有条件判断的存储过程

需求:输入一个整数,如果1,则返回“星期一”,如果2,返回“星期二”,如果3,返回“星期三”。其他数字,返回“错误输入”;

小鱼儿玄机30码姐妹 7

DELIMITER $
CREATE PROCEDURE pro_testIf(IN num INT,OUT str VARCHAR(20))
BEGIN
    IF num=1 THEN
        SET str='星期一';
    ELSEIF num=2 THEN
        SET str='星期二';
    ELSEIF num=3 THEN
        SET str='星期三';
    ELSE
        SET str='输入错误';
    END IF;
END $

--调用
CALL pro_testIf(4,@str);

SELECT @str;

小鱼儿玄机30码姐妹 8

 

5. 带有循环功能的存储过程

需求: 输入一个整数,求和。例如,输入100,统计1-100的和

小鱼儿玄机30码姐妹 9

DELIMITER $
CREATE PROCEDURE pro_testWhile(IN num INT,OUT result INT)
BEGIN
    -- 定义一个局部变量
    DECLARE i INT DEFAULT 1;
    DECLARE vsum INT DEFAULT 0;
    WHILE i<=num DO
          SET vsum = vsum i;
          SET i=i 1;
    END WHILE;
    SET result=vsum;
END $

--调用
CALL pro_testWhile(100,@result);

SELECT @result;

小鱼儿玄机30码姐妹 10

 

6. 使用查询的结果赋值给变量(INTO)

小鱼儿玄机30码姐妹 11

DELIMITER $
CREATE PROCEDURE pro_findById2(IN eid INT,OUT vname VARCHAR(20) )
BEGIN
    SELECT empName INTO vname FROM employee WHERE id=eid;
END $

--调用
CALL pro_findById2(1,@NAME);

SELECT @NAME;

小鱼儿玄机30码姐妹 12

 

小鱼儿玄机30码姐妹 13

例子:创建触发器,记录表的增、删、改操作记录

接下来将创建user和user_history表,以及三个触发器tri_insert_user、tri_update_user、tri_delete_user,分别对应user表的增、删、改三件事;

  • 创建user表;

    1 DROP TABLE IF EXISTS user; 2 CREATE TABLE user ( 3 id bigint(20) NOT NULL AUTO_INCREMENT, 4 account varchar(255) DEFAULT NULL, 5 name varchar(255) DEFAULT NULL, 6 address varchar(255) DEFAULT NULL, 7 PRIMARY KEY (id) 8 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  • 创建对user表操作历史表;

    DROP TABLE IF EXISTS user_history; CREATE TABLE user_history ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, operatetype varchar(200) NOT NULL, operatetime datetime NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  • 创建user表插入事件对应的触发器tri_insert_user;

几点说明:

DELIMITER:改变输入的结束符,默认情况下输入结束符是分号;,这里把它改成了两个分号;;,这样做的目的是把多条含分号的语句做个封装,全部输入完之后一起执行,而不是一遇到默认的分号结束符就自动执行;

new:当触发插入和更新事件时可用,指向的是被操作的记录

old: 当触发删除和更新事件时可用,指向的是被操作的记录

小鱼儿玄机30码姐妹 14

DROP TRIGGER IF EXISTS `tri_insert_user`;
DELIMITER ;;
CREATE TRIGGER `tri_insert_user` AFTER INSERT ON `user` FOR EACH ROW begin
    INSERT INTO user_history(user_id, operatetype, operatetime) VALUES (new.id, 'add a user',  now());
end
;;
DELIMITER ;

小鱼儿玄机30码姐妹 15

  • 创建user表更新事件对应的触发器tri_update_user;

小鱼儿玄机30码姐妹 16

DROP TRIGGER IF EXISTS `tri_update_user`;
DELIMITER ;;
CREATE TRIGGER `tri_update_user` AFTER UPDATE ON `user` FOR EACH ROW begin
    INSERT INTO user_history(user_id,operatetype, operatetime) VALUES (new.id, 'update a user', now());
end
;;
DELIMITER ;

小鱼儿玄机30码姐妹 17

  • 创建user表删除事件对应的触发器tri_delete_user;

小鱼儿玄机30码姐妹 18

DROP TRIGGER IF EXISTS `tri_delete_user`;
DELIMITER ;;
CREATE TRIGGER `tri_delete_user` AFTER DELETE ON `user` FOR EACH ROW begin
    INSERT INTO user_history(user_id, operatetype, operatetime) VALUES (old.id, 'delete a user', now());
end
;;
DELIMITER ;

小鱼儿玄机30码姐妹 19

  • 至此,全部表及触发器创建完成,开始验证结果,分别做插入、修改、删除事件,执行以下语句,观察user_history是否自动产生操作记录;

小鱼儿玄机30码姐妹 20

INSERT INTO user(account, name, address) VALUES ('user1', 'user1', 'user1');
INSERT INTO user(account, name, address) VALUES ('user2', 'user2', 'user2');

UPDATE user SET name = 'user3', account = 'user3', address='user3' where name='user1';

DELETE FROM `user` where name = 'user2';

小鱼儿玄机30码姐妹 21

  • 观察结果user表和user_history表的结果,操作记录已产生,说明触发器工作正常;

小鱼儿玄机30码姐妹 22

参数说明:如果a==null,则选择b;如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)。

存储过程弊端

不同数据库,语法差别很大,移植困难,换了数据库,需要重新编写;

不好管理,把过多业务逻辑写在存储过程不好维护,不利于分层管理,容易混乱,一般存储过程适用于个别对性能要求较高的业务,其它的必要性不是很大;

...

 

弊端

增加程序的复杂度,有些业务逻辑在代码中处理,有些业务逻辑用触发器处理,会使后期维护变得困难;

 

 

 

以下实例中如果名字为空我们使用总数代替:

该系统Support人员反馈在双击查看该作业时报下面错误。于是我测试,验证了一下这个权限是否OK,

mysql> SELECT coalesce(name, '总数'), SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
 -------------------------- -------------- 
| coalesce(name, '总数') | singin_count |
 -------------------------- -------------- 
| 小丽                   |            2 |
| 小明                   |            7 |
| 小王                   |            7 |
| 总数                   |           16 |
 -------------------------- -------------- 
4 rows in set (0.01 sec)

3.NULL值
(1)IS NULL: 当列的值是 NULL,此运算符返回 true。
(2)IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。

 

本文由小鱼儿玄机30码发布于数据库,转载请注明出处:该系统Support职员报告在双击查看该学业时报上边

关键词: 小鱼儿玄机30码