我正在尝试执行代码重写。其中之一就是这个怪物。我有一组普通的 DML,突然间我在一个脚本中有这个 PL/SQL 块(请参阅当前的解决方案),这在 SQL DML 中看起来很奇怪。
最初我们决定使用 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}
问题:如何在一组行之后或有条件地增加一个 oracle 序列?
数据设置:
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 为这四行更新,以 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;
/
真的可以将其重构为普通 SQL 而不是 PL/SQL 块吗?如果您需要任何澄清,请告诉我。
任何想尝试的人都可以在这里看到小提琴