2011-10-05 75 views
1

我有form.php在其中创建或编辑记录。这个页面被一个'New Record'链接调用,在这种情况下没有ID集合,或者通过'EDIT'链接调用$ _GET ['ID']来设置(并用于检索记录)。'ON DUPLICATE KEY UPDATE',SET选项需要正确的语法

计划A是: 将form.php提交给process.php;在process.php中,如果有一个ID,查询是一个UPDATE,否则它是一个INSERT。在某一时刻,这个if/else是按照预期工作的,但是令人耳目一新,因此我开始玩'ON DUPLICATE KEY UPDATE',但是没有成功。 B计划最终发生在我小小的脑子里:不应该process.php只有一个INSERT查询,加上ON DUPLICATE KEY UPDATE?还没有得到这个工作。

process.php:

<?php 
    // get $_POST from form.php *** note: no ID if it's a New Record *** 
    $id  = $_POST['ID']; 
    $invNumber = $_POST['invoice-number']; 
    $invDate = $_POST['invoice-date']; 
    $projNumber = $_POST['project-number']; 
    $client = $_POST['client']; 
    $issueDate = $_POST['issue-date']; 
    $task  = $_POST['task']; 
    $subTotal = $_POST['sub-total']; 
    $tax  = $_POST['tax']; 
    $invTotal = $_POST['invoice-total']; 
    $datePaid1 = $_POST['payment-date-1']; 
    $datePaid2 = $_POST['payment-date-2']; 
    $comments = $_POST['comments']; 

    if (isset($_POST['submit'])) { 
     $query = "INSERT INTO $table SET 
      invNumber = '$invNumber', 
      invDate  = '$invDate', 
      projNumber = '$projNumber', 
      client  = '$client', 
      task   = '$task', 
      issueDate = '$issueDate', 
      subTotal  = '$subTotal', 
      tax   = '$tax', 
      invTotal  = '$invTotal', 
      datePaid1 = '$datePaid1', 
      datePaid2 = '$datePaid2', 
      comments  = '$comments' 

      ON DUPLICATE KEY UPDATE 
      invNumber = $invNumber, 
      invDate  = $invDate, 
      projNumber = $projNumber, 
      client  = $client, 
      task   = $task, 
      issueDate = $issueDate, 
      subTotal  = $subTotal, 
      tax   = $tax, 
      invTotal  = $invTotal, 
      datePaid1 = $datePaid1, 
      datePaid2 = $datePaid2 
      ID    = LAST_INSERT_ID(ID) 
     "; 

     $lastID = mysql_insert_id(); 
     $result = mysql_query($query) or die(mysql_error()); 
     $affRows = mysql_affected_rows(); 
     if (($result) && ($affRows)) { 
      echo "<p class=\"status\"> 
      <strong>RECORD #".$id." UPDATED.</strong><br /> 
      <strong>Records updated: " . $affRows . "</strong> 
      </p>"; 
     } // END if ($result ... 
    } // END CASE 1 
?> 

刷新process.php的INSERT愚弄是否有一个ID或没有。我的'ID'列,btw,是主键,唯一索引,自动递增。那么,如何在$查询或者插入或UPDATEing之前检查的ID?[进入拉头发出的陈词滥调随后几天的研究和实验夜]

在此先感谢,S

附:回复:注:

我已经包括此块在我head.php - 请让我知道,如果这涵盖了注射:

<?php 
    // prevent SQL Injection in $_POST variables: 
    foreach ($_POST as $key => $value) { 
     $_POST[$key] = mysql_real_escape_string($value); 
    } 

    // prevent SQL Injection in $_GET variables: 
    foreach ($_GET as $key => $value) { 
     $_GET[$key] = mysql_real_escape_string($value); 
    } 
?> 
+0

您可以通过引用'VALUES'来简化您的'ON DUPLICATE KEY UPDATE'子句。请参阅http://stackoverflow.com/questions/302544/is-there-a-way-to-do-an-insert-on-duplicate-key-udpate-in-zend-framework/1207076#1207076 – 2011-10-05 23:58:29

+0

感谢凤凰城。我一直坚持SET选项,因为我发现它更易于阅读。根据我迄今为止阅读的内容,我不了解使用VALUES的其他优点,除非它是解决我目前问题的唯一方案。干杯! – shecky

回答

6

修复了SQL注入孔
你不能插入$_POST瓦尔(或任何超全球$_*直接进入查询。
这是一个SQL注入漏洞。

而是执行此操作:

$id = mysql_real_escape_string($_POST['ID']); 
$invnumber = mysql_real_escape_string($_POST['invoice_number']); 
.... 
etc 

INSERT .. ON DUPLICATE KEY UPDATE正确的语法是:

INSERT INTO TABLE (ID,invNumber,invDate,projNumber,client,task,issueDate 
        ,subTotal,tax,invTotal,datePaid1,datePaid2,comments) 
VALUES ('$id','$invNumber','$invDate','$projNumber','$client','$task' 
     ,'$issueDate','$subTotal','$tax','$invTotal','$datePaid1','$datePaid2' 
     ,'$comments') 
ON DUPLICATE KEY UPDATE invNumber = '$invNumber', invDate = '$invDate', ..... 

最后一行也可以改为(所以,你的代码没有通过参数数据两次):

ON DUPLICATE KEY UPDATE invNumber = VALUES(invNumber) 
         , invDate = VALUES(invDate) 
         , ..... 
         , comments = VALUES(comments) 

请勿在更新部分使用主键和唯一键
请注意,insert部分中的字段与您的update部分中的字段完全相同是没有意义的。
如果您使用此语句,则更新部分必须排除SET子句中的所有主键和唯一键!

+1

正确的语法也可以是:'ON DUPLICATE KEY UPDATE invNumber = VALUES(invNumber),invDate = VALUES(invDate),..... ' –

+0

而且我认为这是'重复密钥更新'。 'ON DUPLICATE KEY ** SET **'有效的语法? –

+0

谢谢Johan&ypercube。请注意我编辑的问题;我非常感谢确认我包含在head.php中的代码足以防止注入。 – shecky

1

首先我必须说,对重复密钥更新不彪替换UPDATE,在这种情况下,我将使用INSERT作为新数据,并在现有数据被修改时更新UPDATE。

要在您的脚本中创建ON D​​UPLICATE KEY UPDATE触发器,您还必须将该ID添加到INSERT中,因为这是您正在使用的唯一列。

如果它找到该ID,它将触发查询的ON DUPLICATE部分。

+0

我喜欢你,但你忘记了SQL注入,所以我不能:-( – Johan

+2

呵呵,我仍然在学习如何“教”,这可能是我没有提到注入问题的原因:)从每个帖子我都会学习新的东西,就像现在一样解决您发现的所有问题,即使它们不是原始问题的一部分:P – Ole

+0

Thx Helbom。正如我注意到的,我的原始设置是按照您的描述:插入新数据,更新编辑过的数据......但后来我必须解决模糊问题,并且无法在插入查询中使用ON DUPLICATE KEY UPDATE,所以我试图简化为带有ON DUPLICATE KEY UPDATE的插入查询,但我也遇到了问题 – shecky

相关问题