MySql创建函数与过程,触发器, shell脚本与sql的相互调用。

一:函数

1:创建数据库和表deptartment,

mysql> use DBSC;
Database changed
mysql> create table deptartment(dept_name varchar(20),
-> budget bigint(20),
-> building varchar(20));
Query OK, 0 rows affected mysql> insert into deptartment values('电子系',10000,'2号楼');
Query OK, 1 row affected mysql> insert into deptartment values('通信系',40000,'3号楼');
Query OK, 1 row affected mysql> insert into deptartment values('计算机系',100000,'6号楼');

2:创建表 instructor

create table instructor(id int,
salary int,
dept_name varchar(20),
foreign key(dept_name) references deptartment(dept_name)) ENGINE=innodb DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

提示错误:1005 - Can't create table 'dbsc.instructor' (errno: 150)

修改数据表deptartment 的执行引擎:

alter table deptartment engine=innodb;

依然提示错误,因为外键约束的字段必须为被应用的表的主键。 修改 deptartment  中dept_name的定义。

alter table deptartment modify dept_name varchar(20) primary key;

3:向表instructor中添加数据。

mysql> insert into instructor values(1,1000,'电子系');
Query OK, 1 row affected mysql> insert into instructor values(2,1000,'电子系');
Query OK, 1 row affected mysql> insert into instructor values(3,1000,'电子系');
Query OK, 1 row affected mysql> insert into instructor values(4,1000,'电子系');
Query OK, 1 row affected mysql> insert into instructor values(5,1000,'电子系');
Query OK, 1 row affected mysql> insert into instructor values(1,1000,'通信系');
Query OK, 1 row affected mysql> insert into instructor values(2,1000,'通信系');
Query OK, 1 row affected mysql> insert into instructor values(3,1000,'通信系');
Query OK, 1 row affected mysql> insert into instructor values(1,1000,'计算机系');
Query OK, 1 row affected

4:创建函数

创建函数提示错误: https://blog.csdn.net/topasstem8/article/details/8216740/

1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

修改

mysql> set global log_bin_trust_function_creators=TRUE;

创建有参函数: 数据库默认语句分隔符为;,DELIMITER //  将数据库语句执行分隔符改为//。

DELIMITER //
create function dept_count(deptName varchar(20))
returns integer
begin
return(
select count(*)
from instructor
where instructor.dept_name = deptName);
end//
DELIMITER ;

5:使用函数,  求出instructor中院系教师大于2的deptartment

mysql> select * from deptartment where dept_count(dept_name)>2;
+-----------+--------+----------+
| dept_name | budget | building |
+-----------+--------+----------+
| 电子系 | 10000 | 2号楼 |
| 通信系 | 40000 | 3号楼 |
+-----------+--------+----------+
2 rows in set

https://www.cnblogs.com/taiguyiba/p/6619027.html

6: 在函数中定义变量,返回赋值后的变量。

mysql> DELIMITER //
create function dept_count(deptName varchar(20))
returns integer
begin
declare d_count integer ;
select count(*) into d_count
from instructor
where instructor.dept_name = deptName;
return d_count;
end//
DELIMITER ;
Query OK, 0 rows affected mysql> select dept_count('电子系');
+----------------------+
| dept_count('电子系') |
+----------------------+
| 5 |
+----------------------+
1 row in set

7:创建无参函数

mysql> CREATE FUNCTION simpleFun()RETURNS VARCHAR(20) RETURN "电子系";
1304 - FUNCTION simpleFun already exists
mysql> select * from deptartment where dept_name=simpleFun();
+-----------+--------+----------+
| dept_name | budget | building |
+-----------+--------+----------+
| 电子系 | 10000 | 2号楼 |
+-----------+--------+----------+
1 row in set

二:过程:使用一中的表  https://www.cnblogs.com/oskyhg/p/7679962.html

1:创建无参数的过程,查询的值直接返回。

