правильный синтаксис требуется при 'ON DUPLICATE KEY UPDATE', опция SET - PullRequest
1 голос
/ 05 октября 2011

У меня есть form.php, в котором запись либо создается, либо редактируется. Эта страница вызывается либо ссылкой «Новая запись», в этом случае идентификатор не установлен, либо ссылкой «РЕДАКТИРОВАТЬ», в этом случае устанавливается $ _GET ['ID'] (и используется для извлечения записи).

План А был: Отправка form.php в process.php; в process.php, если есть идентификатор, запрос представляет собой ОБНОВЛЕНИЕ, в противном случае это ВСТАВКА. В какой-то момент, если / иначе работал как положено, но обновлял созданные дупы, я начал играть с «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 ВСТАВЛЯЕТ, дублирует ли идентификатор или нет. Мой столбец 'ID', кстати, является первичным ключом, уникальным индексом, автоинкрементом. Так как же $ query проверяет идентификатор перед вставкой или обновлением? [Введите выдвигающееся клише после нескольких дней исследований и экспериментов]

Заранее спасибо, с

p.s. Re: впрыск:

Я включил этот кусок в свой 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);
    }
?>

Ответы [ 2 ]

6 голосов
/ 06 октября 2011

Исправить это отверстие для 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 голос
/ 06 октября 2011

Сначала я должен сказать, что ON DUPLICATE KEY UPDATE не предназначен для замены UPDATE, в этом случае я бы использовал INSERT для новых данных и UPDATE при изменении существующих данных.

Чтобы сделать ON DUPLICATEТриггер KEY UPDATE в вашем скрипте также должен добавить идентификатор к INSERT, так как это уникальный столбец, к которому вы обращаетесь.

Если затем он находит идентификатор, он активирует часть запроса ON DUPLICATE.

...