У меня возникли проблемы с эффективным решением этой проблемы. Возможно, я делаю это более сложным, чем нужно. У меня есть таблица вроде этого: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
?
Что касается последнего вопроса, вы можете использовать 'SELECT MAX (ORDER)' как часть INSERT в качестве подзапроса, по крайней мере, не нужно делать два вызова и, возможно, добавлять условие гонки, если не используете транзакции. – ficuscr
Хорошо круто. Я использую фреймворк codeigniter, поэтому мне, возможно, придется бороться с этим немного, поэтому он не считает, что это SQL-инъекция ха-ха. Таким образом, запрос будет просто «INSERT INTO tbl VALUES (4, 1, (SELECT MAX (order) FROM tbl WHERE user_id = 1)», правильно? –
Yup. Фактически, используя [транзакции] (http: //dev.mysql .com/doc/refman/5.0/en/commit.html) может решить вашу основную проблему ... прочитайте это: http://stackoverflow.com/questions/5014700/in-mysql-can-i-defer-referential- целостность-проверки-до-фиксации ... ну на самом деле не транзакции, но откладывание ссылочной целостности. – ficuscr