Una breve introducción a la sintaxis de funciones y procedimientos almacenados de MySQL 5.6

MySQL admite rutinas almacenadas (procedimientos almacenados y funciones almacenadas)

Una rutina almacenada es un conjunto de sentencias SQL que se pueden almacenar en el servidor. Después de completar esta operación, el cliente no necesita continuar emitiendo extractos individuales, pero puede consultar las rutinas almacenadas.

Primero, aprenda la sintaxis de la rutina almacenada:

Utilice el procedimiento de creación y cree declaraciones de función para crear rutinas almacenadas.

Use la declaración de llamada para llamar al procedimiento y solo use la variable de salida para devolver el valor.

Se puede llamar a una función desde dentro de una instrucción como cualquier otra función (es decir, llamando al nombre de la función), y puede devolver un valor escalar.

El cuerpo de la rutina almacenada puede usar declaraciones compuestas

Puede utilizar el procedimiento de eliminación y las declaraciones de función de eliminación para eliminar rutinas almacenadas

Se puede cambiar mediante el procedimiento de modificación y las declaraciones de función de modificación.

Demostración simple:

-- 声明结束符,因为mysql默认使用“;”作为结束符,而在存储过程中,会使用“;”作为一段语句的结束,导致“;”使用冲突
delimiter $$
CREATE PROCEDURE hello_procedure()
BEGIN 
  SELECT 'hello procedure';
END $$

CALL hello_procedure()

Uno, variables y asignación

Para las variables del procedimiento almacenado, puede analizar la declaración y el uso de variables locales y variables miembro en Java;

1. Variables locales:

Definido por el usuario, válido en el bloque inicial / final

gramática:

Declarar variables: declare var_name type [default'unkown '];

Ejemplo: declare nickname varchar (32);


establecer asignación

-- 声明结束符,因为mysql默认使用“;”作为结束符,而在存储过程中,会使用“;”作为一段语句的结束,导致“;”使用冲突
delimiter $$
create PROCEDURE sp_var01()
BEGIN
 -- 局部变量(需要声明) 字符类型如果为char或者varchar,一定要表明单位长度,int可以不写
 DECLARE nickname VARCHAR(32) DEFAULT 'SF';

 select nickname;

 -- set赋值
 set nickname := 'UG';

 select nickname;

END $$

-- 使用call调用该函数
call  sp_var01()$$

-- 使用drop删除该函数,若想要修改该存储函数,mysql只能drop之后重新create
drop PROCEDURE sp_var01;

en la asignación

