首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在MySQL中向动态表中插入数据?

如何在MySQL中向动态表中插入数据?
EN

Stack Overflow用户
提问于 2019-03-04 02:28:42
回答 1查看 400关注 0票数 0

我尝试使用下面的存储过程在MySQL的动态表中插入数据,但在使用以下命令调用它时遇到错误:

代码语言:javascript
复制
CALL insert_data ('table_x', 'NULL', 'A', 'B', 'C', 'D', 'E ')

错误

代码语言:javascript
复制
Column unknown' 0 'in the list of fields.

操作步骤

代码语言:javascript
复制
DELIMITER $$
CREATE PROCEDURE insertar_datos (name VARCHAR(25), N INT, AP 
VARCHAR(15),
AM VARCHAR(15), Nom VARCHAR(30), DNI VARCHAR(8), Direc VARCHAR(30))
BEGIN
    SET @tableName = Name;
    SET @NName= N;
    SET @APName = AP;
    SET @AMName = AM;
    SET @NomName = Nom;
    SET @DNIName = DNI;
    SET @DirecName = Direc;
    SET @q = CONCAT('
        INSERT INTO `' , @tableName, '` VALUES(
            `',@NName,'`,
            `',@APName,'`,
            `',@AMName,'`,
            `',@NomName,'`,
            `',@DNIName,'`,
            `',@DirecName,'`
        )
    ');
    PREPARE stmt FROM @q;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END $$
DELIMITER;    
EN

回答 1

Stack Overflow用户

发布于 2019-03-04 03:34:57

如果您发现自己有多个具有相同列的表,那么您的模式可能设计得很糟糕。如果有一个设计良好的模式,那么您所要求的就不是必需的。我鼓励您提出另一个问题,即如何设计您的模式以完全避免您的问题。

将未过滤的字符串连接在一起容易受到SQL Injection attack的攻击。相反,只要有可能,就使用绑定参数并将值传入。这确保了它们被正确地转义和引用,并且不会被意外或恶意地曲解。

代码语言:javascript
复制
SET @q = 'INSERT INTO `' , @tableName, '` VALUES(?,?,?,?,?,?)';
PREPARE stmt FROM @q;
EXECUTE stmt USING @NName, @APName, @AMName, @NomName, @DNIName, @DirectName

这也解决了你的其他问题,并不是所有东西都是字符串。

代码语言:javascript
复制
CALL insert_data ('table_x', 'NULL', 'A', 'B', 'C', 'D', 'E ')
                              ^^^^

绑定参数将保留非字符串的类型,如整数和空值。我还会注意到,N是一个整数,但您将其用作名称,这通常意味着字符串。所以这可能是个问题。

现在来看看那个讨厌的表名。我们不能将其作为绑定参数传递。您希望确保它不会跳出引号,所以使用must be escaped. You also don't want anyone to be able to jump to another database, so.must also be escaped. Or better yet, [raise an error](http://www.mysqltutorial.org/mysql-signal-resignal/). We can't use [quote()`](https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_quote),因为这是针对具有不同引号规则的列值。我们得写我们自己的。

代码语言:javascript
复制
DELIMITER $$
drop procedure if exists check_table_name;
CREATE PROCEDURE check_table_name (
    table_name varchar(255)
)
begin
    if( locate("`", table_name) ) then
        signal sqlstate '45000'
            set message_text = 'illegal ` in table name';
    elseif( locate(".", table_name) ) then
        signal sqlstate '45000'
            set message_text = 'illegal . in table name';
    end if;
end $$
DELIMITER ;

现在,我们在使用它之前对表名调用它。

代码语言:javascript
复制
call check_table_name(@tableName);
SET @q = concat('INSERT INTO `' , @tableName, '` VALUES(?,?,?,?,?,?)');
PREPARE stmt FROM @q;
EXECUTE stmt USING @NName, @APName, @AMName, @NomName, @DNIName, @DirecName;
DEALLOCATE PREPARE stmt;

如果它是淘气的,我们会得到一个错误。

代码语言:javascript
复制
mysql> call insertar_datos("foo`haha, I broke your quoting`bar", 23, 'A', 'B', 'C', 'D', 'E ');
ERROR 1644 (45000): illegal ` in table name

但是,,我强烈反对这种方法。任何时候,当您将字符串连接在一起以生成SQL语句时,就有可能出现bug和安全缺陷。我不相信所有的问题都是check_table_name造成的。

如果您必须采用这种方法,请考虑改用一组固定的允许名称。

代码语言:javascript
复制
if name in ("foo", "bar", "baz", "table_x") then
    set @tableName = name;
else
    signal sqlstate '45000'
        set message_text = 'unknown name';
end if;

我鼓励您重新考虑重新设计您的模式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54972244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档