2013-03-01 58 views
0

我有一些麻烦提出了一个有效的解决方案来解决这个问题。也许我会让它变得比需要更复杂。我有这样一个表:mysql重新排列具有唯一约束的行

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

用户可以与他们周围事物的混乱,他们改变的东西1〜3的事情可能发生,事情3事情。在我的情况下,是不是用户明确地改变了订单。相反,他们正在修改他们的东西库,他们可能会改变第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 2013-03-01 17:18:20

+0

好酷。我正在使用codeigniter框架,所以我可能不得不与这一点作斗争,所以它不认为它是SQL注入哈哈。因此,查询将简单地为'INSERT INTO tbl VALUES(4,1,(SELECT MAX(order)FROM tbl WHERE user_id = 1)',对吧? – 2013-03-01 17:20:43

+0

是的,事实上使用[transactions](http://dev.mysql .com/doc/refman/5.0/en/commit.html)可能会解决您的主要问题...阅读此:http://stackoverflow.com/questions/5014700/in-mysql-can-i-defer-referential-完整性检查直到提交...实际上不是交易,但推迟参照完整性 – ficuscr 2013-03-01 17:20:56

回答

0

我的评论似乎已经获得了一些吸引力,所以我将其作为答案张贴...为了避免您的问题,请添加一个没有约束的新列,并将其用于用户所需的更新。

0

为什么不更新订单而不是thingid?

UPDATE tbl 
    SET order = 2 
    WHERE thing_id=1; 

每一行代表一个“事物 - 用户”对。 数据是您要使用的顺序。你不想改变实体(“事物 - 用户”)。你想改变数据。

顺便说一句,您将不得不做一些额外的工作,以保持订单中的唯一值。

如果你切换这个,并把唯一的约束放在user_id, order上,那么更新thing_id是有意义的。