2

多年来,我一直在开发中使用以下代码段。现在突然间我得到一个数据库错误:没有这样的字段警告

$process = "process";
$create = $connection->query
(
    "INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));

但如果我使用数字也没关系

$process = "12345";
$create = $connection->query
(
    "INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));

或将值直接写入表达式

$create = $connection->query
(
    "INSERT INTO summery (process) VALUES('process')"
);
if (DB::isError($create)) die($create->getMessage($create));

我真的很困惑......有什么建议吗?

4

2 回答 2

7

使用准备好的查询和参数占位符总是更好。在 Perl DBI 中就像这样:

my $process=1234;
my $ins_process = $dbh->prepare("INSERT INTO summary (process) values(?)");
$ins_process->execute($process);

为了获得最佳性能,请在打开数据库连接后立即准备所有常用查询。许多数据库引擎会在会话期间将它们存储在服务器上,就像小型临时存储过程一样。

它对安全性也很有好处。自己将值写入插入字符串意味着您必须在每个 SQL 语句中编写正确的转义码。使用准备和执行风格意味着只有一个地方(执行)需要知道转义,如果转义甚至是必要的。

于 2008-11-30T19:36:53.890 回答
0

与 Zan Lynx 关于占位符的说法相同。但是您可能仍然想知道为什么您的代码失败了。

您似乎忘记了之前为您工作多年的代码中的一个关键细节:引号。

这个(经过测试的)代码工作正常:

my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
                              VALUES (3,'$thing')");
$sth->execute;

但是下一个代码(就像您的第一个示例一样,在 VALUES 字段中缺少引号)会产生您报告的错误,因为 VALUES (3,$thing) 解析为 VALUES (3,abcde) 导致您的 SQL 服务器查找字段称为 abcde 并且没有该名称的字段。

my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
                              VALUES (3,$thing)");
$sth->execute;

所有这些都假设您的第一个示例不是直接引用您描述的失败的代码,因此不是您想要的。它解决:

"INSERT INTO summery (process) VALUES(process)"

如上所述,这会导致您的 SQL 服务器将 VALUES 集中的项目读取为另一个字段名称。如给定的那样,这实际上在 MySQL 上运行而没有抱怨,并将用 NULL 填充名为“process”的字段,因为当 MySQL 在创建新记录时在那里查找值时,名为“process”的字段包含的内容。

我确实将这种风格用于涉及已知的安全数据(例如程序本身提供的值)的快速丢弃黑客。但是对于任何涉及来自程序外部的数据或可能包含 [0-9a-zA-Z] 以外的数据的任何内容,使用占位符都会让您省心。

于 2008-12-01T04:24:33.217 回答