将列名作为参数传递给mySQL中的存储过程

时间:2019-02-15 18:35:49

标签: mysql sql database mysql-workbench

我正在创建一些存储过程来管理数据库。 特别是,我想创建一个存储过程来编辑特定行的一列,但是我想通过将列名作为参数传递来做到这一点。

这就是我想要做的

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

使用参数keymyTable中找到我要编辑的特定行,并且我想使用参数col仅编辑我想要的列。 / p>

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

有帮助吗?

1 个答案:

答案 0 :(得分:2)

您将需要使用动态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;