我有下面的存储过程:
create or replace PROCEDURE CALCULATE_RECOVERY_HISTORY(p_month IN VARCHAR2) AS
l_id NUMBER;
BEGIN
ADD_LOG_INFO('CALCULATE_RECOVERY_HISTORY', 'Procedure Started');
l_id := SQ_AP_RECOVERY_HISTORY.NEXTVAL;
INSERT INTO t_ap_recovery_history (ID, RECOVERY_TARGET_MONTH, TARGET_INSTANCE, RECOVERY_PROGRESS, RECOVERY_TARGET, FAILED_TO_RECOVERY, FOCUS_AREA, IDENTIFIER_CLASS, CREATED_ON)
SELECT l_id,
a_recovery_target_month,
a_target_instance,
COUNT(CASE WHEN A_IS_RECOVERED = 'Y' THEN 1 END),
COUNT(CASE WHEN A_IS_RECOVERED IN ('Y', 'N') THEN 1 END),
COUNT(CASE WHEN A_IS_RECOVERED = 'N' THEN 1 END),
f.focus_area,
r.identifier_class,
SYSDATE
from t_ap_recovery_target t, t_ap_recovery_focusarea f, range r
where t.a_focus_area_id = f.id and t.a_range_id = r.id
and t.a_recovery_target_month = p_month
group by a_target_instance, a_recovery_target_month, f.focus_area, r.identifier_class;
COMMIT;
END CALCULATE_RECOVERY_HISTORY;
当我运行该过程时,收到错误消息
ORA-00001:违反了唯一约束。
我还尝试了另一种方法
SELECT SQ_AP_RECOVERY_HISTORY.NEXTVAL, a_recovery_target_month ...
但这也会返回另一个错误
此处不允许使用序号
要解决这个约束问题,我应该在代码中做什么修改?
以下是T_AP_RECOVERY_HISTORY的表定义
CREATE TABLE "DIMSPST"."T_AP_RECOVERY_HISTORY"
( "ID" NUMBER(38,0),
"RECOVERY_TARGET_MONTH" VARCHAR2(6 BYTE) DEFAULT TO_CHAR(SYSTIMESTAMP, 'YYYYMM'),
"TARGET_INSTANCE" VARCHAR2(20 BYTE),
"RECOVERY_PROGRESS" NUMBER(38,0),
"RECOVERY_TARGET" NUMBER(38,0),
"FAILED_TO_RECOVERY" NUMBER(38,0),
"FOCUS_AREA" VARCHAR2(20 BYTE),
"IDENTIFIER_CLASS" VARCHAR2(42 BYTE),
"CREATED_ON" TIMESTAMP (6),
PRIMARY KEY ("ID")
3条答案
按热度按时间uyhoqukh1#
在子查询中执行聚合,然后在外部查询中应用序列值:
COMMIT
,则不能将多个过程链接在一起,如果一个过程失败,则使用ROLLBACK
,然后使用所有过程。相反,应该在从中调用过程的块中使用COMMIT
。*fiddle
jucafojl2#
一个选项是让Oracle创建ID。您没有指定使用的数据库版本,因此触发器肯定是什么工作:
这样,过程就不会包含
ID
列的插入,即另一个选项(如果您的数据库版本支持)是创建
ID
作为标识列,而不是触发器,例如gopyfrb33#
或者,如果您不想像上一个答案中那样创建触发器,则过程应如下所示:
一般来说,如果使用insert select一次插入大量行,或者使用大规模更新、大规模删除或合并,触发器会对性能造成损害。如果仅使用DML影响少量行,触发器可能会保存复杂性,尽管我宁愿多使用存储过程,少使用触发器。