drop procedure if exists pro1;
mysql> create procedure pro1()
select 5
-> ;
Query OK, 0 rows affected
mysql> call pro1();
+---+
| 5 |
+---+
| 5 |
+---+
1 row in set Query OK, 0 rows affected mysql>
mysql> drop procedure if exists pro1;
mysql> create procedure pro1()
select * from instructor;
Query OK, 0 rows affected mysql> call pro1();
+----+--------+-----------+
| id | salary | dept_name |
+----+--------+-----------+
| 1 | 1000 | 电子系 |
| 2 | 1000 | 电子系 |
| 3 | 1000 | 电子系 |
| 4 | 1000 | 电子系 |
| 5 | 1000 | 电子系 |
| 1 | 1000 | 通信系 |
| 2 | 1000 | 通信系 |
| 3 | 1000 | 通信系 |
| 1 | 1000 | 计算机系 |
+----+--------+-----------+
9 rows in set Query OK, 0 rows affected mysql>

2:创建有输入输出参数的过程。 mysql中的变量   https://blog.csdn.net/qq_34531925/article/details/79483312

mysql> -- 定义执行语句的分割符,遇到//就执行。
DELIMITER //
drop procedure if exists pro3 //
-- in输入参数和类型,out输出参数和类型
create procedure pro3(in parm1 int, out parm2 int)
begin
-- 定义自定义变量,局部变量
declare parm3 int;
-- 对输入参数值进行判断
if parm1=10 then
set parm3=parm1; -- 对parm3进行赋值
else
set parm3=20;
end if;
-- 插入操作,自定义变量的值做为插入值
insert into instructor(id) values(parm3);
-- 查询结果赋值给输出参数
select count(*) into parm2 from instructor;
end //
-- 调用过程,将输出值,赋值给outValue变量
call pro3(10,@outValue) //
-- 查询输出值,@outValue 是用户变量
select @outValue //
Query OK, 0 rows affected Query OK, 0 rows affected Query OK, 1 row affected +-----------+
| @outValue |
+-----------+
| 12 |
+-----------+
1 row in set mysql>

3:当没有输出参数时,会将过程中最后的select查询结果作为过程的结果

mysql> create procedure pro1(name varchar(20))
select * from instructor where dept_name=name;//
Query OK, 0 rows affected mysql> call pro1('电子系');//
+----+--------+-----------+
| id | salary | dept_name |
+----+--------+-----------+
| 1 | 1000 | 电子系 |
| 2 | 1000 | 电子系 |
| 3 | 1000 | 电子系 |
| 4 | 1000 | 电子系 |
| 5 | 1000 | 电子系 |
+----+--------+-----------+
5 rows in set Query OK, 0 rows affected

三:函数和过程 支持for while语句。

创建工资表

mysql> create table salarie(name varchar(20),salary int(11));
mysql> insert into salarie values('zhangsan',2000);
mysql> insert into salarie values('lisi',2500);
mysql> insert into salarie values('wangwu',3000);

1:使用过程中的while语句向sql表中添加数据

mysql> delimiter //
drop procedure if exists salary //
create procedure salary()
begin
declare i int default 0;
while i<10 do
insert into salarie values('wangwu',100);
set i=i+1;
end while;
end //
Query OK, 0 rows affected Query OK, 0 rows affected mysql> call salary();//
Query OK, 1 row affected mysql> select * from salarie; //
+----------+--------+
| name | salary |
+----------+--------+
| zhangsan | 2000 |
| lisi | 2500 |
| wangwu | 3000 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
| wangwu | 100 |
+----------+--------+
13 rows in set

2:使用repeat语句向数据库中添加数据

delimiter //
drop procedure if exists salary //
create procedure salary()
begin
declare i int default 0;
repeat
insert into salarie values('lisi',100);
set i=i+1;
until i>5
end repeat;
end //

3:  使用loop循环插入。    read_loop为起的loop名字,可以为任意名。

delimiter //
drop procedure if exists StatisticStore; //
CREATE PROCEDURE StatisticStore()
BEGIN
declare i int default 0;
read_loop:loop
if i>6 then
leave read_loop;
end if;
insert into salarie values('zhangsan',300);
set i=i+1;
end loop;
END; //

四:使用游标,对查询出来的记录进行迭代操作。   游标只能在存储过程中使用。使用三中的表  https://blog.csdn.net/liguo9860/article/details/50848216

向表中添加一个自增的字段,用于区分各个记录。

