MySQL UPDATE конфликтует с уникальным ключом - PullRequest
0 голосов
/ 15 декабря 2010

Таблица выглядит следующим образом:

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, поскольку пользователь не может войти в систему, и в этом случае используется идентификатор сеанса.

Когда пользователь входит в систему, его идентификатор пользователя изменяется.Таким образом, простое обновление будет

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?

Ответы [ 2 ]

0 голосов
/ 16 декабря 2010

Полагаю, вы пытаетесь сначала удалить конфликтующие записи, а затем вставить новую запись.Это может помочь ...

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 голосов
/ 15 декабря 2010

Я могу ошибаться, но для меня это звучит как сценарий корзины покупок.Почему бы не хранить анонимные и авторизованные туры в отдельных таблицах?Т.е. после входа пользователя преобразовать анонимные туры "Корзина покупок" в реальные туры "Заказы" в другой таблице?

Таким образом, вы не уничтожаете никакие данные.Кроме того, откуда вы знаете, что человек, который только что вошел в систему, совпадает с человеком, который добавил туры до того, как они вошли в систему?

...