-- 首先创建一张表
DROP TABLE IF EXISTS `departments`;
CREATE TABLE `departments` (
  `id` int(11) DEFAULT NULL,
  `dep_name` varchar(255) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of departments
-- ----------------------------
INSERT INTO `departments` VALUES ('1', '开发');
INSERT INTO `departments` VALUES ('2', '测试');
INSERT INTO `departments` VALUES ('3', '产品');
INSERT INTO `departments` VALUES ('4', '运维');


-- 创建存储函数
delimiter $$
create PROCEDURE sp_var01_into()
BEGIN
 -- 声明局部变量
 DECLARE dept_name VARCHAR(32) DEFAULT 'unkown';
 DECLARE dept_no int DEFAULT 0;

 -- select 查询要给局部变量赋值的属性 into 直接进行赋值
 SELECT d.id,d.dep_name into dept_no,dept_name from departments d where d.id = 1;

 select dept_no,dept_name;
END $$

call  sp_var01_into()$$

drop PROCEDURE sp_var01_into;

2. Variables de usuario

Definido por el usuario, la sesión actual (conexión) es válida

gramática:

@var_name

No es necesario declararlo por adelantado, solo úselo

establecer asignación

delimiter $$
create PROCEDURE sp_var02()
BEGIN
	set @nick_name = 'WR';
END $$

CALL sp_var02 $$
select @nick_name $$

en la asignación

delimiter $$
create PROCEDURE sp_var_into()
BEGIN
	select d.dep_name into @deptname from departments d where d.id = 1;
END $$

CALL sp_var_into $$
select @deptname $$

 

3. Variables de sesión

Proporcionado por el sistema, todo el servidor mysql es válido

gramática:

@@ global.var_name

4. Variables globales

Proporcionado por el sistema, todo el servidor Mysql es válido

gramática:

@@ global.var_name

Dos, entrada y salida

- gramática

en | fuera | inout param_name tipo

Por ejemplo

-- int 类型演示
delimiter $$
create PROCEDURE sp_param01(in age int)
BEGIN
	set @user_age = age;
end $$
call sp_param01(10) $$
SELECT @user_age $$

delimiter $$
create PROCEDURE sp_param03(in `name` VARCHAR(32))
BEGIN
	set @user_name = `name`;
end $$
call sp_param03('liman') $$
SELECT @user_name $$




-- out 类型,只负责输出!
-- 需求:输出传入的地址字符串对应的部门编号。
delimiter $$
create PROCEDURE sp_param02(in deptname VARCHAR(32),out dept_no int(11))
BEGIN
	SELECT d.id into dept_no from departments d where d.dep_name = deptname;
	-- 此处强调,要么表起别名,要么入参名不与字段名一致
end $$

-- 测试
delimiter ;
set @dept_no = 7;
call sp_param02("开发",@dept_no);
select @dept_no;


-- inout类型
delimiter $$
create PROCEDURE sp_param04(inout `name` VARCHAR(32))
	BEGIN
		set `name` = CONCAT('hello ',`name`);
end $$
delimiter ;
set @user_name = '小明';
call sp_param04(@user_name);
SELECT @user_name;

Tres, juicio de control de procesos

if - 语法
IF condición_de_búsqueda THEN lista_de_secuencias 
    [ELSEIF condición_de_búsqueda THEN lista_de_segundos] ...
    [ELSE lista_de_segundos ]
END IF

Por ejemplo: 

DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
  `empno` int(50) NOT NULL AUTO_INCREMENT,
  `ename` varchar(50) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
  `job` varchar(50) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
  `mgr` int(50) DEFAULT NULL,
  `hiredate` datetime DEFAULT NULL,
  `sal` decimal(10,2) DEFAULT NULL,
  `comm` varchar(25) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
  `deptno` int(50) NOT NULL,
  PRIMARY KEY (`empno`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_general_mysql500_ci;

-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1', 'smith', 'clerk', '7902', '1980-12-07 12:42:26', '8000.00', null, '1');
INSERT INTO `emp` VALUES ('2', 'martmin', 'saleman', '1630', '1981-10-14 12:43:24', '10000.00', null, '2');
-- 前置知识点:timestampdiff(unit,exp1,exp2)取差值,单位是unit
select TIMESTAMPDIFF(YEAR,e.hiredate,now()) from emp e where e.empno = '2'

delimiter //

CREATE PROCEDURE sp_hire ()
BEGIN
  DECLARE result VARCHAR (32) ;
  DECLARE years int;
  select TIMESTAMPDIFF(YEAR,e.hiredate,now()) into years from emp e where e.empno = '2';

	IF years > 40 THEN
		SET result = '元老' ;
	ELSEIF years > 38 THEN
		SET result = '老员工' ;
	ELSE
		SET result = '新手' ;
	END IF ; 
	SELECT result ;
END//

delimiter ;

CALL sp_hire();

Sintaxis de caso: esta sintaxis se puede utilizar no solo en procedimientos almacenados, sino también en declaraciones de consulta.

语法 一 (类比 java 的 switch)
CASE case_value
        when when_value then statement_list
        [when when_value then statement_list] ...
        [else statement_list]
END CASE

 语法 二 :
CASE 
    when search_condition luego statement_list
    [cuando search_condition luego statement_list]
END CASE

Por ejemplo: 

-- 需求:入职年限年龄<=38 是新手  >38<=40老员工 >40元老
-- 语法一:
-- 1.创建函数
delimiter $$
create PROCEDURE sp_hire_case_in(in year INT)
BEGIN
	DECLARE result VARCHAR(32);
	DECLARE message VARCHAR(64);
	CASE year
		when 40
			then 
					set result = '元老';
					set message = '老爷爷';
		when 38
			then 
					set result = '老员工';
					set message = '油腻中年人';
		ELSE  set result = '新手';
					set message = '萌新';
  end CASE;
  SELECT result,message;
end $$
delimiter;

-- 2.调用函数
call sp_hire_case_in(40);

-- 3.删除函数
drop PROCEDURE sp_hire_case_in;

-- 语法二:
-- 1.创建函数
delimiter $$
create PROCEDURE sp_hire_case()
BEGIN
	DECLARE result VARCHAR(32);
	DECLARE message VARCHAR(64);
	CASE
		when TIMESTAMPDIFF(YEAR,'2001-01-01',now()) > 40
			then 
					set result = '元老';
					set message = '老爷爷';
		when TIMESTAMPDIFF(YEAR,'2001-01-01',now()) > 38
			then 
					set result = '老员工';
					set message = '油腻中年人';
		ELSE  set result = '新手';
			  set message = '萌新';
     end CASE;
     SELECT result,message;
end $$
delimiter;

-- 2.调用函数
call sp_hire_case();

-- 3.删除函数
drop PROCEDURE sp_hire_case;
 


Cuarto, bucle de control de proceso

LOOP 语法 :
[begin_label:] LOOP
        statement_list
END LOOP [end_label]

Por ejemplo: Debe
    explicarse que el bucle es un bucle infinito y debe salir manualmente. Podemos usar dejar para salir. Podemos
    considerar dejar como una interrupción en nuestro Java; en
    consecuencia, hay iterar (continuar bucle), análogo a continuar en java

Solución de procesamiento de bucle sin fin:

-- 如有死循环处理,可以通过下面的命令查看并结束

show processlist;

kill  id;

Ejemplos: 

-- 需求:循环打印到1到10
-- leave控制循环的退出
delimiter $$
CREATE PROCEDURE sp_flow_loop()
begin 
	DECLARE c_index int DEFAULT 1;
  DECLARE result_str VARCHAR(256) default '1';
  cnt:LOOP

		if c_index >= 10
			then leave cnt;
		end if;

		set c_index = c_index + 1;
		set result_str = CONCAT(result_str,',',c_index);

  end loop cnt;
  select result_str;
    
end $$

delimiter ;
call sp_flow_loop();


delimiter $$
create PROCEDURE sp_flow_loop02()
begin 
  DECLARE c_index int  DEFAULT 1;
  DECLARE result_str VARCHAR(256) default '1';
  cnt:LOOP

		set c_index = c_index + 1;
		set result_str = CONCAT(result_str,',',c_index);
		if c_index < 10 then 
			 ITERATE cnt;  -- 约等于java的continue
		end if;
		-- 	下面这句话能否执行到?什么时候执行到
    leave cnt;

  end loop cnt;
  select result_str;
END $$

delimiter;
call sp_flow_loop02();

Sintaxis de REPEAT: equivalente a DO ... WHILE ... en java

[begin_label:] REPEAT
   statement_list
hasta search_condition - no salga del ciclo hasta ...
END REPEAT [end_label]

 

Por ejemplo:

-- 需求:循环打印1到10
delimiter $$
create PROCEDURE sp_flow_repeat()
BEGIN
	DECLARE c_index int DEFAULT 1;
	-- 	收集结果字符串
	declare result_str VARCHAR(256) DEFAULT '1';
	count_lab:REPEAT
		SET c_index = c_index + 1;
		set result_str = CONCAT(result_str,',',c_index);
		until c_index >= 10;
end REPEAT count_lab;
select result_str;
end $$
delimiter;
call sp_flow_repeat();

 while: analogía con while () en Java {}

 while 语法 :
[begin_label:] while search_condition DO
        statement_list
END WHILE [end_label]

-- 需求:循环打印1到10
delimiter $$
create PROCEDURE sp_flow_while()
begin 
	DECLARE c_index int DEFAULT 1;
	-- 收集结果字符串
  DECLARE result_str VARCHAR(256) DEFAULT '1';

	while c_index < 10 DO
		set c_index = c_index + 1;
		set result_str = CONCAT(result_str,',',c_index);
	end while;
	SELECT result_str;
end $$

delimiter ;
call sp_flow_while();

Cinco, control de proceso-salida, continuar el ciclo

dejar: romper en analogía con java;

-- 退出leave can be used within begin ... end or loop constructs(LOOP,REPEAT,WHILE).
LEAVE label

ITERATE: analogía con java's continue;

-- 继续循环 ITERATE can appear only within LOOP,and while statements
ITERATE label

Seis, cursor

Use el cursor para obtener un determinado conjunto de resultados y procese los datos fila por fila (no se recomienda, porque se escanea fila por fila, lo cual es relativamente ineficiente)
análogo al resultSet de jdbc

-- 声明语法
DECLARE cursor_name CURSOR FOR select_statement

-- 打开语法
OPEN cursor_name

-- 取值语法(当fetch 到底 报错 no datas ) 每次只能一个值
FETCH cursor_name into var_name [,var_name] ...

-- 关闭语法
CLOSE cursor_name

Ejemplos:

-- 需求:按照部门名称查询员工,通过select查看员工的编号、姓名、薪资。(注意,此处仅仅演示游标用法)
drop PROCEDURE if EXISTS sp_create_table;

delimiter $$
create PROCEDURE sp_create_table(in dept_name VARCHAR(32))
BEGIN 
  DECLARE emp_no int;
  DECLARE emp_name VARCHAR(32);
  DECLARE emp_sal DECIMAL(7,2); 

  DECLARE lp_flag boolean DEFAULT true;
 
  DECLARE emp_cursor cursor FOR  
		SELECT e.empno,e.ename,e.sal from emp e 
		inner join departments d 
		on e.deptno = d.id where d.dep_name = dept_name;

  -- handle 句柄
  DECLARE CONTINUE HANDLER for 1329 set lp_flag = false;

  OPEN emp_cursor;

  emp_loop:LOOP
		FETCH emp_cursor into emp_no,emp_name,emp_sal; -- 一个fetch每次只能取一个值
		if lp_flag then 
			SELECT emp_no,emp_name,emp_sal;
		ELSE
			LEAVE emp_loop;
		END IF;
	END LOOP emp_loop;
  set @end_flag = 'end';

  CLOSE emp_cursor;
END $$
delimiter ;
CALL sp_create_table('开发');

presta atención:

En la sintaxis, las declaraciones de variables, las declaraciones de cursor y las declaraciones de manejadores deben escribirse en orden, de lo contrario habrá un error al crear un procedimiento almacenado.

Siete, el identificador en el procedimiento almacenado

HANDLER 语法:
DECLARE handler_action HANDLER 
	for condition_value [,condition_value] ...
statement

handler_ation:{
	CONTINUE
|EXIT
|UNDO
}

conditon_value:{
	mysql_error_code
|SQLSTATE [VALUE] sqlstate_value
|conditon_name
|SQLWARNING
|NOT FOUND
|SQLEXCEPTION
}

 

Supongo que te gusta

Origin blog.csdn.net/LOVE_Me__/article/details/109158646
Recomendado
Clasificación