alter table `salarie` add `id` int AUTO_INCREMENT UNIQUE;//
mysql> select * from salarie;
+----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2000 | 1 |
| lisi | 2500 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 100 | 4 |
| wangwu | 100 | 5 |
| wangwu | 100 | 6 |
| wangwu | 100 | 7 |
| wangwu | 100 | 8 |
| wangwu | 100 | 9 |
| wangwu | 100 | 10 |
| wangwu | 100 | 11 |
| wangwu | 100 | 12 |
| wangwu | 100 | 13 |
| lisi | 100 | 14 |
| lisi | 100 | 15 |
| lisi | 100 | 16 |
| lisi | 100 | 17 |
| lisi | 100 | 18 |
| lisi | 100 | 19 |
| zhangsan | 300 | 20 |
| zhangsan | 300 | 21 |
| zhangsan | 300 | 22 |
| zhangsan | 300 | 23 |
| zhangsan | 300 | 24 |
| zhangsan | 300 | 25 |
| zhangsan | 300 | 26 |
+----------+--------+----+
26 rows in set

向工资低于2700的员工每人加一百块钱工资的工程如下,并将工资低于2700的员工的总额统计出来。

mysql>  delimiter //
drop procedure if exists addMoney; //
CREATE PROCEDURE addMoney()
BEGIN
-- 定义的游标变量,用于接收查询出来的记录
declare oldSalary int;
declare nid int;
declare total int default 0;
declare done int default false;
declare cur cursor for select salary,id from salarie where salary<2700;
-- 定义的标记符done, 直到最后将游标中的数据全部取出,设置done为true
declare continue HANDLER for not found set done = true;
set total = 0;
open cur;
read_loop:loop
fetch cur into oldSalary,nid;
if done then
leave read_loop;
end if;
update salarie set salary=salary+100 where id=nid;
set total = total + oldSalary;
end loop;
close cur;
select total;
END; //
Query OK, 0 rows affected Query OK, 0 rows affected mysql> call addMoney;//
+-------+
| total |
+-------+
| 8200 |
+-------+
1 row in set Query OK, 0 rows affected mysql> select * from salarie;
-> //
+----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
| wangwu | 200 | 10 |
| wangwu | 200 | 11 |
| wangwu | 200 | 12 |
| wangwu | 200 | 13 |
| lisi | 200 | 14 |
| lisi | 200 | 15 |
| lisi | 200 | 16 |
| lisi | 200 | 17 |
| lisi | 200 | 18 |
| lisi | 200 | 19 |
| zhangsan | 400 | 20 |
| zhangsan | 400 | 21 |
| zhangsan | 400 | 22 |
| zhangsan | 400 | 23 |
| zhangsan | 400 | 24 |
| zhangsan | 400 | 25 |
| zhangsan | 400 | 26 |
+----------+--------+----+
26 rows in set

五:触发器

FOR EACH ROW,可以迭代取出每一行中的列的 数据。

创建触发器,并使用。  创建插入触发器,当新加入的薪水大于1000时,减去200。

mysql> drop trigger if exists BeforeInsert; //

CREATE TRIGGER BeforeInsert BEFORE insert ON salarie
FOR EACH ROW
BEGIN
IF new.salary> 1000 THEN
SET new.salary = new.salary-200;
END IF;
END; //
Query OK, 0 rows affected Query OK, 0 rows affected mysql> insert into salarie(name,salary) values('zhaoliu',1500);//
Query OK, 1 row affected mysql> select * from salarie;//
+----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
| wangwu | 200 | 10 |
| wangwu | 200 | 11 |
| wangwu | 200 | 12 |
| wangwu | 200 | 13 |
| lisi | 200 | 14 |
| lisi | 200 | 15 |
| lisi | 200 | 16 |
| lisi | 200 | 17 |
| lisi | 200 | 18 |
| lisi | 200 | 19 |
| zhangsan | 400 | 20 |
| zhangsan | 400 | 21 |
| zhangsan | 400 | 22 |
| zhangsan | 400 | 23 |
| zhangsan | 400 | 24 |
| zhangsan | 400 | 25 |
| zhangsan | 400 | 26 |
| zhaoliu | 1300 | 28 |
+----------+--------+----+
27 rows in set

创建更新触发器,new  代表更新的数据,准备插入的,old代表原来的数据。

