レコードセットのデータベース列のsum()を見つけて、後でそのような合計を別のクエリで使用するアプリケーションがあります。これは次のようになります(テーブルは作成されましたが、アイデアは同じです)。集計関数でSELECT ... FOR UPDATEを使用できないのはなぜですか?
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;
しかし理論的に誰かが2つのクエリ間でマテリアルテーブルのコスト列を更新することができます。その場合、計算されたパーセントはオフになります。
理想的には、私は最初のクエリに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'で解析関数(sumまたはratio_to_report)を使用することはできますか?私は現時点でこれをテストするためのデータベースを用意していませんので、わかりません... –