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

时间:2019-03-03 18:28:42

标签: mysql sql

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

Node *constructTreeHelper(FILE *infile, int *index) { 
    double lwire, rwire;
    int sink;
    double cap;
    Node *node;

    // Base case 
    if (*index <= 0) {
        // This test seems redundant with the file contents */
        return NULL; 
    }

    // this fscanf will fail on the byte byte if it is not a '('
    if (fscanf(infile, " (%le %le)", &lwire, &rwire) == 2) {
       // If the node is not a leaf node
        node = createNode(0, 0, lwire, rwire);
        *index -= 1;
        node->right = constructTreeHelper(infile, index); 
        node->left = constructTreeHelper(infile, index); 
    } else if (fscanf(infile, "%d(%le)\n", &sink, &cap) == 2) {
        // If the node is a leaf node
        node = createNode(sink, cap, 0, 0);
        *index -= 1;
    } else {
        // invalid format or end of file */
        node = NULL;
    }
    return node;
} 

错误

CALL insert_data ('table_x', 'NULL', 'A', 'B', 'C', 'D', 'E ')

程序

Column unknown' 0 'in the list of fields.

1 个答案:

答案 0 :(得分:1)

如果您发现具有相同列的多个表,则可能是设计不良的架构。设计良好的架构不需要您要的内容。我鼓励您问另一个问题,关于如何设计架构以完全避免问题。


将未过滤的字符串连接在一起容易受到SQL Injection attack的攻击。取而代之的是,只要有可能,就使用绑定参数并传入值。这样可以确保对它们进行正确的转义和引用,并且不会因意外或恶意而被误解。

SET @q = 'INSERT INTO `' , @tableName, '` VALUES(?,?,?,?,?,?)';
PREPARE stmt FROM @q;
EXECUTE stmt USING @NName, @APName, @AMName, @NomName, @DNIName, @DirectName

这也解决了您的其他问题,并非所有内容都是字符串。

CALL insert_data ('table_x', 'NULL', 'A', 'B', 'C', 'D', 'E ')
                              ^^^^

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


现在关于那个讨厌的表名。我们不能将其作为绑定参数传入。您要确保它不能跳出引号,因此必须将其转义。您也不希望任何人都能跳转到另一个数据库,因此.也必须转义。甚至更好,raise an error。我们不能使用quote(),因为那是针对具有不同引号规则的列值。我们必须自己编写。

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 ;

现在,在使用表名称之前,先对其进行调用。

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;

如果它很顽皮,我们会得到一个错误。

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语句时,您都有遭受错误和安全漏洞的风险。我不相信check_table_name会解决所有问题。

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

if name in ("foo", "bar", "baz", "table_x") then
    set @tableName = name;
else
    signal sqlstate '45000'
        set message_text = 'unknown name';
end if;

我鼓励您改为考虑重新设计架构。