微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有游标和准备语句问题的过程:您的 SQL 语法有错误;执行 stmt;解除分配准备 stmt; END L' 在第 34 行

如何解决带有游标和准备语句问题的过程:您的 SQL 语法有错误;执行 stmt;解除分配准备 stmt; END L' 在第 34 行

我有一个适用于 10.3.28-MariaDB 的过程,但是我在 MysqL 5.7.26 中发现了一些问题。该过程采用所有过程/功能,在某个日期后更改,并将对它们的执行权限授予特定用户

CREATE PROCEDURE ExecuteGrantsForModifiedProcedures(IN p_schema varchar(120),IN p_MysqLUser varchar(120),IN p_fromModificationDate datetime)
BEGIN
    DECLARE v_done INT DEFAULT FALSE;
    DECLARE v_statement TEXT;
    # Get all the modified procedures/functions
    DECLARE cur1 CURSOR FOR SELECT CONCAT('GRANT EXECUTE ON PROCEDURE `',ROUTINE_SCHEMA,'`.`',routine_name,'` TO ',p_MysqLUser,';')
                            FROM information_schema.routines
                            where routine_schema = p_schema
                              AND ROUTINE_TYPE = 'PROCEDURE'
                              AND date(LAST_ALTERED) >= date(p_fromModificationDate)
                            UNION
                            SELECT CONCAT('GRANT EXECUTE ON FUNCTION `',';')
                            FROM information_schema.routines
                            where routine_schema = p_schema
                              AND ROUTINE_TYPE = 'FUNCTION'
                              AND date(LAST_ALTERED) >= date(p_fromModificationDate);

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;

    SET max_sp_recursion_depth = 1024;

    OPEN cur1;

    read_loop:
    LOOP
        FETCH cur1 INTO v_statement;
        IF v_done THEN
            LEAVE read_loop;
        END IF;
        PREPARE stmt FROM v_statement;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END LOOP;

    CLOSE cur1;

end;

当我尝试运行过程创建语句时,MysqL 显示错误

[1064] 你的 sql 语法有错误;检查与您的 MysqL 服务器版本相对应的手册,以获取在 'v_statement 附近使用的正确语法;执行 stmt;解除分配准备 stmt; END L' 在第 34 行

解决方法

在 MySQL 中,PREPARE 中只能使用用户定义的变量。所以删除 v_statement 声明并在任何地方使用 @v_statement

CREATE PROCEDURE ExecuteGrantsForModifiedProcedures(IN p_schema varchar(120),IN p_mysqlUser varchar(120),IN p_fromModificationDate datetime)
BEGIN
    DECLARE v_done INT DEFAULT FALSE;
    DECLARE v_statement TEXT;
    # Get all the modified procedures/functions
    DECLARE cur1 CURSOR FOR SELECT CONCAT('GRANT EXECUTE ON PROCEDURE `',ROUTINE_SCHEMA,'`.`',routine_name,'` TO ',p_mysqlUser,';')
                            FROM information_schema.routines
                            where routine_schema = p_schema
                              AND ROUTINE_TYPE = 'PROCEDURE'
                              AND date(LAST_ALTERED) >= date(p_fromModificationDate)
                            UNION
                            SELECT CONCAT('GRANT EXECUTE ON FUNCTION `',';')
                            FROM information_schema.routines
                            where routine_schema = p_schema
                              AND ROUTINE_TYPE = 'FUNCTION'
                              AND date(LAST_ALTERED) >= date(p_fromModificationDate);

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;

    SET max_sp_recursion_depth = 1024;

    OPEN cur1;

    read_loop:
    LOOP
        FETCH cur1 INTO v_statement;
        IF v_done THEN
            LEAVE read_loop;
        END IF;
        SET @v_statement := v_statement;
        PREPARE stmt FROM @v_statement;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END LOOP;

    CLOSE cur1;

end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。