Database Mysql_ study notes (two)

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:

  1. 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
  2. IN type parameters are generally only used for incoming, in the process of calling, generally not as modification and return
  3. 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:

  1. Outgoing parameters: in the call to store, you can change its value, and you can return
  2. OUT is an outgoing parameter and cannot be used for incoming parameters
  3. When calling a stored procedure, the out parameter also needs to be specified, but it must be a variable, not a constant;
  4. 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:

  1. 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
  2. INOUT parameters: a collection of parameters of IN and OUT parameter types
  3. 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:

  1. 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;
  2. Variables have data type and length, which are consistent with mysql's SQL data type, and can set default values
  3. Variables can be assigned through set or select into;
  4. Variables need to be returned, you can use the select statement, such as: select variable name.

Variable assignment

  1.  set variable name = value
  2.  select field 1, field 2 into variable 1, variable 2 from table name where condition...

Variable scope

Description of scope

  1. 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
  2. Need to pass values ​​between multiple blocks, you can use global variables, that is, placed before all code blocks
  3. 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:

  1. The creation function must specify the return value type, and the input parameters are all IN types by default
  2. The function body is placed between BEGIN and END
  3. return the return value of the specified function
  4. 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:

Guess you like

Origin blog.csdn.net/LoveG_G/article/details/112275886