2017-02-10 6 views
2

学習目的でダミーデータベースを作成しましたが、重複したレコードをテーブルの1つに意図的に作成しました。いずれの場合も、重複したレコードの1つにLatest = 'Y'、もう1つのレコードに 'N'というフラグを付けたいとし、すべてのレコードに対してLatestフラグを 'Y'にします。計算値を使用してPL SQLで列を更新するには

それはと言う私は、私のすべてのレコードを通過するPLSQLを使用しようとしましたが、私は(そのA重複して記録することを言うだろう)以前に計算した値を使用しようとすると:

ORA-06550:行20、コラム17: PLS-00201:識別子 'COUNTER' ここ

を宣言する必要がありますが、私が使用しようとする文は次のとおりです。

DECLARE CURSOR cur IS SELECT order_id, order_date, person_id, amount, successfull_order, country_id, latest, ROWCOUNT AS COUNTER FROM (SELECT order_id, order_date, person_id, amount, successfull_order, country_id, latest, ROW_NUMBER() OVER (PARTITION BY order_id, order_date, person_id, amount, successfull_order, country_id ORDER BY order_id, order_date, person_id, amount, successfull_order, country_id) ROWCOUNT FROM orders) orders FOR UPDATE OF orders.latest; rec cur%ROWTYPE; BEGIN FOR rec IN cur LOOP IF MOD (COUNTER, 2) = 0 THEN UPDATE orders SET latest = 'N' WHERE CURRENT OF cur; ELSE UPDATE orders SET latest = 'Y' WHERE CURRENT OF cur; END IF; END LOOP; END;

私はPLSQLに新しいですので、私は変更してみました私がここに見つけた文: http://www.adp-gmbh.ch/ora/plsql/cursors/for_update.html

私は私の声明で何を変えるべきですか、あるいは別のアプローチをとるべきですか?

ご回答ありがとうございます。 Botond

+0

あなたがで、 'MODのようなカーソルの参照から、私は回避策を使用(rec.COUNTER、2)' –

答えて

0

ROWNUMCOUNTERとしてください。フェッチしている間に、あなたはMOD (rec.COUNTER, 2)

+0

お返事ありがとうございますが、そのように私は新しい問題を抱えています。私はパーティションを使っているので、更新したくない。私はこの代わりに回避策を使用しました。 –

0

変数COUNTERを宣言して、それをループ内で維持(つまりインクリメント)する必要があります。 私はあなたの例がPL/SQLを学ぶためのものだと思っています。ただし、カーソルループを使用するのではなく、単一のSQL文で処理するほうがはるかに性能が良いことに注意してください。

+0

おかげでそれにアクセスする必要がありますいくつかのヘルパー列を持つ全く新しいテーブルを作成します。このようにして、PLSQLを使用する必要はありませんでした。 –

0

のようにカーソルの参照からアクセスする必要があります
あなたの問題はCOUNTERは、カーソル・レコードrecなくPL/SQL変数の属性であるということです。ただし、PL/SQLまたはカーソルを使用する必要はありません、それは単一MERGE文で行うことができます

IF MOD (rec.COUNTER, 2) = 0 

::だから:

IF MOD (COUNTER, 2) = 0 

であるべき

Oracleのセットアップ

CREATE TABLE orders (order_id, order_date, latest) AS 
SELECT 1, DATE '2017-01-01', CAST(NULL AS CHAR(1)) FROM DUAL UNION ALL 
SELECT 1, DATE '2017-01-02', NULL FROM DUAL UNION ALL 
SELECT 1, DATE '2017-01-03', NULL FROM DUAL UNION ALL 
SELECT 2, DATE '2017-01-04', NULL FROM DUAL UNION ALL 
SELECT 2, DATE '2017-01-01', NULL FROM DUAL UNION ALL 
SELECT 3, DATE '2017-01-06', NULL FROM DUAL; 

UPDATE文

MERGE INTO orders dst 
USING (SELECT ROW_NUMBER() OVER (PARTITION BY order_id 
            ORDER BY order_date DESC) AS rn 
     FROM orders 
    ) src 
ON (src.ROWID = dst.ROWID) 
WHEN MATCHED THEN 
    UPDATE SET latest = CASE src.rn WHEN 1 THEN 'Y' ELSE 'N' END; 

出力

SELECT * FROM orders; 

ORDER_ID ORDER_DATE LATEST 
-------- ---------- ------ 
     1 2017-01-01 N 
     1 2017-01-02 N 
     1 2017-01-03 Y 
     2 2017-01-04 Y 
     2 2017-01-01 N 
     3 2017-01-06 Y 
関連する問題