一:函數
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