2010-12-15 33 views
0

unique Le tableau est la suivante:MySQL conflits UPDATE avec clé

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

Ainsi, un utilisateur peut posséder de nombreuses visites (jamais l'esprit ce que les visites sont). Le champ UserId est un char, pas un int, car l'utilisateur n'est peut-être pas connecté, auquel cas l'ID de session est utilisé.

Lorsqu'un utilisateur se connecte, son ID utilisateur change. Donc, la mise à jour simple serait

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

Mais cela pourrait donner une clé d'entrée en double. Lorsque l'ancien utilisateur et le nouvel utilisateur ont la même visite, nous devrions en déposer un avant la mise à jour.

J'ai essayé

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"; 

et

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"; 

Les deux me donnent des erreurs. Est-il possible de le faire dans la requête SQL elle-même, ou dois-je juste faire

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

puis faire moi-même les calculs nécessaires en PHP?

+0

Pourriez-vous s'il vous plaît partager l'erreur que vous obtenez pour la première mise à jour? –

Répondre

0

Je suppose que ce que vous essayez de faire est d'abord supprimer les enregistrements en conflit et ensuite insérer le nouvel enregistrement. Cela pourrait aider ...

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

Maintenant, ça a l'air bien. Je vais essayer cet après-midi. – TRiG

0

Je peux me tromper, mais cela ressemble à un scénario de panier d'achat pour moi. Pourquoi ne pas stocker des visites anonymes et enregistrées dans des tables séparées? C'est-à-dire, après que l'utilisateur se connecte, convertir les visites "Panier d'achat" anonymes en visites "Commandes" réelles dans un autre tableau?

De cette façon, vous ne détruisez aucune donnée. D'ailleurs, comment savez-vous que la personne qui vient de se connecter est la même que la personne qui a ajouté les visites avant de se connecter?

+0

C'est un panier, oui. (Ceci est une table temporaire pour stocker des choses qui n'ont pas encore été payées.) Et c'est certainement une option. (La connexion est sûre, cependant: nous connaissons l'ancien et le nouveau identifiant Nous ne devinons pas quels circuits appartiennent à quelle personne.) – TRiG