コードの書き換えを実行しようとしています。その中の一つがこの怪物でした。私は通常の 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にリファクタリングすることは本当に可能ですか? 説明が必要な場合はお知らせください。
試してみたい人は誰でもここでフィドルを見ることができます