【MySQL教程】MySQL 存储过程简单学习

零 Mysql教程评论81字数 3513阅读11分42秒阅读模式

MySQL 存储过程是一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字和参数值来调用它。存储过程可以接收参数,并可以返回结果。存储过程可以看作是对一系列 SQL 操作的封装和重用,它可以提高数据库操作的效率和安全性。

以下是 MySQL 存储过程的基本用法:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

1. 创建存储过程

使用 CREATE PROCEDURE 语句来创建存储过程。语法如下:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
CREATE PROCEDURE procedure_name([parameters])
BEGIN
    -- SQL 语句集
END;

其中,procedure_name 是存储过程的名称,parameters 是存储过程的参数列表(可选)(parameters = [IN|OUT|INOUT] parameter_name data_type, ...),在 BEGIN 和 END 之间编写要执行的 SQL 语句集。文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

例如,创建一个简单的存储过程,用于向表中插入数据:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
DELIMITER //
CREATE PROCEDURE InsertData(IN param1 INT, IN param2 VARCHAR(255))
BEGIN
    INSERT INTO your_table_name (column1, column2) VALUES (param1, param2);
END //
DELIMITER ;

注意:DELIMITER 用于改变 MySQL 的命令结束符,因为存储过程内部可能包含多个 SQL 语句,需要使用不同的结束符来区分它们。文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

2. 调用存储过程

使用 CALL 语句来调用存储过程。语法如下:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
CALL procedure_name([parameters]);

其中,procedure_name 是存储过程的名称,parameters 是传递给存储过程的参数值(如果有的话)。例如,调用上面创建的 InsertData 存储过程:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
CALL InsertData(1, 'Test');

3. 删除存储过程

  • 修改存储过程:MySQL 不直接支持修改存储过程,如果需要修改存储过程,通常的做法是先删除原有的存储过程,然后重新创建。
  • 删除存储过程:使用 DROP PROCEDURE 语句来删除存储过程。语法如下:

sql

复制代码
DROP PROCEDURE IF EXISTS procedure_name;

4. 存储过程的参数

存储过程的参数有三种类型:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

  • IN:输入参数,用于传递值给存储过程。存储过程内部可以使用,但不能修改。
  • OUT:输出参数,用于从存储过程获取值。存储过程内部可以修改,并且在存储过程执行完后可以返回给调用者。
  • INOUT:既是输入参数也是输出参数。既可以传递值给存储过程,也可以从存储过程获取值。

5. 存储过程的变量

sql

复制代码
DECLARE variable_name data_type [DEFAULT value];

6. 存储过程的示例

sql

复制代码
DELIMITER //
CREATE PROCEDURE get_employee(IN emp_id INT)
BEGIN
    SELECT * FROM employees WHERE emp_id = emp_id;
END //
DELIMITER;
DELIMITER //
CREATE PROCEDURE add_employee(IN emp_name VARCHAR(255), IN emp_salary INT)
BEGIN
   INSERT INTO employees (name, salary) VALUES (emp_name, emp_salary);
END //
DELIMITER;
CALL get_employee(1);
CALL add_employee('John Doe', 5000);

这次写的一个示例,用于删除日志大表中过期的数据:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
CREATE PROCEDURE `delete_expired_log_procedure`(IN __table_name varchar(1000), IN __colume_name varchar(100), IN __id_value bigint, IN __limit int, IN __times int)
BEGIN
    # 开始执行时间
    DECLARE _start_time DATETIME DEFAULT now();
    # 每次删除行数M
    DECLARE _row INT DEFAULT __limit;
    # 总计删除行数
    DECLARE _total_row INT DEFAULT 0;
    # 总计删除次数N
    DECLARE _times INT DEFAULT 0;

    SET @_sql = 'DELETE FROM $TABLE_NAME$ WHERE $COLUME_NAME$ <= $ID_VALUE$ LIMIT $LIMIT$';

    SET @_sql = REPLACE(@_sql, '$TABLE_NAME$', __table_name);
    SET @_sql = REPLACE(@_sql, '$COLUME_NAME$', __colume_name);
    SET @_sql = REPLACE(@_sql, '$ID_VALUE$', __id_value);
    SET @_sql = REPLACE(@_sql, '$LIMIT$', __limit);
    SET @_remark = concat(@_sql, '; 每次影响行数=');

    # 每次删除M行,最多删除N次, 如果有一次删除行数不等于M就退出循环
    WHILE _times < __times AND _row = __limit
        DO # 每次删除M行
            START TRANSACTION;
            PREPARE stmt FROM @_sql;
            EXECUTE stmt;
            # 获取实际删除的行数
            SELECT ROW_COUNT() INTO _row;
            DEALLOCATE PREPARE stmt;
            COMMIT;
            SET @_remark = concat(@_remark, _row, ', ');

            SET _total_row = _total_row + _row;
            SET _times = _times + 1;
        END WHILE;

    # 保存执行日志
    INSERT INTO a_delete_task_log (table_name, delete_row_count, start_time, end_time, create_time, remark)
    VALUES (__table_name, _total_row, _start_time, now(), now(), concat('执行次数=', _times, ', sql=', @_remark));
END

用于存储执行记录的表:文章源自灵鲨社区-https://www.0s52.com/bcjc/mysqljc/15384.html

sql

复制代码
CREATE TABLE `a_delete_task_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `table_name` varchar(100) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '表名',
  `delete_row_count` int NOT NULL DEFAULT '0' COMMENT '删除的记录数',
  `start_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务开始时间',
  `end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务结束时间',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `remark` varchar(500) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='删除任务日志表';

后续我们是通过一个 MySQL 定时任务 Event 来调度执行的。

7. 存储过程的优点

  • 代码重用:存储过程可以被多次调用,提高了代码的重用性。
  • 性能优化:存储过程在创建时会被编译并存储在数据库中,减少了 SQL 语句的解析和编译时间,提高了执行效率。
  • 事务处理:存储过程可以包含复杂的逻辑和事务处理,确保数据的一致性和完整性。

不过在阿里出的 Java 开发手册里倒是提到了禁止使用存储过程,原文是【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。 不过我在以前的公司也从没使用过存储过程。

零
  • 转载请务必保留本文链接:https://www.0s52.com/bcjc/mysqljc/15384.html
    本社区资源仅供用于学习和交流,请勿用于商业用途
    未经允许不得进行转载/复制/分享

发表评论