Php 使用';在重复密钥更新时';,设置选项

Php 使用';在重复密钥更新时';,设置选项,php,mysql,duplicates,Php,Mysql,Duplicates,我在form.php中创建或编辑记录。此页面由“新记录”链接调用,在这种情况下没有设置ID,或者由“编辑”链接调用,在这种情况下设置了$\u GET['ID'],并用于检索记录 A计划是: 将form.php提交到process.php;在process.php中,如果有ID,则查询是更新,否则是插入。在某一点上,if/else按预期工作,但刷新创建了重复,因此我开始玩“复制密钥更新”,但没有成功。我小小的大脑最终想到了B计划:process.php不应该只有一个插入查询,并添加了一个重复的密钥

我在form.php中创建或编辑记录。此页面由“新记录”链接调用,在这种情况下没有设置ID,或者由“编辑”链接调用,在这种情况下设置了$\u GET['ID'],并用于检索记录

A计划是: 将form.php提交到process.php;在process.php中,如果有ID,则查询是更新,否则是插入。在某一点上,if/else按预期工作,但刷新创建了重复,因此我开始玩“复制密钥更新”,但没有成功。我小小的大脑最终想到了B计划:process.php不应该只有一个插入查询,并添加了一个重复的密钥更新吗?这个也还没起作用

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
?>

首先,我必须指出,在重复密钥更新时,不允许替换更新,在这种情况下,我将对新数据使用INSERT,并在修改现有数据时进行更新

若要在脚本中执行ON DUPLICATE KEY UPDATE触发器,还必须将ID添加到INSERT,因为这是您要引用的唯一列


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

首先,我必须说ON replicate KEY UPDATE不是用来替换更新的,在这种情况下,我将使用INSERT替换新数据,并在修改现有数据时进行更新

若要在脚本中执行ON DUPLICATE KEY UPDATE触发器,还必须将ID添加到INSERT,因为这是您要引用的唯一列


如果找到ID,它将触发查询的重复部分。

修复SQL注入漏洞。
您不能将
$\u POST
变量(或任何超全局
$\u*
)直接插入查询中。
这是一个SQL注入漏洞

改为这样做:

$id = mysql_real_escape_string($_POST['ID']);
$invnumber = mysql_real_escape_string($_POST['invoice_number']);
....
etc 
插入的正确语法。。重复密钥更新时
为:

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', .....
最后一行也可以更改为(因此,您的代码不会两次传递参数数据):

不要在更新部分使用主键和唯一键
请注意,
insert
部分中的字段与
update
部分中的字段完全相同是没有意义的。

如果使用此语句,更新部分必须从
SET
子句中排除所有主键和唯一键

修复SQL注入漏洞
您不能将
$\u POST
变量(或任何超全局
$\u*
)直接插入查询中。
这是一个SQL注入漏洞

改为这样做:

$id = mysql_real_escape_string($_POST['ID']);
$invnumber = mysql_real_escape_string($_POST['invoice_number']);
....
etc 
插入的正确语法。。重复密钥更新时为:

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', .....
最后一行也可以更改为(因此,您的代码不会两次传递参数数据):

不要在更新部分使用主键和唯一键
请注意,
insert
部分中的字段与
update
部分中的字段完全相同是没有意义的。

如果使用此语句,更新部分必须从
SET
子句中排除所有主键和唯一键

我会投票给你,但是你忘了SQL注入,所以我不能:-(呵呵,我还在学习如何“教”。这可能就是为什么我没有在这里提到注入问题:)从每一篇文章中我学到了一些新的东西,比如现在。解决您发现的所有问题,即使它们不是原始问题的一部分:PThx Helbom。正如我所指出的,我的原始设置与您描述的一样:插入新数据,更新编辑的数据。。。但后来我不得不解决重复问题,无法在插入查询中进行重复密钥更新,因此我尝试简化为使用重复密钥更新的插入查询,但我遇到了问题。我会投票给你,但你忘记了SQL注入,所以我无法:-(呵呵,哦,我还在学习如何“教学”.这可能就是为什么我没有在这里提到注射问题:)从每一篇文章中我都学到了一些新的东西,比如现在。解决您发现的所有问题,即使它们不是原始问题的一部分:PThx Helbom。正如我所指出的,我的原始设置与您描述的一样:插入新数据,更新编辑的数据。。。但后来我不得不解决重复问题,无法在insert查询中使用重复密钥更新,因此我尝试简化为使用重复密钥更新的insert查询,但我遇到了问题,正确的语法也可能是:
ON DUPLICATE KEY UPDATE invNumber=VALUES(invNumber),invDate=VALUES(invDate),…
我还以为这是重复密钥更新的
。重复键**上的
设置**
语法有效吗?谢谢Johan和ypercube。请注意我编辑的问题;如果您能确认我在head.php中包含的代码足以防止注入,我将不胜感激。Johan,ypercube,如果您不介意的话,请回答几个后续问题。首先,在使用SET选项而不是值时,是否不能在重复密钥更新时使用?我意识到后者更为常见,但我发现SET的语法更易于阅读,我想理解为什么它似乎不那么流行。@shecky,手册没有列出您喜欢的
SET
变体,所以我对此表示怀疑,但不是100%确定。这是一个问题。你的第二个问题是什么?正确的语法也可以是:
关于重复密钥更新invNumber=VALUES(invNumber),invDate=VALUES(invDate)。重复键**上的
设置**
语法有效吗?谢谢Johan和ypercube。请注意我编辑的问题;如果您能确认我在head.php中包含的代码足以防止注入,我将不胜感激。Johan,ypercube,如果您不介意的话,请回答几个后续问题。首先,在使用SET选项而不是值时,是否不能在重复密钥更新时使用?我意识到后者