【问题标题】:Passing a column name as parameter to a stored procedure in mySQL将列名作为参数传递给 mySQL 中的存储过程
【发布时间】:2019-07-09 22:41:41
【问题描述】:

我正在创建一些存储过程来管理我的数据库。 特别是,我想创建一个存储过程来编辑特定行的列,但我想动态地进行操作,将列名作为参数传递。

这就是我想做的事情

CREATE PROCEDURE myDB.edit_myTable(
    IN key CHAR(16), 
    IN col VARCHAR(100), 
    new_value VARCHAR(200)
)
UPDATE myDB.myTable SET col = new_value

使用参数key我在myTable中找到我想要编辑的特定行,我想使用参数col来编辑我想要的列。

我已经尝试过使用 CONCATE() 或定义局部变量,正如我在其他主题中所读到的,但我还没有找到解决方案。

有什么帮助吗?

【问题讨论】:

    标签: mysql sql stored-procedures sql-update dynamic-sql


    【解决方案1】:

    您需要使用动态 SQL

    DELIMITER //
    CREATE PROCEDURE myDB.edit_myTable(
        IN key CHAR(16), 
        IN col VARCHAR(100), 
        new_value  VARCHAR(200)
    )
    BEGIN
        SET @s = CONCAT(
            'UPDATE myDB.myTable SET `', 
             col, '` = ', QUOTE(new_value),
             ' WHERE key = ', QUOTE(key)
        );
        PREPARE stmt FROM @s;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END
    //
    DELIMITER;
    

    请注意,正如Paul Spiegel 所评论的,使用变量作为列名会产生 SQL 注入的风险。提高安全性的一种解决方案是使用 MySQL 信息模式确保输入 col 确实存在于目标表中:

    DELIMITER //
    CREATE PROCEDURE myDB.edit_myTable(
        IN key CHAR(16), 
        IN col VARCHAR(100), 
        new_value  VARCHAR(200)
    )
    BEGIN
        DECLARE col_exists INT;
    
        SELECT COUNT(*) INTO col_exists 
        FROM  information_schema.COLUMNS
        WHERE TABLENAME = 'mytable' AND COLUMN_NAME = col;
    
        IF (col_exists != 1) THEN
            SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT = CONCAT('Column ', col, ' does not exist in table mytable');
        END IF;
    
        SET @s = CONCAT(
            'UPDATE myDB.myTable SET `', 
             col, '` = ', QUOTE(new_value),
             ' WHERE key = ', QUOTE(key)
        );
        PREPARE stmt FROM @s;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END
    //
    DELIMITER;
    

    【讨论】:

    • 你需要把new_valuekey括起来。
    • 你最好使用QUOTE functioncol, '=', QUOTE(new_value)。它更易于阅读,并且还可以保存注入。但是 - col 参数仍然对 SQL 注入开放。
    • @PaulSpiegel :我试图提供一个针对 SQL 注入的解决方案。
    • 不确定这是否 100% 安全 - 但我喜欢这个想法。最后一件事:col 应该在准备好的语句中用反引号括起来。它可以是保留字,如“订单”或包含空格。
    猜你喜欢
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多