2009-12-21 63 views
0

我寫用來更新數據庫的PHP腳本,但它給錯誤,當我嘗試它說運行它返回沿單引號

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'id=15"' at line 1 

行的錯誤的查詢「在附近使用」似乎在數據中有空間後顯示部分查詢。林假設我需要把周圍的單引號,其中數據從PHP變量的查詢,但是當我試圖把它們(甚至逃避引號)我從腳本解析錯誤

的SQL查詢

mysql_query("UPDATE Videos SET Title=".$_POST['Title'].", Preacher=".$_POST['Preacher'].", Date=".$_POST['Date'].", Service=".$_POST['Service'].", File=".$_POST['File'].", Description=".$_POST['Description']."WHERE id=".$_GET['vid_id']."\"") or die(mysql_error()); 

預先感謝您的幫助

回答

1

您需要正確轉義變量,用單引號包圍他們:

mysql_query("UPDATE 
       Videos 
      SET 
       Title = '".mysql_real_escape_string($_POST['Title'])."', 
       Preacher = '".mysql_real_escape_string($_POST['Preacher'])."', 
       Date = '".mysql_real_escape_string($_POST['Date'])."', 
       Service = '".mysql_real_escape_string($_POST['Service'])."', 
       File = '".mysql_real_escape_string($_POST['File'])."', 
       Description = '".mysql_real_escape_string($_POST['Description'])."' 
      WHERE 
       id = '".mysql_real_escape_string($_GET['vid_id'])."'") 
or die(mysql_error()); 

沒有正確轉義的變量,你使自己容易受到SQL injection attacks

編輯

爲了簡化上面,你可以做一些小技巧:

// Apply mysql_escape_string to every item in $_POST 
array_map('mysql_real_escape_string', $_POST); 
// Get rid of $_POST, $_POST['Title'] becomes $p_Title 
extract($_POST, EXTR_PREFIX_ALL, 'p_'); 

// Use sprintf to build your query 
$query = sprintf("UPDATE 
       Videos 
      SET 
       Title = '%s', 
       Preacher = '%s', 
       Date = '%s', 
       Service = '%s', 
       File = '%s', 
       Description = '%s' 
      WHERE 
       id = '%s'", 
      $p_Title, 
      $p_Preacher, 
      $p_Service, 
      $p_File, 
      $p_Description, 
      mysql_real_escape_string($_GET['vid_id'])); 

mysql_query($query) or die(mysql_error()); 

注意,混合$ _ POST和$ _GET變量是不鼓勵的。您應該通過表單中的隱藏輸入字段提供更新ID。

+0

哇,接受:)我認爲正確使用sprintf()會更好,無論是爲了可讀性和性能 – drAlberT 2009-12-21 09:04:34

1

如您是在直接使用DB API(無DB抽象層)最好的解決方案是使用DB逃生功能。

只需使用mysql_real_escape_string()

<?php 
// Your query 
$query = sprintf("UPDATE Videos SET Title='%s', preacher='%s', Date='%s', " 
        ."Service='%s', File='%s', Description='%s' WHERE id='%s'", 
       mysql_real_escape_string($_POST['Title']), 
       mysql_real_escape_string($_POST['Preacher']), 
       mysql_real_escape_string($_POST['Date']), 
       mysql_real_escape_string($_POST['Service']), 
       mysql_real_escape_string($_POST['File']), 
       mysql_real_escape_string($_POST['Description']), 
       mysql_real_escape_string(($_GET['vid_id'])); 
?> 

作爲獎勵,你會得到對SQL INJECTION attacs以前的代碼確實提高了安全性是容易。

在這種情況下,您只需跳過斜線,再次使用php/mysql函數addslashes()將在這種情況下完成這項工作。

0

爲什麼你在最後放置一個\",這會使你的SQL的末尾有一個",但你在開始時沒有一個?

試試這個:

mysql_query("UPDATE Videos SET Title=".$_POST['Title'].", Preacher=".$_POST['Preacher'].", Date=".$_POST['Date'].", Service=".$_POST['Service'].", File=".$_POST['File'].", Description=".$_POST['Description']."WHERE id=".$_GET['vid_id']) or die(mysql_error()); 
0

REMOVE \」,從:

id=".$_GET['vid_id']."\"" 
4

mysql_real_escape_string()sql injections已經提到
但現在你的腳本(刻意)與數據/參數,並在未來的混合SQL語句。 (服務器端)prepared statements你的查詢的兩個「部分」都是單獨發送的,你的MySQL服務器的SQL解析器永遠不會「困惑」到哪裏該聲明結束並開始數據。

php-mysql模塊不知道準備好的語句,但php-mysqliPDO做。

$pdo = new PDO('mysql:host=localhost;dbname=test', '...', '...'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$stmt = $pdo->prepare(' 
    UPDATE 
    Videos 
    SET 
    Title=:title , 
    Preacher=:preacher , 
    Date=:date , 
    Service=:service , 
    File=:file , 
    Description=:description 
    WHERE 
    id=:id 
'); 
$stmt->bindParam(':title', $_POST['title']); 
$stmt->bindParam(':preacher', $_POST['preacher']); 
$stmt->bindParam(':date', $_POST['date']); 
$stmt->bindParam(':service', $_POST['service']); 
$stmt->bindParam(':file', $_POST['file']); 
$stmt->bindParam(':description', $_POST['description']); 
$stmt->bindParam(':id', $_GET['id']); // really _GET? 
$stmt->execute(); 

如果您僅對一個操作使用$ stmt,可能會出現很多膨脹。但考慮一下,否則你必須爲每個參數調用mysql_real_escape_string()。

+0

正確,但你也爲每個參數調用bindParm():) – drAlberT 2009-12-21 10:27:58

+0

是的,這是我的觀點 - 只有其他方式;-)整個bindParm()的東西可能看起來像開銷,但你必須調用real_escape_string(),否則(或確保一個數字參數真的是數字) – VolkerK 2009-12-21 11:31:34