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

        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM