2016-09-22 54 views
-1

誰能告訴我什麼是錯的這個查詢:我有一個查詢問題

$query = "INSERT INTO ideas_tbl (idea, desc) VALUES ('$idea', '$desc')"; 
+0

wats error? –

+1

'desc'是一個SQL關鍵字(想'ORDER BY')。我投票結束了簡單的印刷錯誤等問題。 –

+0

它容易受到[SQL注入攻擊](https://en.wikipedia.org/wiki/Sql_injection_attack)的影響。爲了避免這個問題以及其他許多問題,請使用[綁定參數](https://metacpan.org/pod/DBI#Placeholders-and-Bind-Values)。 – Schwern

回答

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。這裏我假設這是Perl使用DBI。

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"