有谁能告诉我这个查询有什么问题:
$this->set(compact('initial_dept_id', 'index_chosen'));
答案 0 :(得分:0)
As @GordonLinoff mentioned in a comment问题是desc
是一个SQL关键字。像这样使用,SQL服务器可能会将其视为一段语法,而不是列名,并且会感到困惑。 SQL关键字列表因服务器而异,但here's a good baseline list from SQLite。
有两种解决方案。首先引用"
列。某些数据库将使用`
(MySQL)或[]
(Microsoft),但"
是SQL标准。可以将不合格数据库配置为支持"
标准,例如MySQL has ANSI_QUOTES。
这也意味着要么使用balanced quoting operators转义引号或我的首选选项(假设这是Perl)。
$query = qq[INSERT INTO ideas_tbl (idea, "desc") VALUES ('$idea', '$desc')];
我不喜欢这个选项,因为这意味着每次使用该列时都必须记住引用它。更好的选择是将列重命名为“description”之类的其他内容。
现在让我们谈谈您的安全漏洞。因为您已将变量直接放入查询字符串中,所以您的代码容易受到SQL Injection Attack的攻击。这是最常见的安全漏洞之一。如果$idea
或$desc
来自用户输入,那么聪明的人可以制作一些可以跳出引号并被解释为更多SQL的数据。这也可能是无意义的,例如$desc = "Our prices can't be beat!"
你可以做各种引用,但为了完全击败它,并加快你的代码,请使用prepared statements and bind parameters。在这里,我假设这是使用DBI的Perl。
my $sth = $dbh->prepare(q{
INSERT INTO ideas_tbl
(idea, description)
VALUES (?, ? )
};
$sth->execute($idea, $desc);
另一个优点是现在您可以重用此语句句柄,避免了重新编译它的开销。就像你在循环一系列想法一样。
for my $idea (@ideas) {
$sth->execute( $idea->{idea}, $idea->{desc} );
}
最后,我怀疑您在查询失败时没有收到错误消息,这就是您提出问题的原因。遗憾的是,默认情况下,DBI不会将SQL错误视为错误。如果您在每次查询后忘记or die
,则不会收到错误。
要避免这种情况,请在连接(最佳)或之后打开RaiseError。
my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 });
or
$dbh->RaiseError(1);
现在所有失败的查询都会引发错误。无需记住将or die "Something failed because $DBI::errstr"
放在每个查询上。