BEFORE
id | cat_id | order
33 | 1 | 1
34 | 1 | 2
AFTER
id | cat_id | order
33 | 1 | 2
34 | 1 | 1
现在使用4个查询
$ db是使用占位符和注入防御来包装$ mysqli
按ID
获取第一条记录$curr = $db->q('SELECT id,order,cat_id FROM `tbl` WHERE id`=? FOR UPDATE',
33)->fetch_assoc();
如果存在第一条记录按订单字段查找下一条记录
if($curr){
$next = $db->q('SELECT id,order FROM `tbl` WHERE `cat_id`=? AND
`order`>? ORDER BY `order` LIMIT 1 FOR UPDATE',
$curr['cat_id'],$curr['order']));
如果存在第一个和第二个重新修改订单值
if($prev['id']){
$db->q("UPDATE `tbl` SET `order`=? WHERE `id`=?",$next['order'],$curr['id']);
$db->q("UPDATE `tbl` SET `order`=? WHERE `id`=?",$curr['order'],$next['id']);
}
}
重要!检查存在两条记录,锁定行进行更新
答案 0 :(得分:2)
MySQL doesn't support update with the same table in the FROM statement。因此,内部子查询中存在(select * from TBL) as t2
。
第一个EXISTS
中的CASE WHEN
条件是在第二个记录不存在时阻止更新(“如果存在第一个和第二个记录改变了订单值”)
UPDATE tbl as t1
SET `order`=
CASE WHEN id = 33
and
EXISTS (SELECT ID from (select * from TBL) t2 where
cat_id=t1.Cat_Id
and `order`>t1.`order`
ORDER BY `order`
LIMIT 1)
THEN
(SELECT `order` from (select * from TBL) t2 where
cat_id=t1.Cat_Id
and `order`>t1.`order`
ORDER BY `order`
LIMIT 1)
WHEN id <>33 THEN
(SELECT `order` from (select * from TBL) t2 where
cat_id=t1.Cat_Id
and `order`<t1.`order`
ORDER BY `order` DESC
LIMIT 1 )
ELSE `order`
END
where id =33
or
(SELECT ID from (select * from TBL) t2 where
cat_id=t1.Cat_Id
and `order`<t1.`order`
ORDER BY `order` DESC
LIMIT 1) =33
答案 1 :(得分:1)
只有一个查询:
UPDATE
`tbl`
SET
`order`=CASE
WHEN `order`=2 THEN 1
WHEN `order`=1 THEN 2
END;
WHERE
`order` IN (1,2)
或者,对于id的条件:
UPDATE
`tbl`
SET
`order`=CASE
WHEN `order`=2 THEN 1
WHEN `order`=1 THEN 2
END;
WHERE
id = $id
答案 2 :(得分:1)
要按行id
交换2个字段,请尝试:
UPDATE `tbl` AS tbl1
JOIN `tbl` AS tbl2 ON ( tbl1.id = 33 AND tbl2.id = 34 )
SET
tbl1.order = tbl2.order, tbl2.order = tbl1.order
您也可以设置所需的值,而不是在2个文件之间交换。
如果需要,您可以添加如下所示的where子句来交换两行中cat_id为1
的位置:
WHERE
tbl1.cat_id = 1 AND tbl2.cat_id = 1
<强>更新强>
如果您的订单号对于任何cat_id
都是唯一的,您可以尝试这种方式:
UPDATE `tbl` AS tbl1
JOIN `tbl` AS tbl2 ON ( tbl1.order = 1 AND tbl2.order = 2 )
SET
tbl1.order = tbl2.order, tbl2.order = tbl1.order
WHERE
tbl1.cat_id = 1 AND tbl2.cat_id = 1
如果您的订单字段为int
,则可以使用,否则您应该在查询中引用订单值。
查看 SQLFiddle
上的结果