2010-12-15 119 views
0

表MySQL的更新衝突如下:具有獨特的鍵

CREATE TABLE `ToursCartsItems` (
    `Id` int(10) unsigned NOT NULL auto_increment, 
    `UserId` char(40) default NULL, 
    `TourId` int(10) unsigned NOT NULL, 
    `CreatedAt` int(10) unsigned default NULL, 
    PRIMARY KEY (`Id`), 
    UNIQUE KEY `UniqueUserProduct` (`UserId`,`TourId`) 
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED 

// simple sample data 
INSERT INTO 
    ToursCartsItems (UserId, TourId) 
VALUES 
    ("old", 1), ("old", 2), ("new", 1), ("new", 3); 

所以一個用戶可以擁有許多旅行團(別提是什麼旅行團)。 UserId字段是char而不是int,因爲用戶可能未登錄,在這種情況下會話ID被使用。

當用戶登錄時,其用戶ID將發生變化。所以簡單的更新將是

UPDATE ToursCartsItems SET UserId="new" WHERE UserId="old" 
-- In reality, the new UserId would be an integer, but never mind that. 

但是,這可能會給一個重複的輸入密鑰。舊用戶和新用戶都具有相同的導覽,我們應該在更新之前刪除一個。

所以我已經試過

UPDATE ToursCartsItems 
    SET UserId="in" 
    WHERE UserId="out" 
    AND (TourId NOT IN (SELECT TourId FROM ToursCartsItems WHERE UserId="in") 
); 
DELETE FROM ToursCartsItems WHERE UserId="old"; 

TRUNCATE ToursCartsItems; 
INSERT INTO ToursCartsItems (UserId, TourId) VALUES ("old", 1), ("old", 2), ("new", 1), ("new", 3); 
DELETE FROM ToursCartsItems WHERE UserId="old" AND TourId IN (SELECT TourId FROM ToursCartsItems WHERE UserId="new"); 
UPDATE ToursCartsItems SET UserId="new" WHERE UserId="old"; 

兩個給我的錯誤。有沒有辦法在SQL查詢本身要做到這一點,還是我只需要做

SELECT * FROM ToursCartsItems WHERE UserId IN ("old", "new") 

,然後做必要的計算自己在PHP?

+0

請問您可以分享您獲得第一次更新的錯誤嗎? – 2010-12-15 19:13:56

回答

0

我想你要做的是首先刪除衝突的記錄,然後插入新的記錄。這可能會有所幫助...

mysql> select * from ToursCartsItems; 
+----+--------+--------+-----------+ 
| Id | UserId | TourId | CreatedAt | 
+----+--------+--------+-----------+ 
| 1 | old |  1 |  NULL | 
| 2 | old |  2 |  NULL | 
| 3 | new |  1 |  NULL | 
| 4 | new |  3 |  NULL | 
+----+--------+--------+-----------+ 
4 rows in set (0.00 sec) 

mysql> delete from b using ToursCartsItems as a inner join ToursCartsItems as b on a.TourId = b.TourId where a.UserId = 'new' and b.UserId = 'old' and a.Id <> b.Id; 

mysql> select * from ToursCartsItems; 
+----+--------+--------+-----------+ 
| Id | UserId | TourId | CreatedAt | 
+----+--------+--------+-----------+ 
| 2 | old |  2 |  NULL | 
| 3 | new |  1 |  NULL | 
| 4 | new |  3 |  NULL | 
+----+--------+--------+-----------+ 
3 rows in set (0.00 sec) 
+0

現在看起來不錯。我今天下午試試。 – TRiG 2010-12-16 13:00:32

0

我可能是錯的,但這聽起來像一個購物車場景對我來說。爲什麼不將匿名和登錄遊覽存儲在單獨的表格中?也就是說,在用戶登錄後,將匿名的「購物車」遊覽轉換爲另一個表中的實際遊覽「訂單」?

這樣你就不會破壞任何數據。此外,您如何知道剛剛登錄的人與登錄前添加的人相同?

+0

這是一個購物車,是的。 (這是一個臨時表,用於存儲尚未支付的東西。)這當然是一種選擇。 (但是登錄是安全的:我們確實知道舊的和新的ID,我們不知道哪個遊覽屬於哪個人。) – TRiG 2010-12-15 21:53:31