2017-01-17 10 views
0

Oracle 12データベースがあります。pl/sqlでテーブルをループして値を更新する方法

テーブルをループして前の行に基づいて値を更新する必要があります。下のように、行1から値を取得し、行2から6に更新する必要があります。次に、行7から新しい値を取得して、テーブルの最後まで進みます。

id column1 column2 
1 xxx;yyy;zzz;123456; 
2 aaa 123456 
3 bbb 123456 
4 ccc 123456 
5 ddd 123456 
6 eee 123456 
7 xxx;yyy;zzz;789123; 
8 aaa 789123 

TBH Iドン」:更新テーブルは次のようになります。後はcolumn1のは、CSV形式のテキストですので、私はそこから数-値を抽出する必要があります...

id column1 column2 
1 xxx;yyy;zzz;123456; 
2 aaa 
3 bbb 
4 ccc 
5 ddd 
6 eee 
7 xxx;yyy;zzz;789123; 
8 aaa 

pl/sqlに多くの経験があります。 ループ中にpl/sqlを使用しようとしましたが、動作しませんでした。

誰かが私を正しい方向に蹴ることができたら、それは感謝します。

+0

いくつかのクイッククエリ。行は常に6つのグループに分かれていますか、それとも変わることができ、最初の行は常に同じ長さですか? – MightyRearranger

+0

行は24行からそれ以上に変更できません。最初の行は常に同じ長さで、最初の3文字は同じです。 – snow

答えて

1

あなたは、このためのPL/SQLを必要としない、それが(サブ文字列を抽出するために)MERGEの組み合わせ、LAG(...) IGNORE NULLS ...解析関数とREGEXP_SUBSTRを使用してSQLで完全に行うことができます。

MERGE INTO table_name dst 
USING (
    SELECT id, 
     CASE WHEN val IS NULL 
       THEN LAG(val) IGNORE NULLS OVER (ORDER BY id) 
     END AS val 
    FROM (
    SELECT id, 
      REGEXP_SUBSTR(column1, ';(\d{6});$', 1, 1, NULL, 1) AS val 
    FROM table_name 
) 
) src 
ON (dst.id = src.id) 
WHEN MATCHED THEN 
    UPDATE SET column2 = src.val; 

を更新しました表:

id column1    column2 
-- ------------------- ------- 
1 xxx;yyy;zzz;123456; 
2 aaa     123456 
3 bbb     123456 
4 ccc     123456 
5 ddd     123456 
6 eee     123456 
7 xxx;yyy;zzz;789123; 
8 aaa     789123 
0

このようなものは、必要な操作を行う必要があります。テーブルをループし、 'xxx'で始まるたびに最初のレコードの最後のビットを変数に渡し、そうでなければ列2を更新します。

DECLARE 
    L_UpdateVal VARCHAR2(10) := ''; 
BEGIN 
    FOR REC IN (SELECT Column1, column2, ROWNUM From table) LOOP 
     IF SUBSTR(REC.column1, 1, 3) = 'xxx' THEN 
      L_UpdateVal := SUBSTR(column1, 13, 6); 
     ELSE 
      UPDATE Table SET Column2 = L_UpdateVal 
       WHERE ROWNUM := REC.ROWNUM 
     END IF; 
    END LOOP; 
END; 
0

これにはPL/SQLは必要ありませんが、1つのMERGE文で実行できます。

まず第一に、あなたは後にしている結果を取得する方法を考え出す - そのようにあなたは、「LAST_VALUE()」解析関数を使用してこれを行うことができます。

WITH your_table AS (SELECT 1 id, 'xxx;yyy;zzz;123456;' column1, NULL column2 FROM dual UNION ALL 
        SELECT 2 id, 'aaa' column1, NULL column2 FROM dual UNION ALL 
        SELECT 3 id, 'bbb' column1, NULL column2 FROM dual UNION ALL 
        SELECT 4 id, 'ccc' column1, NULL column2 FROM dual UNION ALL 
        SELECT 5 id, 'ddd' column1, NULL column2 FROM dual UNION ALL 
        SELECT 6 id, 'eee' column1, NULL column2 FROM dual UNION ALL 
        SELECT 7 id, 'xxx;yyy;zzz;789123;' column1, NULL column2 FROM dual UNION ALL 
        SELECT 8 id, 'aaa' column1, NULL column2 FROM dual) 
select id, 
     column1, 
     last_value(CASE WHEN substr(column1, -1) = ';' THEN 
          regexp_substr(column1, ';*([[:digit:]]*)(;$)', 1, 1, NULL, 1) 
        END IGNORE NULLS) OVER (ORDER BY ID) column2 
from your_table; 

     ID COLUMN1    COLUMN2 
---------- ------------------- ------------------- 
     1 xxx;yyy;zzz;123456; 123456 
     2 aaa     123456 
     3 bbb     123456 
     4 ccc     123456 
     5 ddd     123456 
     6 eee     123456 
     7 xxx;yyy;zzz;789123; 789123 
     8 aaa     789123 

そして、あなたがそれを使用することができます以下のようなので、アップデートを行うにはMERGE文:

MERGE INTO your_table tgt 
    USING (select id, 
       column1, 
       CASE WHEN substr(column1, -1) = ';' THEN 'Y' ELSE 'N' END driving_column1, 
       last_value(CASE WHEN substr(column1, -1) = ';' THEN 
            regexp_substr(column1, ';*([[:digit:]]*)(;$)', 1, 1, NULL, 1) 
          END IGNORE NULLS) OVER (ORDER BY ID) column2 -- assuming id drives the correct order to use here 
     from your_table) src 
    ON (tgt.id = src.id) -- assuming id is the primary key of your_table 
WHEN MATCHED THEN 
    UPDATE SET tgt.column2 = src.column2; 

あなたは値が(私は存在セミコロンがあることを、CSV値を仮定してきたしているCOLUMN1行の列2を更新したくない場合それらがcsv値の場合)、ON句をand driving_column1 = 'N'またはdriving_column1をフィルタリングする外側のクエリにソースサブクエリをラップすることができます(残念なことに、同じクエリ内のアナリティック関数をフィルタ処理できません)。または、マージステートメントの更新セクションにwhere句を追加できます。

+0

私は少し微調整してこのコードを使用することができました。最後のマージ部分には 'src'と 'set'コマンドがありませんでしたが、それらを追加した後はすべて正常に動作しました。 – snow

+0

@snowええ、それは謝罪します。私はポストボタンを押すのに過度に興奮しているに違いない。そして、私が書いたものを十分に再確認しなかった。 D'oh! – Boneist

関連する問題