2009-10-05 213 views
1

我有一个表sessionBasket,它包含我网站访问者的购物篮中的项目列表。它看起来像:重复密钥更新实现/设计

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

我添加到购物篮脚本首先检查是否与与usersessid有关此表来对当前的product_id项目的存在,如果找到一个,它更新数量。如果不是,则单独的查询会插入一个包含相关信息的新行。

我自从发现有一个条件的重复密钥更新,但我不知道我需要改变,以使其正常工作。我需要两个密钥--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连接,可以将唯一索引合并为一个而不是两个字段,但这并不理想。

回答

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); 
+0

很酷,我会试试。将这些领域独特化,不仅可以让一个人拥有一个特定的物品,而且不会有其他物品?这个篮子一次不是一个用户,它可能是几十个。我希望不止一个人能够拥有product_id 1,例如... – user97410 2009-10-05 13:52:42

+1

您将在两列上都有唯一的索引/主键,而不仅仅是其中的一个(http://dev.mysql.com/doc /refman/5.0/en/multiple-column-indexes.html)。它将确保每个'usersessid,product_id'组合只有一行。 – 2009-10-05 14:08:43

+0

太好了 - 我不确定那会怎样。非常感谢:) – user97410 2009-10-05 14:13:40