'ON DUPLICATE KEY UPDATE',SET选项需要正确的语法

时间:2011-10-05 19:26:54

标签: php mysql duplicates

我有form.php,其中创建或编辑了一条记录。此页面由aa'New Record'链接调用,在这种情况下没有ID设置,或者通过'EDIT'链接调用,在这种情况下设置$ _GET ['ID'](并用于检索记录)。 / p>

计划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'列,顺便说一句,是主键,唯一索引,自动增量。那么$ query在INSERTing或UPDATEing之前如何检查ID?[在研究和实验的日夜之后进入拉扯陈词滥调]

提前致谢,s

P.S。 re:注射:

我一直把这个块包括在我的脑袋里。请告诉我这是否包括注射:

<?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);
    }
?>

2 个答案:

答案 0 :(得分:6)

修复SQL注入漏洞
您不得将$_POST vars (或任何超级全局$_*直接插入查询中。
这是一个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 :(得分:1)

首先,我必须说ON DUPLICATE KEY UPDATE不是替换UPDATE,在这种情况下我会使用INSERT来获取新数据,并在修改现有数据时使用UPDATE。

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

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