当给一个员工改变薪水时,如果改变的薪水大于4000,那么还按原来的薪水。

mysql> drop trigger if exists BeforeUpdate; //

CREATE TRIGGER BeforeUpdate BEFORE update ON salarie
FOR EACH ROW
BEGIN
IF new.salary> 4000 THEN
SET new.salary = old.salary;
END IF;
END; //
Query OK, 0 rows affected Query OK, 0 rows affected mysql> update salarie set salary=7000 where id=28;//
Query OK, 0 rows affected
Rows matched: 1 Changed: 0 Warnings: 0 mysql> select * from salarie;//
+----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
| wangwu | 200 | 10 |
| wangwu | 200 | 11 |
| wangwu | 200 | 12 |
| wangwu | 200 | 13 |
| lisi | 200 | 14 |
| lisi | 200 | 15 |
| lisi | 200 | 16 |
| lisi | 200 | 17 |
| lisi | 200 | 18 |
| lisi | 200 | 19 |
| zhangsan | 400 | 20 |
| zhangsan | 400 | 21 |
| zhangsan | 400 | 22 |
| zhangsan | 400 | 23 |
| zhangsan | 400 | 24 |
| zhangsan | 400 | 25 |
| zhangsan | 400 | 26 |
| zhaoliu | 1300 | 28 |
+----------+--------+----+
27 rows in set

mysql中不用给新的数据或旧的数据起别名,默认为new,old

其它数据库的更新或插入:

CREATE TRIGGER TestField1_BeforeInsert BEFORE INSERT ON salarie
-- 新插入的行或更新的行的别名为nrow, 相当于mysql中的new 。 例如:update salarie set salary=7000 where id=28;//
referencing new row as nrow -- 数据库中原来的旧数据别名为orow,相当于mysql中的old 。例如:| zhaoliu | 1300 | 28 |
referencing old row as orow
FOR EACH ROW
BEGIN
IF nrow.salary> 1000 THEN
SET nrow.salary = orow.salary-200;
END IF;
END;

六:递归mysql不支持with recursive 递归查询语句,只能自己写循环语句迭代   https://blog.csdn.net/wickedvalley/article/details/78925041

七:sql与shell脚本的相互调用。

window上面sql与c++的相互调用。 https://blog.csdn.net/swotcoder/article/details/18524

https://blog.csdn.net/shaoyiwenet/article/details/53256103

触发器调用shell文件,shell读取mysql中最新插入的一行,读取邮箱用户名,然后发送邮件给客户。

触发器中执行shll命令,  https://zhidao.baidu.com/question/2271230050936210028.html

八: 循环中使用union

delimiter //
drop procedure if exists tile;//
drop table if exists tempTable;//
create temporary table tempTable as select * from salarie where id<3;//
create procedure tile(n int)
-- set @tb:=table(id int(11),salary int(11), name varchar(20));
begin
while(n>0) do
set n=n-1;
select * from ((select * from tempTable) union (select * from salarie where id<(10+n)))t3;
end while;
-- select * from tempTable;
end//
delimiter;
mysql> call tile(3);
+----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
| wangwu | 200 | 10 |
| wangwu | 200 | 11 |
+----------+--------+----+
11 rows in set +----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
| wangwu | 200 | 10 |
+----------+--------+----+
10 rows in set +----------+--------+----+
| name | salary | id |
+----------+--------+----+
| zhangsan | 2100 | 1 |
| lisi | 2600 | 2 |
| wangwu | 3000 | 3 |
| wangwu | 200 | 4 |
| wangwu | 200 | 5 |
| wangwu | 200 | 6 |
| wangwu | 200 | 7 |
| wangwu | 200 | 8 |
| wangwu | 200 | 9 |
+----------+--------+----+
9 rows in set Query OK, 0 rows affected

九:事件 ,事件可以定时执行一些任务等。

如下:创建一个事件e1,每周执行一次过程procedure1

create event e1 on schedule every 1 week
do
call procedure1('hello');

mysql 误操作之后的回滚,当mysql误操作之后,又没有开启事务,可以用一下方法回滚。就是生成与误操作相反的语句。

https://www.jb51.net/article/99553.htm

上一篇:倍增求lca


下一篇:sql中1=1的and和or问题