2013-03-01 4 views
0

У меня возникли проблемы с эффективным решением этой проблемы. Возможно, я делаю это более сложным, чем нужно. У меня есть таблица вроде этого:mysql переупорядочивает строки с уникальным ограничением

thing_id | user_id | order 
    1   1  0 
    2   1  1 
    3   1  2 

Пользователя имеет право бездельничать с их вещами, и это может случиться так, что они меняют вещи от 1 до 3 вещей, и вещь 3 к вещам 1. В моем случае, это не так пользователь явно меняет порядок. Скорее, они изменяют свой банк вещей, и они могут изменить вещь в слоте 1, чтобы быть в слоте 3, и наоборот. Таким образом, если пользователь выполняет эту операцию, таблица должна выглядеть следующим образом:

thing_id | user_id | order 
    3   1  0 
    2   1  1 
    1   1  2 

Что усложняет это в том, что (thing_id, user_id) имеет единственное ограничение, так что делает последовательные обновления не совсем работа. Если я попытаюсь установить UPDATE tbl SET thing_id=3 WHERE thing_id=1, будет нарушено единственное ограничение.

Колонка заказа предназначена только для показа, чтобы составить список в алфавитном порядке. Поэтому я полагаю, что я мог бы использовать PHP для проверки порядка и определения таких вещей, но это вводит код, который действительно не имеет ничего общего с важным материалом. Я хотел бы найти решение, которое является чисто/главным образом SQL.

Кроме того, в тех же строках, если бы я должен был вставить новую строку в таблицу, я бы хотел, чтобы значение порядка было 3. Есть ли эффективный способ сделать это в SQL, без предварительного SELECT MAX(order) WHERE user_id=1?

+0

Что касается последнего вопроса, вы можете использовать 'SELECT MAX (ORDER)' как часть INSERT в качестве подзапроса, по крайней мере, не нужно делать два вызова и, возможно, добавлять условие гонки, если не используете транзакции. – ficuscr

+0

Хорошо круто. Я использую фреймворк codeigniter, поэтому мне, возможно, придется бороться с этим немного, поэтому он не считает, что это SQL-инъекция ха-ха. Таким образом, запрос будет просто «INSERT INTO tbl VALUES (4, 1, (SELECT MAX (order) FROM tbl WHERE user_id = 1)», правильно? –

+0

Yup. Фактически, используя [транзакции] (http: //dev.mysql .com/doc/refman/5.0/en/commit.html) может решить вашу основную проблему ... прочитайте это: http://stackoverflow.com/questions/5014700/in-mysql-can-i-defer-referential- целостность-проверки-до-фиксации ... ну на самом деле не транзакции, но откладывание ссылочной целостности. – ficuscr

ответ

0

Мой комментарий, кажется, получил некоторую тягу, поэтому я отправляю его как ответ ... Чтобы избежать вашей проблемы, добавьте новый столбец без ограничений и просто используйте это для желаемых пользователем обновлений.

0

Почему вы не обновляете заказ вместо объекта?

UPDATE tbl 
    SET order = 2 
    WHERE thing_id=1; 

Каждая строка представляет собой пару «вещь-пользователь». Данные - это заказ, который вы хотите использовать. Вы не хотите изменять объект («предмет-пользователь»). Вы хотите изменить данные.

Кстати, вам нужно будет выполнить дополнительную работу, чтобы сохранить уникальные значения в заказах.

Если вы включили это и установили уникальное ограничение на user_id, order, тогда было бы целесообразно обновить thing_id.

Смежные вопросы