Mysql在一个查询中替换两个值?

时间:2013-09-20 08:39:20

标签: php mysql sql mysqli

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']);
  }
}

重要!检查存在两条记录,锁定行进行更新

3 个答案:

答案 0 :(得分:2)

MySQL doesn't support update with the same table in the FROM statement。因此,内部子查询中存在(select * from TBL) as t2

第一个EXISTS中的CASE WHEN条件是在第二个记录不存在时阻止更新(“如果存在第一个和第二个记录改变了订单值”)

这是SQLfiddle example

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

上的结果