concept
Stored procedures and functions are a collection of SQL statements that have been compiled and stored in the database. Calling stored procedures and functions can simplify a lot of work for application developers, reduce data transmission between the database and the application server, and improve the efficiency of data processing.
The difference between a stored procedure and a function is that a function must have a return value, whereas a stored procedure does not.
- Function: is a procedure that returns a value;
- Procedure: is a function that returns no value;
Use of stored procedures
Creating a stored procedure
Delimiter Custom end symbol for example, $$CREATE PROCEDUREStored procedure name ([in.out.inout] Parameter name Data type...)begin
- SQL statement
endDelimiter, a custom end symbol;Copy the code
Example:
delimiter $$
create procedure pro_test1()
begin
select 'Hello Mysql' ;
end $$
delimiter ;
Copy the code
DELIMITER: Declares a DELIMITER for SQL statements, telling the MySQL interpreter whether the command has ended and whether MySQL can execute it. By default, delimiter is a semicolon (;) . On the command line client, if a command line ends with a semicolon, mysql will execute the command when you press enter.
Calling a stored procedure
callStored procedure name ();Copy the code
Viewing stored Procedures
Query all stored procedures in db_name database
select name from mysql.proc where db='db_name';
-- Query the status of stored procedures
show procedure status;
-- Queries the definition of a stored procedure
show create procedure test.pro_test1 \G;
Copy the code
Deleting a stored procedure
DROP PROCEDURE [IF EXISTSSp_name;Copy the code
Stored procedure syntax
Stored procedures are programmable, meaning they can use variables, expressions, and control structures to perform complex functions.
variable
- Local variables: Pass
DECLARE
You can define a local variable whose scope can only be defined in BEGIN… In the END block. - User variable: The variable name is preceded by the “@” symbol, called user session variable, user – defined variable. Current session (link) valid, BEGIN… Also valid outside the END block, similar to Java member variables.
- System variable: a variable preceded by the “@@” symbol is called a system variable. System variables The system has been created, but you cannot define system variables or modify them yourself. System variables are divided into global variables and session variables
- Global variables: Global variables are automatically initialized to default values by the server at MYSQL startup. These default values can be changed by changing the my.ini file. S
- Session variables: Session variables are initialized by MYSQL each time a new connection is created. MYSQL will make a copy of the values of all current global variables. As a session variable.
- That is, if the values of session variables and global variables have not been manually changed since the session was established, then all of these variables have the same value. It’s just a different scope.
- The difference between a global variable and a session variable is that changes to a global variable affect the entire server, whereas changes to a session variable affect only the current session (that is, the current database connection).
- Some system variables can be changed dynamically using statements, but some system variables are read-only. For those that can be changed, set statements can be used to change them.
A local variable
Local variable creation syntax:
DECLAREVariable name type [DEFAULTThe default value]Copy the code
Example:
delimiter $$
create procedure pro_test()
begin
declare num int default 5; Create a local variable of type int num, default value 5
select num + 10; -- Prints the value of the variable num
end $$
delimiter ;
Call the stored procedure
CALL pro_test();
Copy the code
Execution Result:
The user variables
Grammar:
@user variable name-- No need to declare in advance, just declare when using
Copy the code
Such as:
DELIMITER $$
CREATE PROCEDURE pro_test4 () BEGIN
SET @var_name = 'wk'; Create user variable @var_name and assign 'wk'
END $$
DELIMITER;
CALL pro_test4 (); Call the stored procedure pro_test4
SELECT @var_name; -- View user variables
Copy the code
Execution Result:
System variables
Global variable syntax:
@@global.var_name
Copy the code
Such as:
show.global variables;Look at global variables
select @@globa1.auto_increment_increment; View a global variable
set global sort_buffer_size = 40000;
set @@global.sort_buffer_size = 40000 ; -- Changes the value of a global variable
Copy the code
Session variable syntax:
@@session.var_name
Copy the code
Such as:
show session variables;-- View session variables
select @@session. auto_increment increment;-- View a session variable
set session sort buffer size = 50000 ;-- Modify the value of session variablesset @@session. sort_buffer_size = 50000 ;-- Modify the value of session variablesCopy the code
The assignment
SET
Assignment:
To assign a local variable directly, use SET. You can assign constants or expressions.
Grammar:
SETThe variable name1 = 值1;SETThe variable name2 = 值2; .Copy the code
Example:
DELIMITER $
CREATE PROCEDURE pro_test3() Create a stored procedure named pro_test3
BEGIN
DECLARE NAME VARCHAR(20); Create a local variable named NAME of type VARCHAR;
SET NAME = 'MYSQL';-- Assign the local variable NAME to MYSQL
SELECT NAME ;Print this local variable
END$
DELIMITER ;
Copy the code
Execution Result:
select ... into
The assignment operation
In addition to the set assignment, use select… Into can also perform assignments.
Grammar:
DELIMITER $$
CREATE PROCEDURE pro_test5()
BEGIN
declare countnum int;
select count(*) into countnum from city; -- Assign the value of count(*) to countnum
select countnum; -- Output variable
END $$
DELIMITER ;
Copy the code
parameter
Syntax format:
delimiter $$
create procedure procedure_name([in/out/inout] Parameter name Parameter type)begin.end $$
delimiter;
-- IN: This parameter can be used as input, which requires the caller to pass IN a value, by default
-- OUT: This parameter is output, that is, this parameter can be returned
-- INOUT: can be used as either input or output parameters
Copy the code
IN
Requirements:
Determines the type of body that the current height belongs to according to the defined height variable. Example:
- a case
delimiter $$
create procedure pro_test5(in height int)
begin
declare description varchar(50) default ' ';
if height > = 180 then
set description='身材高挑';
elseif height > = 170 and height < 180 then
set description='Standard size';
else
set description='Average body';
end if;
select concat('height', height , 'Corresponding body type is :',description); -- Output statement
end $$
delimiter ;
Call the stored procedure
call pro_test5(1.80);
- the second case
delimiter $$
create procedure pro_test6(in height_ int)
begin
select * from emp where emp.height = height_;
end $$
delimiter ;
Call the stored procedure
call pro_test5(1.80);
Copy the code
OUT
Requirement: Get the user name and password based on the incoming ID.
Example:
delimiter $$
CREATE PROCEDURE pro_test8(IN in_id VARCHAR(20),OUT out_name VARCHAR(20),OUT out_pass VARCHAR(200))
BEGIN
SELECT username,password INTO out_name,out_pass FROM sys_user WHERE id = in_id;Username = out_name; password = out_pass;
END $$
delimiter;
CALL pro_test8(1.@o_name,@o_pass);Call the stored procedure and assign the query out_name value to the user variable @o_name; Out_pass is assigned to the user variable @o_pass;
SELECT @o_name;-- Query @o_name;
SELECT @o_pass;-- Query user variable @o_pass;
Copy the code
INOUT
Requirement: Pass in a number and print 10 times that number
Example:
delimiter $$
CREATE PROCEDURE pro_test9(INOUT num int)
BEGIN
SET num = num * 10;
END $$
delimiter;
SET @into_num = 2;-- Set @into_num to 2;
CALL pro_test9(@into_num);Call the stored procedure, passing in the @into_num argument;
SELECT @into_num;-- Query user variable @into_num;
Copy the code
Branch statements
IF statement
Case 1:
delimiter $$
CREATE PROCEDURE pro_test10(in score INT)
BEGIN
IF score < 60
THEN SELECT 'Fail';
ELSEIF score > = 60 AND score < 80
THEN SELECT 'pass';
ELSEIF score > = 80 AND score < 90
THEN SELECT 'good';
ELSEIF score > = 90 AND score < = 100
THEN SELECT'good';
ELSE
SELECT 'Grade error';
END IF; -- The end needs to add;
END $$
delimiter;
CALL pro_test10(100);-- Call statement
Copy the code
Case 2:
delimiter $$
create PROCEDURE pro_teset11(in in_name varchar(20))
BEGIN
DECLARE var_sal DECIMAL(7.2); Declare a salary variable
DECLARE result VARCHAR(20); Declare a result variable
SELECT sal INTO var_sal FROM emp WHERE ename = in_name; -- Execute SQL statements
if val_sal < 1000
THEN SET result = 'Trial salary';
ELSEIF var_sal < = 20000
THEN SET result = 'Regular salary';
ELSE
SET result = 'Senatorial salary';
END IF;
SELECT result;
END $$
delimiter ;
CALL pro_test11('Wu Ke');
Copy the code
A CASE statement
Grammar 1:
When case_value is consistent with when_value, the statement statement_list is executed
When case_value is inconsistent with when_value, else statement is executed
case case_value
when when_value then statement_list
[when when_value then statement_list]
...
[else statement_list]
end case
Copy the code
Syntax 2:
-- Search_condition is true, execute statement_list
If none of the above search_condition is true, statement_list is executed
case
when search_condition then statement_list
[when search_condition then statement_list]
...
[else statement_list]
end case
Copy the code
Case 1:
-- The first format:
/* Payment method: 1. Wechat Pay 2. Alipay 3
delimiter $$
CREATE PROCEDURE pro_test12(in pay_type int)
BEGIN
CASE pay_type
WHEN 1 THEN SELECT 'wechat Pay';
WHEN 2 THEN SELECT 'Alipay pay';
WHEN 3 THEN SELECT 'Card payment';
ELSE SELECT 'Payment by other means';
END CASE;
END $$
delimiter ;
CALL pro_test12(1);Call the stored procedure
-- Second format:
delimiter $$
CREATE PROCEDURE pro_test13(in score int)
BEGIN
CASE
WHEN score < = 50 THEN SELECT 'Fail';
WHEN score > 50 AND score < = 80 THEN SELECT 'good';
WHEN score >80 AND score < = 100 THEN SELECT 'good';
ELSE SELECT 'Incorrect result input';
END CASE;
END $$;
delimiter ;
CALL pro_test13(88);
Copy the code
Looping statements
The while loop
Grammatical structure:
WHILE loop condition DO loop bodyEND
END WHILE;
Copy the code
Example:
Compute the increment from 1 to n
delimiter $$
create procedure pro_test14(n int)
begin
declare total int default 0; Create the total variable, default to 0
declare num int default 1; Create num variable, default value 1
while num < = n do -- Loop condition num <= n
set total = total + num;
set num = num + 1;
end while;
select total;
end $$
delimiter ;
call pro_test14(10);
Insert data into a table
delimiter $$
create procedure proc16_while(in insertCount int)
begin
declare i int default 1;
label:while i < = insertCount do -- label: Just a label (optional) indicating where the loop starts
insert into user (uid, username, password)values(i,concat(user,i),'123456');
set i = i + 1;
end while label;-- label indicates which loop to end
end $$
delimiter ;
call proc16_while(10);
-- while + leave
-- leave: Directly breaks out of the while loop
delimiter $$
create procedure proc17_while_leave(in insertCount int)
begin
declare i int default 1;
label:while i < = insertCount do
insert into user(uid,username,password)values(i,concat('user-',i),'123456');
if i = 5 then
leave label; -- When I = 5, the loop starting with the label is broken;
end if;
set i = i + 1;
endwhile label; End a loop that begins with a label: label;select 'End of loop';
end $$
delimiter ;
call proc17_while_leave(10);
-- while + iterate
Iterate: Skip the rest of the code for this loop and go to the next loop
delimiter $$
create procedure proc17_while_iterate(in insertCount int)
begin
declare i int default 0;
label:while i < insertCount do
set i = i + 1;
if i = 5 then iterate label;-- Execute the following code when I = 5, and proceed directly to the next loop.
end if;
insert into user2(uid, username, password) values(i,concat('user-',i),'123456');
end while label;
select 'End of loop';
end $$
delimiter ;
call proc17_while_iterate(10); -- 1,2,3,4,6,7,8,9 will skip 5
Copy the code
Repeat statement
Conditional loop control statements that exit the loop when the condition is met. While is executed when the condition is met, while repeat is exited when the condition is met.
Grammatical structure:
[tag:]REPEAT; UNTIL conditional expressionThe loop is broken UNTIL the condition is true
END REPEAT;
Copy the code
Example:
delimiter $$
create procedure proc18_repeat(in insertCount int)
begin
declare i int default 1;
label:repeat
insert into user(uid, username, password) values(i,concat('user-',i),'123456');
set i = i + 1;
until i > insertCount -- When I > insertCount, we jump out of the loop
end repeat label;
select 'End of loop';
end $$
delimiter ;
call proc18_repeat(100);
Copy the code
Loop statements
LOOP implements a simple LOOP. The exit condition of the LOOP needs to be defined by another statement, usually using the LEAVE statement. The syntax is as follows:
[tag :] LOOP body; If conditional expressionthenLeave [label];ENDIF;ENDLOOP;Copy the code
The LOOP statement can be used to implement a simple LOOP IF an exit statement is not added to the IF.
Case study:
delimiter $$
create procedure proc19_loop(in insertCount int)
begin
declare i int default 1;
label: loop
insert into user(uid, username, password) values(i,concat('user-',i),'123456');
set i = i + 1
if i > insertCount then leave label; -- If I > insertCount, the loop exits;
end if ;
end loop label; -- End loop
end $$
delimiter ;
call proc19_loop(100);
Copy the code
Cursor/cursor
Cursors are data types used to store the result set of a query, which can be looping over with the cursor in stored procedures and functions. Cursor usage includes cursor declaration, OPEN, FETCH, and CLOSE, with the following syntax, respectively.
Declare cursor:
DECLARE cursor_name CURSOR FOR select_statement
Copy the code
Open the cursor:
OPEN cursor_name ;
Copy the code
Get values by cursor:
FETCH cursor_name INTO var_name [, var_name] ...
Copy the code
Close the cursor:
CLOSE cursor_name ;
Copy the code
Example:
Initialization script:
create table emp(
id int(11) not null auto_increment ,
name varchar(50) not null comment 'name',
age int(11) comment 'age',
salary int(11) comment 'salaries'.primary key(`id`)
)engine=innodb default charset=utf8 ;
insert into emp(id,name,age,salary) values(null.The Golden Lion.55.3800), (null.The White-browed Eagle King..60.4000), (null.'The Green-winged Bat King'.38.2800), (null.The Purple King..42.1800); Copy the codeCopy the code
Delimiter $$CREATE PROCEDURE PRO_test11 () BEGIN delimiter $$CREATE PROCEDURE PRO_test11 () BEGIN define variable declare e_id int(11); declare e_name varchar(50); declare e_age int(11); declare e_salary int(11); -- Define cursor declare EMP_result cursor for SELECT * from EMp; -- Open the cursor open emp_result; Fetch emp_result into e_id,e_name,e_age,e_salary; Select concat('id=',e_id, ', name=',e_name, ', age=', e_age, ', e_age, ', salary =', e_salary); fetch emp_result into e_id,e_name,e_age,e_salary; Select concat (' id = 'e_id,', the name = 'e_name,', the age = 'e_age,', salary is: 'e_salary); fetch emp_result into e_id,e_name,e_age,e_salary; Select concat (' id = 'e_id,', the name = 'e_name,', the age = 'e_age,', salary is: 'e_salary); fetch emp_result into e_id,e_name,e_age,e_salary; Select concat (' id = 'e_id,', the name = 'e_name,', the age = 'e_age,', salary is: 'e_salary); fetch emp_result into e_id,e_name,e_age,e_salary; Select concat (' id = 'e_id,', the name = 'e_name,', the age = 'e_age,', salary is: 'e_salary); close emp_result; end $$ delimiter ;Copy the code
Get cursor data through loop structure:
DELIMITER $$
create procedure pro_test12()
begin
DECLARE id int(11);
DECLARE name varchar(50);
DECLARE age int(11);
DECLARE salary int(11);
DECLARE has_data int default 1;
DECLARE emp_result CURSOR FOR select * from emp;
DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;
open emp_result;
repeat
fetch emp_result into id , name , age , salary;
select concat('id',id, ', the name of ' ,name , ', the age for ' ,age , ', salary: ', salary);
until has_data = 0
end repeat;
close emp_result;
end $$
DELIMITER ;
Copy the code
Exception handling
-- cursor + handle
/* DECLARE handler_action HANDLER FOR condition_value [, condition_value] ... statement handler_action: { CONTINUE | EXIT | UNDO } condition_value: {mysql_error_code | condition_name | SQLWARNING | NOT FOUND special note: in syntax, variable declarations, cursor statement, handler declaration must be in accordance with the order of writing, or create a stored procedure is wrong. * /
use mysql7_procedure;
drop procedure if exists proc21_cursor_handler;
-- Requirement: Enter a department name, query the number, name, and salary of the employees in the department, and add a cursor to the query result set
delimiter $$
create procedure proc21_cursor_handler(in in_dname varchar(50))
begin
Define local variables
declare var_empno int;
declare var_ename varchar(50);
declare var_sal decimal(7.2);
-- Define tag values
declare flag int default 1;
-- Declare cursors
declare my_cursor cursor for
select empno,ename,sal
from dept a, emp b
where a.deptno = b.deptno and a.dname = in_dname;
Define handles: Define how exceptions are handled
/* 1: How to execute the program after the exception is handled continue: continue the remaining code exit: directly terminate the program undo: not supported 2: trigger condition Condition code: 1329 SQLWARNING NOT FOUND SQLEXCEPTION 3: What code is executed after the exception is triggered to set the value of flag -- 0 */
declare continue handler for 1329 set flag = 0;
-- Open the cursor
open my_cursor;
Fetch values via cursors
label:loop
fetch my_cursor into var_empno, var_ename,var_sal;
-- Check flag. If flag is 1, the command is executed. Otherwise, the command is not executed
if flag = 1 then
select var_empno, var_ename,var_sal;
else
leave label;
end if;
end loop label;
-- xxxxx
-- Close the cursor
close my_cursor;
end $$;
delimiter ;
call proc21_cursor_handler('Teaching and Research Department');
Copy the code
practice
Practice -
User_2021_12_01, user_2022_12_02,... Requirement Description: We need to use a table to record a lot of data, such as record so-and-so users search, purchase behavior (note that this is a hypothesis with a database to store), when the record is large, every day if put all data records to a table is too large, need table, our request is that one table every day, the statistics of the day, Just ask to produce these tables ahead of time -- create the next day's tables at the end of each month! * /
Create table user_2021_11_01 to user_2020_11_30; And execute the CREATE statement.
create database mydb18_proc_demo;
use mydb18_proc_demo;
drop procedure if exists proc22_demo;
delimiter $$
create procedure proc22_demo()
begin
declare next_year int; -- Next month's year
declare next_month int; -- The month of the following month
declare next_month_day int;-- the last day of the following month
declare next_month_str varchar(2); -- Month string for next month
declare next_month_day_str varchar(2);-- The day string for the next month
-- Handles daily table names
declare table_name_str varchar(10);
declare t_index int default 1;
-- declare create_table_sql varchar(200);
-- Gets the year of the next month
set next_year = year(date_add(now(),INTERVAL 1 month)); - 2021
-- Get what month is next month
set next_month = month(date_add(now(),INTERVAL 1 month)); 11 -
-- What's the last day of next month
set next_month_day = dayofmonth(LAST_DAY(date_add(now(),INTERVAL 1 month))); 30 -
if next_month < 10
then set next_month_str = concat('0',next_month); -- "01
else
set next_month_str = concat(' ',next_month); 12 -
end if;
while t_index < = next_month_day do
if (t_index < 10)
then set next_month_day_str = concat('0',t_index);
else
set next_month_day_str = concat(' ',t_index);
end if;
-- 2021_11_01
set table_name_str = concat(next_year,'_',next_month_str,'_',next_month_day_str);
-- Splice create SQL statements
set @create_table_sql = concat(
'create table user_',
table_name_str,
'(`uid` INT ,`uname` varchar(50) ,`information` varchar(50)) COLLATE=\'utf8_general_ci\' ENGINE=InnoDB');
-- Local variables cannot be used after FROM!
prepare create_table_stmt FROM @create_table_sql;
execute create_table_stmt;
DEALLOCATE prepare create_table_stmt;
set t_index = t_index + 1;
end while;
end $$
delimiter ;
call proc22_demo();
Copy the code