更新一些未在另一个表中使用的列

时间:2014-06-12 08:38:44

标签: sql oracle

我有两张桌子。让我们拨打一个items。其中的列是一些唯一的id,位置和旧位置。 如果它具有旧位置,则其当前从position_old移动到position。如果它的位置-为旧 它不动。每个职位可以有多个项目。

第二个表(position)用于职位。其中的列是唯一的ID和状态。

我需要更新位置表中状态为100且没有移动到其中的项目的所有行 (position = position_id AND position_old != '-')并且没有项目从中移动(position_old = position_id)。

+---------+----------+--------------+
| item_id | position | position_old |
+---------+----------+--------------+
|       1 | 0001     | -            |
|       2 | 0001     | 0002         |
+---------+----------+--------------+

+-------------+--------+
| position_id | status |
+-------------+--------+
| 0001        |      0 |
| 0002        |    100 |
+-------------+--------+

我得到了一些解决方案,但我认为它不是最好的解决方案:

UPDATE Position
SET    status = 0
WHERE  status = 100
AND    position_id NOT IN (
  SELECT DISTINCT position_old FROM Items WHERE position_old != '-'
  UNION
  SELECT DISTINCT position FROM Items WHERE position_old != '-'
)

那么还有更好的方法吗?仅供参考 它是一个Oracle 11.2.0.4数据库,如果你建议使用连接,那么每个人都应该使用糟糕的旧语法 这是与它合作,不愿意学习更新的标准。

2 个答案:

答案 0 :(得分:0)

我认为更高效的是:

UPDATE Position out_pos
SET    status = 0
WHERE  status = 100
AND  not exists (
SELECT 1  FROM Items sub_pos WHERE 
 sub_pos.position_old != '-' and 
 ( 
  sub_pos.position = out_pos.position_id 
  OR 
  sub_pos.position_old = out_pos.position_id
 )
)

答案 1 :(得分:0)

你的陈述是正确的,但我更愿意用“不存在”来写它以匹配自然语言形式:

UPDATE Position
SET    status = 0
WHERE
  -- which have status 100:
  status = 100
  AND
  -- have no item which is moving to it:
  NOT EXISTS (SELECT * FROM items WHERE position = position_id AND position_old <> '-')
  AND
  -- no item moving from it:
  NOT EXISTS (SELECT * FROM items WHERE position_old = position_id)

至于效率,执行该声明并查看执行计划是无可替代的。根据索引的存在,表格的基数和条件的选择性(以及更多......),Oracle将乐意将“EXISTS”重写为“IN”等等。

items上带有position_old, position列(按此顺序)的索引似乎很有帮助。