Chapter 2 Mysql Stored Procedure
Description:
The database user name is root, the password is rootpwd, and the connection is the local windows mysql database
Database version, SELECT VERSION(), 8.0.15
Database engine: SHOW ENGINES
As can be seen from the above figure, only InnoDB supports transactions
The default database engine: SHOW VARIABLES LIKE'default_storage_engine'
As can be seen from the above figure, InnoDB is the default data engine.
The structure of the prepared data table:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for trans_order
-- ----------------------------
DROP TABLE IF EXISTS `trans_order`;
CREATE TABLE `trans_order` (
`WAYBILL_NO` int(255) NOT NULL COMMENT '运单号',
`SEND_SITE_ID` int(11) NULL DEFAULT NULL COMMENT '寄件网点ID',
`SEND_SITE_CODE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件网点代码',
`SEND_SITE_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件网点名称',
`SEND_DATE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件时间',
`ORDER_NO` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '订单号',
`CUSTOMER_ID` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '客户ID',
`CUSTOMER_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '客户名称',
`CUSTOMER_CODE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '客户代码',
`SEND_PHONE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件人联系电话',
`SEND_PROVINCE_CITY_DISTRICT` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件人省市区',
`SEND_ADDRESS_DETAIL` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件人详细地址',
`SEND_PERSON` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '寄件人',
`DISP_SITE_ID` int(255) NULL DEFAULT NULL COMMENT '目的网点ID',
`DISP_SITE_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '目的网点名称',
`DISP_SITE_CODE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '目的网点代码',
`ACCEPT_PHONE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '收件人电话',
`ACCEPT_ADDRESS` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '收件人地址',
`ACCEPT_PROVINCE_CITY_DISTRICT` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '收件人省市区',
`ACCEPT_PERSON` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '收件人',
`PRODUCT_ID` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '产品类型',
`WEIGHT` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '重量',
`PAYMENT_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '支付类型',
`PAYMENT__DELIVERY_FEE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '到付费用',
`PAYMENT__NOW_FEE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '现付费用',
`INSURANCE_FEE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '保险费',
`GOODS_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '货物类型',
`REMARK` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注信息',
`PACK_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '包装方式',
PRIMARY KEY (`WAYBILL_NO`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of trans_order
-- ----------------------------
INSERT INTO `trans_order` VALUES (8001, 1, '755A', '深圳龙岗坂街道', '20201216131522', '741000015819', 666, '阿聪', '888', '13828892565', '广东省|深圳市|龙岗区', '坂田街道禾坪岗', '阿聪', 9, '湖北武汉大学网点', '027C', '15889861946', '武汉大学', '湖北省|武汉市|武昌区', '阿朱', 'T66', '1.80', '现付', '0', '100.00', '10', '日用品', '零食和衣物', '0');
SET FOREIGN_KEY_CHECKS = 1;
Reference documents:
https://www.mysqlzh.com/doc/224.html
https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html
2.1 What is a stored procedure
2.1.1 Concept
MySQL 5.0 version began to support stored procedures.
Stored Procedure (Stored Procedure) is a kind of database object that stores complex procedures in the database so that external procedures can call. A stored procedure is a set of SQL statements to complete a specific function. It is compiled and saved in the database. The user can call and execute it by specifying the name of the stored procedure and given parameters (when needed).
The stored procedure is very simple in thought, that is, code encapsulation and reuse at the database SQL language level.
2.1.2 Advantages
- Stored procedures can be encapsulated and hide complex business logic.
- The stored procedure can return values and can accept parameters.
- The stored procedure cannot be run using the SELECT instruction because it is a subroutine, which is different from a view table, data table, or user-defined function.
- Stored procedures can be used for data inspection, forcing business logic, etc.
- The execution speed of the stored procedure is relatively fast, and it has been precompiled.
2.1.3 Disadvantages
- Stored procedures are often customized on a specific database, because the supported programming languages are different. When switching to a database system of another manufacturer, the original stored procedure needs to be rewritten.
- The performance tuning and writing of stored procedures are limited by various database systems.
2.2 A simple example of a stored procedure
2.2.1 Create a stored procedure and stored function statement
Official instructions:
CREATE
[DEFINER = user]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
CREATE
[DEFINER = user]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
type:
Any valid MySQL data type
characteristic: {
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
}
routine_body:
Valid SQL routine statement
By default, the program is associated with the current database. To explicitly associate a subroutine with a given database, you can specify its name as db_name.sp_name when creating the subroutine .
If the name of the subroutine is the same as the name of the built-in SQL function, when defining the subroutine, you need to insert a space between the name and the subsequent brackets, otherwise a syntax error will occur. Insert it when you subsequently call the subroutine. For this reason, even if this situation is possible, we still recommend that it is best to avoid giving your own stored subroutine the same name as the existing SQL function.
DEFINER
: CREATE PROCEDURE and CREATE FUNCTION require CREATE ROUTINE privileges. If there is a DEFINER clause, the required privileges depend on the user value,
The parameter list in parentheses must always exist. If there are no parameters, an empty parameter list of () should be used. Parameter names are not case sensitive.
Each parameter is an IN parameter by default. To specify other parameters, you can use the keyword OUT or INOUT before the parameter name
Note : Specifying the parameter as IN, OUT, or INOUT is only legal for PROCEDURE. (FUNCTION parameters are always considered as IN parameters)
The RETURNS clause can only specify FUNCTION, which is mandatory for functions. It is used to specify the return type of the function, and the function body must contain a RETURN value statement.
routine_body: compound statement
[begin_label:] BEGIN
[statement_list]
END [end_label]
Translated into a grammatical template that can be used:
delimiter //
CREATE
PROCEDURE sp_name ([proc_parameter[,...]])
BEGIN
[statement_list]
END//
delimiter;
delimiter //
CREATE
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
BEGIN
[statement_list]
END
delimiter;
1. Create an empty parameter stored procedure
delimiter //
CREATE
PROCEDURE query_trans_all ()
BEGIN
SELECT * FROM trans_order;
END//
delimiter;
Call stored procedure
CALL query_trans_all;
In fact, the result is the same as executing the query statement: SELECT * FROM trans_order; However, the query statement can be shorter than the stored procedure when the query time is read;
Complex logic can be constructed by multiple statements
-- 将多个sql语句封装成一个存储过程 --
delimiter //
CREATE
PROCEDURE query_trans_all ()
BEGIN
[创建表结构]
[插入表数据]
[查询表数据]
....
END//
delimiter;
2.3 Variables in the stored procedure
2.3.1 The stored procedure enters the parameter variable
The parameter types of the stored procedure are: IN, OUT, INOUT, the three types are introduced below:
Parameter IN description:
- Incoming parameters, the type IN means that the input parameter must be passed in the process of being called, if the specified type is not displayed, the default type is the IN type
- IN type parameters are generally only used for incoming, in the process of calling, generally not as modification and return
- If you need to modify and return the value in the call to the stored procedure, you need to use OUT type parameters
Example: According to the waybill WAYBILL_NO query, return the ORDER_NO of the waybill
-- 根据运单WAYBILL_NO查询,返回运单的ORDER_NO
delimiter //
CREATE
PROCEDURE query_trans_by_Id (IN wayNO int)
BEGIN
DECLARE orderno VARCHAR(32) DEFAULT ' ';
SELECT ORDER_NO INTO orderno FROM trans_order WHERE WAYBILL_NO=wayNO;
SELECT orderno;
END//
delimiter;
-- 调用
CALL query_trans_by_Id(8002);
result:
Parameter OUT description:
- Outgoing parameters: in the call to store, you can change its value, and you can return
- OUT is an outgoing parameter and cannot be used for incoming parameters
- When calling a stored procedure, the out parameter also needs to be specified, but it must be a variable, not a constant;
- If you need to pass in and out at the same time, you can use the INOUT parameter type
Example: According to the waybill WAYBILL_NO query, return the ORDER_NO of the waybill
-- 根据运单WAYBILL_NO查询,返回运单的ORDER_NO
delimiter //
CREATE
PROCEDURE query_trans_by_Id_out (IN wayNO int,out orderno VARCHAR(32))
BEGIN
SELECT ORDER_NO INTO orderno FROM trans_order WHERE WAYBILL_NO=wayNO;
END//
delimiter;
-- 调用
SET @orderno='';
CALL query_trans_by_Id_out(8001,@orderno);
SELECT @orderno as orderno
result:
Parameter INOUT description:
- Variable variable INOUT, the value can be passed in when calling, in the process of calling, its value can be modified, and the value can also be returned at the same time
- INOUT parameters: a collection of parameters of IN and OUT parameter types
- The value passed in when INOUT is called is a variable instead of a constant
Example: According to the waybill WAYBILL_NO query, return the waybill’s ORDER_NO, WAYBILL_NO, SEND_PHONE
-- 根据运单WAYBILL_NO查询,返回运单的ORDER_NO,WAYBILL_NO,SEND_PHONE
delimiter //
CREATE
PROCEDURE query_trans_by_Id_INOUT (INOUT wayNO int,INOUT orderno VARCHAR(32),OUT sendphone VARCHAR(32))
BEGIN
SET orderno = '0000000';
SET sendphone = '12345678';
SELECT WAYBILL_NO,ORDER_NO,SEND_PHONE INTO wayNO,orderno,sendphone FROM trans_order WHERE WAYBILL_NO=wayNO;
END//
delimiter;
-- 调用
SET @wayNO = 8002;
SET @orderno='';
SET @sendphone='';
CALL query_trans_by_Id_INOUT(@wayNO,@orderno,@sendphone);
SELECT @wayNO,@orderno as orderno,@sendphone;
result:
Description: CALL query_trans_by_Id_INOUT(8001,@orderno,@sendphone); The writing of this constant will report an error, and a variable must be required here;
CALL query_trans_by_Id_INOUT(8001,@orderno,@sendphone)
> 1414 - OUT or INOUT argument 1 for routine ats.query_trans_by_Id_INOUT is not a variable or NEW pseudo-variable in BEFORE trigger
> 时间: 0.001s
2.3.2 Local variables of stored procedures
Variable declaration
DECLARE var_name[,...] type [DEFAULT value]
This statement is used to declare local variables. To provide a default value for the variable, include a DEFAULT clause. The value can be specified as an expression and does not need to be a constant. If there is no DEFAULT clause, the initial value is NULL.
Description:
- Use declare for the declaration of variables. Variables must be declared first and then used. The position is within BEGIN...END, and BEGIN...END can be nested;
- Variables have data type and length, which are consistent with mysql's SQL data type, and can set default values
- Variables can be assigned through set or select into;
- Variables need to be returned, you can use the select statement, such as: select variable name.
Variable assignment
- set variable name = value
- select field 1, field 2 into variable 1, variable 2 from table name where condition...
Variable scope
Description of scope
- Variables in the storage process have a scope, the scope is between the BEGIN and END blocks, END ends the scope of the variable is the end
- Need to pass values between multiple blocks, you can use global variables, that is, placed before all code blocks
- Passing parameter variables are global and can work between multiple blocks
Verify the scope of local variables:
-- 变量的作用域验证
delimiter //
CREATE
PROCEDURE test ()
BEGIN
BEGIN
-- 返回trans_order的总记录数
DECLARE count int DEFAULT 0;
SELECT COUNT(*) INTO count FROM trans_order;
SELECT count;
END;
BEGIN
-- 返回trans_order中CUSTOMER_NAME是阿朱的记录数
DECLARE usercount int DEFAULT 0;
SELECT COUNT(*) INTO usercount FROM trans_order WHERE CUSTOMER_NAME = '阿朱' ;
SELECT usercount;
END;
END//
delimiter;
-- 调用
CALL test
result:
If you change it, there will be problems:
-- 变量的作用域验证
delimiter //
CREATE
PROCEDURE test2 ()
BEGIN
BEGIN
-- 返回trans_order的总记录数
DECLARE count int DEFAULT 0;
SELECT COUNT(*) INTO count FROM trans_order;
SELECT count;
END;
BEGIN
-- 返回trans_order中CUSTOMER_NAME是阿朱的记录数
DECLARE usercount int DEFAULT 0;
SELECT COUNT(*) INTO usercount FROM trans_order WHERE CUSTOMER_NAME = '阿朱' ;
SELECT usercount,count;
END;
END//
delimiter;
-- 调用
CALL test2()
No error will be reported when creating, only one result is returned when calling, and the second result is not returned;
Advance variable declaration:
-- 变量的作用域验证
delimiter //
CREATE
PROCEDURE test3 ()
BEGIN
-- 返回trans_order的总记录数
DECLARE count int DEFAULT 0;
BEGIN
SELECT COUNT(*) INTO count FROM trans_order;
SELECT count;
END;
BEGIN
-- 返回trans_order中
DECLARE usercount int DEFAULT 0;
SELECT COUNT(*) INTO usercount FROM trans_order WHERE CUSTOMER_NAME = '阿朱' ;
SELECT usercount,count;
END;
END//
delimiter;
-- 调用
CALL test3()
result:
Description: The scope of the variable in the stored procedure, the scope is between the begin and end blocks, the end of the scope of the variable is the end
2.4 Process control during storage
2.4.1 IF statement
IF statement structure
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
Simple structure:
IF (condition) THEN
statement_list
ELSE
statement_list
END IF
Multi-condition judgment:
IF (condition) THEN
statement_list
ELSEIF (condition) THEN
statement_list
ELSEIF (condition) THEN
statement_list
ELSE
statement_list
END IF
Example: Query by ID, if the id is an even number, the name will be returned, and the odd number will be the phone number;
-- 通过ID查询,如果id是偶数返回名字,奇数返回电话号码;
delimiter //
CREATE
PROCEDURE test4 (IN wayNO int)
BEGIN
DECLARE username VARCHAR(32) DEFAULT ' ';
DECLARE phone VARCHAR(32) DEFAULT ' ';
IF(wayNO%2=0) THEN
SELECT CUSTOMER_NAME INTO username FROM trans_order WHERE WAYBILL_NO = wayNO;
SELECT username;
ELSE
SELECT SEND_PHONE INTO phone FROM trans_order WHERE WAYBILL_NO = wayNO;
SELECT phone;
END IF;
END//
delimiter;
Execution result: (There are two pieces of data in the database table)
2.4.2 WHILE statement
WHILE statement structure
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
Simple structure:
WHILE (condition) DO
statement_list
END WHILE
Example: Add n pieces of data to the table
-- 插入n条记录
delimiter //
CREATE
PROCEDURE test5 (num int)
BEGIN
DECLARE n int DEFAULT 0;
DECLARE wayNO int DEFAULT 0;
WHILE (n < num) DO
SET wayNO = n;
INSERT INTO `trans_order` VALUES (wayNO, 1, '755A', '深圳龙岗坂街道', '20201216131522', '741000015819', 666, '阿聪', '888', '13828892565', '广东省|深圳市|龙岗区', '坂田街道禾坪岗', '阿聪', 9, '湖北武汉大学网点', '027C', '15889861946', '武汉大学', '湖北省|武汉市|武昌区', '阿朱', 'T66', '1.80', '现付', '0', '100.00', '10', '日用品', '零食和衣物', '0');
SET n = n+1;
END WHILE;
SELECT n;
END//
delimiter;
Results of the:
Originally there were 2 pieces of data, now there are 1002 pieces
2.4.3 REPEAT statement
REPEAT statement structure
REPEAT
statement_list
UNTIL search_condition
END REPEAT
search_condition is true to exit the loop
Example: Insert data cyclically, the original id has reached 999, here it increases from 1000
-- 插入n条记录
delimiter //
CREATE
PROCEDURE test6 (num int)
BEGIN
DECLARE n int DEFAULT 0;
DECLARE wayNO int DEFAULT 1000;
REPEAT
SET wayNO = wayNO + n;
INSERT INTO `trans_order` VALUES (wayNO, 1, '755A', '深圳龙岗坂街道', '20201216131522', '741000015819', 666, '阿聪', '888', '13828892565', '广东省|深圳市|龙岗区', '坂田街道禾坪岗', '阿聪', 9, '湖北武汉大学网点', '027C', '15889861946', '武汉大学', '湖北省|武汉市|武昌区', '阿朱', 'T66', '1.80', '现付', '0', '100.00', '10', '日用品', '零食和衣物', '0');
SET n = n+1;
SET wayNO = 1000;
UNTIL n >= num
END REPEAT;
SELECT n;
END//
delimiter;
CALL test6(2000);
result:
Added 2000 pieces of data, id from 1000 to 2999
2.4.4 LOOP statement
Loop statement structure
label: LOOP
statement_list
IF exit_condition THEN
LEAVE label;
END IF;
END LOOP label;
LEAVE label means to exit the loop
Example: Insert 1000 pieces of data cyclically
delimiter //
CREATE
PROCEDURE test7 ()
BEGIN
DECLARE wayNO int DEFAULT 3000;
label: LOOP
INSERT INTO `trans_order` VALUES (wayNO, 1, '755A', '深圳龙岗坂街道', '20201216131522', '741000015819', 666, '阿聪', '888', '13828892565', '广东省|深圳市|龙岗区', '坂田街道禾坪岗', '阿聪', 9, '湖北武汉大学网点', '027C', '15889861946', '武汉大学', '湖北省|武汉市|武昌区', '阿朱', 'T66', '1.80', '现付', '0', '100.00', '10', '日用品', '零食和衣物', '0');
SET wayNO = wayNO + 1;
IF wayNO >= 3999 THEN
LEAVE label;
END IF;
END LOOP label;
SELECT wayNO;
END//
delimiter;
result:
1000 pieces of data have been added;
2.4.5 CASE statement
CASE syntax structure
case ...
when ... then....
when.... then....
else ...
end case;
Similar to the switch-case grammar of other languages, here is a copy of an example written by others as an illustration, it should be easy to understand!
create procedure testcate(userid int)
begin
declare my_status int default 0;
select status into my_status from users where id=userid;
case my_status
when 1 then update users set score=10 where id=userid;
when 2 then update users set score=20 where id=userid;
when 3 then update users set score=30 where id=userid;
else update users set score=40 where id=userid;
end case;
end;
2.5 Operation of the stored procedure
2.5.1 Modify, delete, view
modify
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
delete
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
The IF EXISTS clause is a MySQL extension. If the program or function is not stored, it prevents errors from occurring.
View
SHOW CREATE {PROCEDURE | FUNCTION} sp_name View a single
PROCEDURE {SHOW |} the STATUS the FUNCTION [the LIKE ' pattern '] See creator stored procedure or function, creation time and other attributes
2.6 Custom functions
Define function syntax structure
delimiter //
CREATE
FUNCTION sp_name ([func_parameter[,...]]) RETURNS type
[statement_list]
BEGIN
[statement_list]
END
delimiter;
Description:
- The creation function must specify the return value type, and the input parameters are all IN types by default
- The function body is placed between BEGIN and END
- return the return value of the specified function
- The function call uses select function name()
Example: Query name by ID
delimiter //
CREATE
FUNCTION getUsername (id int) RETURNS VARCHAR(32)
READS SQL DATA
BEGIN
DECLARE id_username VARCHAR(32) DEFAULT ' ';
SELECT CONCAT(CUSTOMER_NAME,'_',id) INTO id_username FROM trans_order WHERE WAYBILL_NO = id;
RETURN id_username;
END//
delimiter;
result: