mysql(十)条件语句、循环语句、动态执行SQL语句

本文介绍了MySQL中流程控制语句的应用,包括条件语句、循环语句等,并详细讲解了如何通过存储过程实现动态SQL的执行,有效避免SQL注入风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MySQL数据库-条件语句、循环语句、动态执行SQL语句

 

1、if条件语句

复制代码
delimiter \\
CREATE PROCEDURE proc_if ()
BEGIN
    
    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END\\
delimiter ;
复制代码

 

 

 

2、循环语句

while循环

复制代码
delimiter \\
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END\\
delimiter ;
复制代码

repeat循环

复制代码
delimiter \\
CREATE PROCEDURE proc_repeat ()
BEGIN

    DECLARE i INT ;
    SET i = 0 ;
    repeat
        select i;
        set i = i + 1;
        until i >= 5
    end repeat;

END\\
delimiter ;
复制代码

loop循环

iterate loop_label退出循环

复制代码
BEGIN
    
    declare i int default 0;
    loop_label: loop
        
        set i=i+1;
        if i<8 then
            iterate loop_label;
        end if;
        if i>=10 then
            leave loop_label;
        end if;
        select i;
    end loop loop_label;

END
复制代码

 

 

3、动态执行SQL语句

动态执行SQL语句,也就是执行一个存储过程来动态执行SQL语句

举例:有这样一张表

 

 

写一个存储过程无参,获取表里id大于11的数据

PREPARE prod FROM存储过程里将字符串解析为sql语句执行,后面跟字符串类型的sql语句

EXECUTE prod USING替换sql语句中的占位符,后面跟要替换占位符的、占位符变量,(sql语句中的占位符是?号)

 

复制代码
delimiter $$
DROP PROCEDURE IF EXISTS proc_sql $$ -- 判断proc_sql存储过程存在删除
CREATE PROCEDURE proc_sql () -- 创建proc_sql存储过程
BEGIN
    declare p1 int;  -- 设置p1变量
    set p1 = 11;     -- 赋值p1变量等于11
    set @p1 = p1;    -- 赋值字符串占位符变量等于p1

    PREPARE prod FROM 'select * from tb2 where nid > ?';  -- 解析字符串为sql语句
    EXECUTE prod USING @p1;   -- 执行sql语句,并且用占位符变量替换sql语句中的?号
    DEALLOCATE prepare prod;  -- 释放解析和执行sql语句

END $$
delimiter ;
复制代码

执行存储过程,动态执行sql语句

CALL proc_sql();  -- 执行存储过程,动态执行sql语句

 

 

写一个存储过程有参,动态传参获取数据

复制代码
delimiter $$
DROP PROCEDURE IF EXISTS proc_sql $$ -- 判断proc_sql存储过程存在删除
CREATE PROCEDURE proc_sql (          -- 创建proc_sql存储过程
    in zfchsql CHAR(90),       --  zfchsql接收字符串最大90字符,接收sql语句
    in shuzi INT(20)           --  shuzi接收整数类型,最大20字符,接收一个id数
) 
BEGIN
        -- 因为解析字符串为sql语句,和替换sql语句的占位符,需要用户变量,也就是有@的变量,所以需要重新赋值成用户变量
        SET @zfchsql = zfchsql;
        SET @shuzi = shuzi;

    PREPARE prod FROM @zfchsql;  -- 将接收到的字符串解析为sql语句
    EXECUTE prod USING @shuzi;   -- 将接收到的整数,替换sql语句中的?号占位符
    DEALLOCATE prepare prod;  -- 释放解析和执行的sql语句

END $$
delimiter ;
复制代码

传入参数动态执行sql语句

CALL proc_sql('select * from usr where id > ?',5);  -- 传入参数动态执行sql语句

 

 

重点:动态执行sql语句,可以防止sql注入,

CALL proc_sql('select * from usr -- where id > ?',5);  -- 传入参数动态执行sql语句

