ПО ДУБЛИКАТУ КЛЮЧЕВОГО ОБНОВЛЕНИЯ реализация / дизайн - PullRequest
1 голос
/ 05 октября 2009

У меня есть таблица, sessionBasket, в которой содержится список товаров в корзинах посетителей моего сайта. Похоже:

id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
usersessid VARCHAR
date_added DATETIME
product_id INT
qty INT

Мой сценарий добавления в корзину сначала проверяет наличие элемента с текущим идентификатором product_id в этой таблице, связанного с usersessid, и, если он его находит, обновляет количество. Если нет, отдельный запрос вставляет новую строку с соответствующей информацией.

С тех пор я обнаружил, что есть условие ОБНОВЛЕНИЕ КЛЮЧЕВОГО КЛЮЧА, но я не уверен, что мне нужно изменить, чтобы это работало правильно. Здесь мне понадобятся два ключа - product_id и usersessid, и, если есть строка, в которой оба из них соответствуют тем, которые я пытаюсь вставить, выполняется условие обновления. Я уверен, что есть лучший способ сделать это, чем я уже делаю. Кроме того, я проверяю, что product_id действителен в том случае, если он каким-то образом подделан, поэтому в целом я делаю два запроса только для проверки содержимого, а затем еще один для обновления / вставки.

Вот отдельные запросы:

//do select query to verify item id
$check_sql = "SELECT * FROM aromaProducts1 WHERE id='".intval($_GET["productid"])."'";
$check_res = mysqli_query($mysqli, $check_sql) or  error_log(mysqli_error($mysqli)."\r\n");

  //do select query to check for item id already in basket
  $duplicate_sql = "SELECT qty FROM sessionBasket WHERE product_id='".intval($_GET["productid"])."' AND usersessid='".session_id()."'";
  $duplicate_res = mysqli_query($mysqli, $duplicate_sql) or  error_log(mysqli_error($mysqli)."\r\n");

    //item in basket - add another
    $add_sql = "UPDATE sessionBasket SET qty=qty+".intval($_GET["qty"])."  WHERE usersessid='".session_id()."'AND product_id='".intval($_GET["productid"])."'";
    $add_res = mysqli_query($mysqli, $add_sql) or  error_log(mysqli_error($mysqli)."\r\n");

  //insert query
  $insert_sql = "INSERT INTO ".$table." (userid, usersessid, date_added, product_id, qty, notes) VALUES (
  '".$userid."',
  '".session_id()."',
  now(),
  '".htmlspecialchars($productid)."',
  '".intval($_GET["qty"])."',
  '".htmlspecialchars($notes)."')";
  $insert_res = mysqli_query($mysqli, $insert_sql) or  error_log(mysqli_error($mysqli)."\r\n");

Пожалуйста, не отвечайте на вопросы об SQL-инъекциях - моя дезинфекция гораздо тщательнее, чем позволяют эти фрагменты!

Любая помощь в их сокращении была бы фантастической. Возможно, мои таблицы не достаточно нормализованы. Я думал, что можно было бы создать новое уникальное поле, содержащее сцепленные usersessid и product_id, которые свернули бы уникальные индексы в одно, а не в два поля, но это не идеально.

1 Ответ

4 голосов
/ 05 октября 2009

Сначала вам нужен уникальный индекс для (usersessid, product_id). Я не уверен, что вы на самом деле используете автоматически сгенерированный столбец id, но если нет, вам следует изменить первичный ключ на (usersessid, product_id). Затем вместо выполнения отдельного запроса UPDATE выполните только один запрос INSERT:

INSERT INTO sessionBasket (userid, usersessid, date_added, product_id, qty, notes)
VALUES (?, ?, now(), ?, ?, ?)
ON DUPLICATE KEY UPDATE qty = qty + ?

Просто чтобы прояснить, как должен выглядеть уникальный индекс:

CREATE UNIQUE INDEX sessionBasket_uniq ON sessionBasket (usersessid, product_id);

Или первичный ключ:

ALTER TABLE sessionBasket ADD CONSTRAINT sessionBasket_pkey PRIMARY KEY (usersessid, product_id);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...