【问题标题】:MySQL (Stored) Procedure - parameters and queryMySQL(存储)过程 - 参数和查询
【发布时间】:2013-10-10 12:19:20
【问题描述】:

我正在尝试创建一个带参数的简单过程。

CALL new_procedure('mode', 'ASC');

第一个输入是列,第二个是排序方向

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `new_procedure`(IN in_order_by_column varchar(20), in_order_by_direction char(4))
BEGIN

    DECLARE order_by varchar(30);
    SET @order_by = CONCAT('`', in_order_by_column, '` ', in_order_by_direction);
/*
    SELECT * FROM `common_tags` ORDER BY @order_by  LIMIT 5;
*/
    SELECT @order_by as 'c';

END

在上面的例子中,我只输出了 2 个参数,所以我可以看到发生了什么。

结果:

"c"
`mode` ASC

.

当我使用预期代码运行该过程时,如下所示。

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `new_procedure`(IN in_order_by_column varchar(20), in_order_by_direction char(4))
BEGIN

    DECLARE order_by varchar(30);
    SET @order_by = CONCAT('`', in_order_by_column, '` ', in_order_by_direction);
    SELECT * FROM `common_tags` ORDER BY @order_by  LIMIT 5;

END

结果

tags_id     data                mode        parent_id       position
1           Wood                2           13              6
2           Trippy              0           0               0
4           Artists             1           0               1
6           "Newest Additions"  1           0               11
12          "Natural Elements"  2           5               8

如您所见,结果未按mode 排序。

感谢任何帮助。

【问题讨论】:

    标签: mysql stored-procedures


    【解决方案1】:

    很遗憾,在这种情况下,您需要PREPARE 整个查询:

    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS `new_procedure`$$
    
    CREATE PROCEDURE `new_procedure`(IN in_order_by_column varchar(20), in_order_by_direction char(4))
    BEGIN
        SET @buffer = CONCAT_WS('',
            'SELECT * FROM `common_tags` ORDER BY `', in_order_by_column, '` ', in_order_by_direction, ' LIMIT 5'
        );
    
        PREPARE stmt FROM @buffer;
        EXECUTE stmt;
    
        DEALLOCATE PREPARE stmt;
    END$$
    
    DELIMITER ;
    

    注意:非常小心使用所描述的方法,因为如果使用不当,很容易受到 SQL 注入攻击。

    【讨论】:

    • 您可能希望使用quote() 引用输入值,请参阅dev.mysql.com/doc/refman/8.0/en/…
    • @Leukipp OP 正在尝试使用不同的列和方向来构建查询。您建议的函数旨在转义值,而不是用于列、方向或任何查询描述部分。
    • 我的评论提到了您关于构造查询易受 SQL 注入攻击的注释。
    • 澄清@Leukipp的建议:这个特定的构造查询只使用参数作为列名SQL关键字 - 使用quote()会导致错误。就像 BlitZ 一样,通过用反引号包围列名来保护列名不被注入。 Leukipp 的评论对于将这种技术用于查询中作为 values 的参数的任何人来说确实很有用(因此在不同的 concat'd 查询中对我很有用,以避免 SQL 注入)。
    • 关于 SQL 注入的更多信息:in_order_by_direction 不受保护;更好的方法是传入一个经过测试的布尔值,在 CONCAT 查询时替换为 ASCDESC。为了安全起见,查询的每个部分都必须通过某种方式加以保护。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    相关资源
    最近更新 更多