我的团队有一张桌子ace_1
STATUS CHARGE_1 CHARGE_2
N 5 20
Y 7 25
N 9 30
N 11 35
Y 13 40
当每个 CHARGE_1/ACTION=CREATE 和 CHARGE_2/ACTION=UPDATE 的 STATUS=N 时,需要 INSERT INTO table ace_2 两行 当 STATUS=N 且 ACTION=CREATE 且 CHARGES=CHARGE_1 时仅插入一行,如下
ace_2
STATUS ACTION CHARGES
N CREATE 5
N UPDATE 20
Y CREATE 7
N CREATE 9
N UPDATE 30
N CREATE 11
N UPDATE 35
Y CREATE 13
我的以下程序运行良好。 但是还有其他选项可以使用 FORALL LOOP 来微调代码吗? 实时数据在0.1到100万之间。需要解决性能问题。
PROCEDURE test1 (
x_status_code OUT VARCHAR2,
x_error_message OUT VARCHAR2
) IS
CURSOR cur_a IS
SELECT
*
FROM
ace_1
WHERE
1 = 1;
TYPE ace_1_tbl_type IS
TABLE OF cur_a%rowtype INDEX BY PLS_INTEGER;
lvar_1 ace_1_tbl_type;
BEGIN
OPEN cur_a;
LOOP
FETCH cur_a
BULK COLLECT INTO lvar_1 LIMIT 100;
EXIT WHEN lvar_1.count = 0;
FOR idx IN 1..lvar_1.count LOOP
IF lvar_1(idx).status = 'Y' THEN
INSERT INTO ace_2 VALUES (
lvar_1(idx).status,
'CREATE',
lvar_1(idx).charge_1
);
ELSIF lvar_1(idx).status = 'N' THEN
INSERT INTO ace_2 VALUES (
lvar_1(idx).status,
'CREATE',
lvar_1(idx).charge_1
);
INSERT INTO ace_2 VALUES (
lvar_1(idx).status,
'UPDATE',
lvar_1(idx).charge_2
);
END IF;
END IF;
END LOOP;
END LOOP;
CLOSE cur_a;
dbms_output.put_line('END WELL');
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('INTO EXCEPTION' || x_error_message);
x_status_code := sqlcode;
x_error_message := sqlerrm;
dbms_output.put_line('fine 123');
END test1;
您可以使用单个插入语句来完成此操作,例如:
insert into ace_2 (status, action, charges)
with dummy as (select level id
from dual
connect by level <= 2)
select a1.status,
case when d.id = 1 then 'CREATE' else 'UPDATE' end action,
case when d.id = 1 then a1.charge_1 else a1.charge_2 end charges
from ace_1 a1
inner join dummy d on a1.status = 'N' or (a1.status = 'Y' and d.id = 1);
这是通过将
ace_1
表中的行连接到包含 2 行的一组数据(在 dummy
子查询中使用 connect by
技巧生成指定级别数的行)来实现的,这样状态为 Y 的行仅与第一个虚拟行匹配,而状态 N 行与两个虚拟行匹配。
获得该数据后,只需将其插入到 ace_2 表中即可。
但是,您提供的数据没有任何暗示排序的列或链接行集的键,因此您获得的结果不一定看起来像您的预期输出,正如您从 this db<> 中看到的那样小提琴.
假设您的实际数据具有这些列,那么您应该很容易应用上述技术,然后相应地对输出进行排序。