2010-12-15 64 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