我有一个查询问题

时间:2016-09-22 18:44:01

标签: sql

有谁能告诉我这个查询有什么问题:

$this->set(compact('initial_dept_id', 'index_chosen'));

1 个答案:

答案 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"放在每个查询上。