<think>嗯,用户想了解如何在MySQL中使用循环执行删除语句的方法。我先看看用户提供的参考引用,发现其中有不少相关信息。用户引用了四篇资料,仔细一看:第一篇讲的是根据查询结果循环执行SQL的基本流程;第二篇讨论如何监控正在执行SQL语句;第三篇详细介绍了用存储过程实现循环操作的具体语法,包括LOOP和REPEAT的示例;第四篇则涉及查看执行SQL的方法。这些资料很全面啊,特别是第三篇对存储过程的说明非常实用。结合用户需求来想,用户明显需要动态删除数据的场景。不过要提醒用户注意,MySQL的DELETE语句本来就能用WHERE条件批量删除,多数情况下根本不需要循环。只有在需要逐条处理或有特殊逻辑时才用循环。我准备用存储过程来实现循环删除,这样效率高又安全。在存储过程里可以这么设计:先用游标安全遍历要删除的数据集,每取一条记录就执行删除。这样能避免锁表问题。参考第三篇引用的存储过程写法,DECLARE声明变量很重要,BEGIN和END的代码块结构也要写规范。得特别注意循环内的COMMIT频率控制,防止大事务超时。对了用户可能是新手,我得强调安全事项。比如测试时用SELECT替代DELETE验证逻辑,循环删除前务必备份数据。事务控制也很关键,最好每次删少量就COMMIT一次。这些安全措施比单纯给代码更重要。示例结构可以这样:先创建测试表和示例数据,然后写带游标的存储过程。在循环内用IF添加条件判断的演示会更实用。最后别忘了让用户调用存储过程的步骤。这个方案应该能满足需求了。用户可能还会关心如何监控执行进度,这正好用上第二篇引用的监控方案,比如SHOWPROCESSLIST。不过实际执行时用SELECT看进度更直观。这些细节也要点到。</think> 以下是在 MySQL 中使用存储过程通过循环执行删除语句的完整示例教程,结合核心引用内容整理: --- ### 一、循环删除的实现方法 **核心原理**:通过存储过程中的游标(Cursor)逐行获取待删除数据,再执行动态 SQL 删除操作(参考引用[3])。 ### 二、示例教程 #### 1. 创建测试数据 ```sql CREATE TABLE `user_log` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `log_time` DATETIME NOT NULL ); -- 插入示例数据 INSERT INTO `user_log` (`user_id`, `log_time`) VALUES (1, '2023-01-01'), (1, '2023-02-01'), (2, '2023-01-15'), (3, '2024-05-01'); -- 符合保留条件的数据 ``` #### 2. 创建循环删除存储过程 ```sql DELIMITER $$ -- 修改分隔符(引用[3]) CREATE PROCEDURE batch_delete_old_logs() BEGIN DECLARE done BOOLEAN DEFAULT FALSE; DECLARE target_id INT; DECLARE target_time DATETIME; -- 声明游标:查询所有 2024 年之前的日志 DECLARE cur CURSOR FOR SELECT user_id, log_time FROM user_log WHERE log_time < '2024-01-01'; -- 删除条件 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; -- 打开游标 -- 开始循环 delete_loop: LOOP FETCH cur INTO target_id, target_time; IF done THEN LEAVE delete_loop; END IF; -- 执行删除(核心操作) DELETE FROM user_log WHERE user_id = target_id AND log_time = target_time; -- 可选:添加事务控制(每删除 100 条提交一次) END LOOP; CLOSE cur; -- 关闭游标 END$$ DELIMITER ; -- 恢复分隔符 ``` #### 3. 执行存储过程 ```sql CALL batch_delete_old_logs(); -- 调用存储过程 ``` #### 4. 监控执行状态(引用[2][4]) ```sql -- 查看正在执行SQL SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND = 'Query' AND INFO LIKE '%DELETE%'; ``` --- ### 三、关键注意事项 1. **游标与循环** - 使用 `DECLARE cur CURSOR FOR ...` 定义待处理数据集 - `LOOP ... END LOOP` 结构实现逐行操作(引用[3]) 2. **安全建议** - 测试阶段先用 `SELECT` 替代 `DELETE` 验证条件 - 重要数据提前备份:`CREATE TABLE backup_table AS SELECT * FROM original_table;` 3. **性能优化** - 在循环内添加分批提交逻辑: ```sql IF @count % 100 = 0 THEN COMMIT; END IF; SET @count = @count + 1; ``` 4. **替代方案** 简单条件可直接批量删除: ```sql DELETE FROM user_log WHERE log_time < '2024-01-01'; -- 避免循环 ``` --- ### 四、典型应用场景 1. 分批次清理历史数据(如日志表) 2. 需要动态拼接条件的复杂删除操作 3. 数据迁移前的有选择清理 > **提示**:实际业务中优先尝试批量删除,仅在处理复杂逻辑时使用循环方案[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值