2009-10-05 190 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