我有一个应用程序,可以在其中找到一组记录的数据库列的sum(),然后在单独的查询中使用该总和,类似于以下内容(组成表,但思想相同):
SELECT Sum(cost) INTO v_cost_total FROM materials WHERE material_id >=0 AND material_id <= 10; [a little bit of interim work] SELECT material_id, cost/v_cost_total INTO v_material_id_collection, v_pct_collection FROM materials WHERE material_id >=0 AND material_id <= 10 FOR UPDATE;
但是,从理论上讲,可以在两个查询之间更新物料表上的“费用”列,在这种情况下,计算出的百分比将不可用。
理想情况下,我只会在第一个查询上使用FOR UPDATE子句,但是当我尝试执行此操作时,出现错误:
ORA-01786: FOR UPDATE of this query expression is not allowed
现在,解决方法不是问题- 只需执行一个额外的查询来锁定行,然后再找到Sum(),但该查询除了锁定表外没有其他用途。尽管此特定示例并不费时,但额外的查询可能会在某些情况下导致性能下降,而且它也不那么干净,因此我想避免这样做。
有谁知道为什么不允许这样做的特定原因?在我的脑海中,FOR UPDATE子句应该只锁定与WHERE子句匹配的行-我不明白为什么对这些行进行处理很重要。
编辑:看起来SELECT … FOR UPDATE可以与解析函数一起使用,如下面的David Aldridge所建议。这是我用来证明可以正常工作的测试脚本。
SET serveroutput ON; CREATE TABLE materials ( material_id NUMBER(10,0), cost NUMBER(10,2) ); ALTER TABLE materials ADD PRIMARY KEY (material_id); INSERT INTO materials VALUES (1,10); INSERT INTO materials VALUES (2,30); INSERT INTO materials VALUES (3,90); <<LOCAL>> DECLARE l_material_id materials.material_id%TYPE; l_cost materials.cost%TYPE; l_total_cost materials.cost%TYPE; CURSOR test IS SELECT material_id, cost, Sum(cost) OVER () total_cost FROM materials WHERE material_id BETWEEN 1 AND 3 FOR UPDATE OF cost; BEGIN OPEN test; FETCH test INTO l_material_id, l_cost, l_total_cost; Dbms_Output.put_line(l_material_id||' '||l_cost||' '||l_total_cost); FETCH test INTO l_material_id, l_cost, l_total_cost; Dbms_Output.put_line(l_material_id||' '||l_cost||' '||l_total_cost); FETCH test INTO l_material_id, l_cost, l_total_cost; Dbms_Output.put_line(l_material_id||' '||l_cost||' '||l_total_cost); END LOCAL; /
给出输出:
1 10 130 2 30 130 3 90 130
该语法select . . . for update将表中的记录锁定以准备进行更新。进行聚合时,结果集不再引用原始行。
select . . . for update
换句话说,数据库中没有要更新的记录。只是一个临时结果集。