前情提要
因工作需要要写一些sql脚本,进行一些数据的修改。
直接在数据库ide中写sql涉及就到一些逻辑的判断。
比如判断根据参数判断这条数据存不存在,不存在插入,存在则删除。
最开始查搜索引擎mysql是支持if判断的,根据格式写完sql也不能执行会报错。经过更细致的学习,发现如果要在mysql中进行一些逻辑判断,需要定义存储过程,相当于一些函数,就可以实现一些逻辑判断或者循环。
下面进入正式学习:
1.存储过程书写格式
DELIMITER $$
CREATE PROCEDURE my_procedure()
BEGIN
-- Statement 1
-- Statement 2
END $$
DELIMITER ;
根据格式就可以定义存储过程,写一些需要的逻辑,增删改查
存储过程还可以传递参数并且也可以定义变量,如下例
DELIMITER $$
CREATE PROCEDURE my_procedure(IN param1 INT, OUT param2 INT)
BEGIN
-- Declare an internal variable
DECLARE var1 INT;
-- Perform some calculations using the input parameter
SET var1 = param1 * 2;
-- Update the output parameter with the result
SET param2 = var1;
-- You can perform more statements here, if needed
-- ...
-- The stored procedure will return automatically after this block
END $$
DELIMITER ;
2.存储过程的使用
执行存储过程:
Call my_procedure(1,2) ;
删除执行过程:
DROP PROCEDURE IF EXISTS my_precedure;
3.存储过程执行业务逻辑
(1)逻辑判断:
IF NOT EXISTS (
SELECT
1
FROM
my_table mt
WHERE
-- 可以使用存储过程传入的参数param1
mt.id = param1) THEN
-- 不存在,插入新数据
INSERT
INTO
my_table (id,code,name)
VALUES (null,code,name);
END IF;
(2)循环判断:
存储过程可以使用LOOP
语句来实现循环。以下是一个简单的MySQL存储过程例子,演示如何使用LOOP
循环来计算某个数的阶乘:
DELIMITER $$
CREATE PROCEDURE calculate_factorial(IN number INT, OUT result INT)
BEGIN
DECLARE counter INT DEFAULT 1;
DECLARE factorial INT DEFAULT 1;
-- Check if the input number is negative or zero
IF number <= 0 THEN
SET result = 1;
LEAVE calculate_factorial;
END IF;
-- Loop to calculate the factorial
factorial_loop: LOOP
SET factorial = factorial * counter;
SET counter = counter + 1;
-- Exit the loop when counter reaches the input number + 1
IF counter > number + 1 THEN
LEAVE factorial_loop;
END IF;
END LOOP factorial_loop;
SET result = factorial;
END $$
DELIMITER ;
(3)查询数据并遍历
-- 创建通用的存储过程:将指定表的自定义列分配给特定用户
CREATE PROCEDURE assign_columns_to_user(IN param1 INT, IN param2 INT)
BEGIN
DECLARE colId INT;
DECLARE colName VARCHAR(255);
DECLARE colDescription VARCHAR(255);
-- 声明游标,用于遍历数据集
DECLARE cur CURSOR FOR
SELECT
column_id AS colId,
column_name AS colName,
column_description AS colDescription
FROM
your_table
WHERE
domain_id = param1;
-- 声明异常处理程序
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @finished = 1;
-- 打开游标
OPEN cur;
-- 初始化完成标志
SET @finished = 0;
loop_start: LOOP
-- 读取游标数据
FETCH cur INTO colId, colName, colDescription;
-- 判断是否读取到数据或已完成
IF @finished = 1 THEN
LEAVE loop_start;
END IF;
-- 检查数据是否已分配给用户
IF NOT EXISTS (
SELECT 1
FROM your_table_assign
WHERE column_id = colId AND user_id = param2
) THEN
-- 不存在,插入新数据
INSERT INTO your_table_assign (assign_id, user_id, column_id, column_name, column_description, assigned_flag, domain_id)
VALUES (NULL, param2, colId, colName, colDescription, 1, param1);
END IF;
END LOOP loop_start;
-- 关闭游标
CLOSE cur;
END;
上述代码从your_table表中查询数据使用‘游标’进行循环遍历,利用‘游标’拿到遍历参数后,判断分配表是否存在,不存在则利用参数创建新的数据插入
注:
使用游标过程中可会遇到 No data - zero rows fetched, selected, or processed sql错误
在上述里例子中声明异常处理程序可以规避这个问题
-- 声明异常处理程序
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @finished = 1;
在游标遍历完数据后,能捕获到这个异常,跳出循环。