2010-04-04 59 views
1

我试图创建一个大意如下的更新语句:MySQL:如何做一个有条件的更新?

TABLE car: id | owner_id | type | status 

所有者可以拥有多辆。

UPDATE car c 
    SET c.type = 1 
    WHERE c.owner_id IN ($ids) 
    AND c.status = [1 IF THIS OWNER HAS A CAR WITH 1, ELSE A CAR WITH 0] // ... ??? 

$ ids相当小(小于50的值)。

这似乎很简单,但我似乎无法得到我的头,因为我不能使用SELECT子查询与UPDATE到同一个表。

有人吗?

感谢

+0

我不确定究竟是什么“如果这个车主有一辆车......”意味着什么。可能会显示一些示例数据,以及如何通过更新来更改它。 – xenoterracide 2010-04-04 22:13:16

+0

@ xenoterracide:基本上,车主拥有多辆车,其中一些状态= 1,一些状态= 0。所以我打算在状态= 1的行上进行更新,如果拥有者拥有的话,否则在status = 0行上进行更新。 – Tom 2010-04-04 22:16:44

回答

2

你说你已经尝试过失败,但不幸的是,你还没有公布它的查询,所以我要去猜测,那就是:

UPDATE car c 
SET c.type = 1 
WHERE c.owner_id IN ($ids) 
    AND c.status = (SELECT MAX(c2.status) FROM car c2 WHERE c.owner_id = c2.owner_id) 

发布您的实际查询会是有帮助的,但现在我只是假设这是你的尝试。如果你有一些稍微不同的东西,那没关系......原理是一样的。它会像您正确指出的那样失败,因为您无法在一个查询中更新并从同一个表中进行选择。要解决这种错误的方法之一是包裹在选择另一种选择:

UPDATE car c 
SET c.type = 1 
WHERE c.owner_id IN ($ids) 
    AND c.status = (SELECT * FROM 
        (SELECT MAX(c2.status) FROM car c2 WHERE c.owner_id = c2.owner_id) 
        AS T1) 

令人惊讶,但似乎它应该等同于第一个查询这会甚至工作。请注意,原始查询不起作用的原因是因为它没有正确锁定表。这种解决方法使MySQL无论如何都允许查询,但您应该意识到在多用户环境中使用它可能不安全。

+0

@Mark:是的,上面的查询就是我正在尝试的。你的第二个例子可以解决这个问题......你能否解释为什么它对多用户环境不安全?谢谢。 – Tom 2010-04-04 22:36:16

+0

@Tom:在此查询中,表应该在更新和选择期间锁定。据我了解,这种锁定目前没有在MySQL中实现。如果表在选择和更新之间更改,则结果可能不是您所期望的。虽然我从来没有看到过这样做的任何问题,但我不能100%确定它在你的情况下肯定是不安全的,但如果想要安全起见,最好先写一个存储过程,产生一个临时表,然后在一个单独的语句中执行更新,而不是这个技巧。 – 2010-04-04 22:43:30

+0

了解。感谢您的洞察力。 – Tom 2010-04-04 22:45:20