1

私のサイトへの訪問者のショッピング バスケット内のアイテムのリストを保持するテーブル、sessionBasket があります。次のようになります。

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

私のバスケット スクリプトへの追加は、まず、useressid に関連付けられたこのテーブルに現在の product_id を持つアイテムの存在をチェックし、見つかった場合は数量を更新します。そうでない場合は、別のクエリで関連情報を含む新しい行が挿入されます。

その後、ON DUPLICATE KEY UPDATE という条件があることを発見しましたが、これを正しく機能させるために何を変更する必要があるのか​​ わかりません。ここでは、product_id と useressid の 2 つのキーが必要です。これらの両方が挿入しようとしているものと一致する行がある場合、更新条件が作成されます。私はそれを行うためのより良い方法があると確信しています。さらに、何らかの形でスプーフィングされた場合に備えて、product_id が有効であることを確認します。そのため、全体として、確認のためだけに 2 つのクエリを作成し、次に更新/挿入を行うために別のクエリを作成します。

個別のクエリは次のとおりです。

//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 インジェクションについては返信しないでください。

これらを縮小するための助けは素晴らしいでしょう。テーブルが十分に正規化されていない可能性があります。連結された useressid と product_id を含む新しい一意のフィールドを作成して、一意のインデックスを 2 つのフィールドではなく 1 つに折りたたむことができると考えていましたが、理想的ではありません。

4

1 に答える 1

4

まず、 の一意のインデックスが必要です(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);
于 2009-10-05T11:01:02.317 に答える