1

コードの書き換えを実行しようとしています。その中の一つがこの怪物でした。私は通常の DML のセットを持っていますが、突然、SQL DML の中で奇妙に見えるスクリプト内にこの PL/SQL ブロックを持っています (現在のソリューションを参照してください)。

最初に、次の仮定に基づいて PL/SQL ブロックを使用することにしました。"updating a column with a sequence number without increment within the group of records and incremented for the next group CANNOT BE achieved in a single SQL."

row1 - seq.nextval
row2 - seq.currval
row3 - seq.nextval
row4 - seq.currval
row5 - seq.currval

where group1 {row1, row2} and group 2 {row3, row4, row5}

質問: 行のセットの後、または条件付きでオラクル シーケンスをインクリメントする方法を教えてください。

データ設定:

CREATE TABLE TEMP_GP_SEQ
(
   COL1   NUMBER,
   COL2   NUMBER,
   COL3   NUMBER,
   COL4   NUMBER,
   COL5   NUMBER,
   COL6   NUMBER,
   COL7   VARCHAR2 (10)
);

INSERT INTO TEMP_GP_SEQ VALUES(1,10,100,NULL,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(1,10,101,NULL,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(12,10,100,1,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(1,10,100,2,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(1,10,100,3,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(12,10,100,1,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(2,10,100,NULL,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(2,10,101,NULL,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(2,10,101,1,NULL,NULL,NULL);
INSERT INTO TEMP_GP_SEQ VALUES(2,10,101,1,NULL,NULL,NULL);

COMMIT; 

CREATE SEQUENCE SEQ_TEMP_TEST
   START WITH 1
   INCREMENT BY 1;

私の関係するレコードの選択基準

SELECT
      COL1,
      COL3,
      COL4,
      COUNT ( * )
FROM
      TEMP_GP_SEQ
GROUP BY
      COL1,
      COL3,
      COL4
HAVING
      COUNT ( * ) > 1;

私にくれるだろう

COL1    COL3    COL4    COUNT(*)
2       101     1       2
12      100     1       2

作成したシーケンスを使用して、上記のグループ化範囲に基づいて、TEMP_GP_SEQ テーブルと COLUMN COL7 を更新する必要があります。ただし、シーケンスはレコードごとにインクリメントするのではなく、グループの変更に対してのみインクリメントする必要があります。例えば

SELECT 
      COL1,
      COL2,
      COL3,
      COL4,
      COL7
FROM
      TEMP_GP_SEQ;

望ましい出力

COL1    COL2    COL3   COL4    COL7         
1       10      100    NULL    NULL         
1       10      101    NULL    NULL         
12      10      100    1       M2           
1       10      100    2       NULL         
1       10      100    3       NULL         
12      10      100    1       M2           
2       10      100    NULL    NULL         
2       10      101    NULL    NULL         
2       10      101    1       M1           
2       10      101    1       M1           

COL7 は、これらの 4 つの行に対して更新され、M が接頭辞として付けられ、M の後に続く番号はシーケンスからのものです。ここでは、グループ化基準に変更があり、グループ全体で同じままである場合にのみ、番号が変更されます (シーケンスが増分されます)。

課題は、どの列にも NULL 値が含まれる可能性があることです。そのため、グループ化中に NULLS を考慮する必要があります。したがって、IS NULL が使用されます。(NVLは念のために無視されます)

現在のソリューション:

DECLARE
    VAL INTEGER;
BEGIN
    FOR REC IN ( SELECT
                    COL1,
                    COL3,
                    COL4
              FROM
                    TEMP_GP_SEQ
              GROUP BY
                    COL1,
                    COL3,
                    COL4
              HAVING
                    COUNT ( * ) > 1 )
    LOOP
        SELECT SEQ_TEMP_TEST.NEXTVAL INTO VAL FROM DUAL;

        UPDATE
              TEMP_GP_SEQ
        SET
              COL7   = 'M' || VAL
        WHERE
                 ( COL1 = REC.COL1 OR ( COL1 IS NULL AND REC.COL1 IS NULL ) )
              AND ( COL3 = REC.COL3 OR ( COL3 IS NULL AND REC.COL3 IS NULL ) )
              AND ( COL4 = REC.COL4 OR ( COL4 IS NULL AND REC.COL4 IS NULL ) );
    END LOOP;
END;
/

これをPL/SQLブロックではなく通常のSQLにリファクタリングすることは本当に可能ですか? 説明が必要な場合はお知らせください。

試してみたい人は誰でもここでフィドルを見ることができます

4

1 に答える 1