我有一个类似下面的程序,但是当我尝试使用sqlplus运行它时,它给了我错误
BEGIN IB_ARCHIVE_FDS('FDS_LOG','TIME_REQUEST',5,6); END;
第1行的错误:ORA-01722:无效的数字ORA-06512:在“NIAGA.IB_ARCHIVE_FDS”,第10行ORA-06512:在第1行
我正在使用Oracle 9i
CREATE OR replace PROCEDURE Ib_archive_fds(table_name VARCHAR2,
column_name VARCHAR2,
success_period NUMBER,
active_period NUMBER)
IS
TYPE fds_tabs
IS TABLE OF ib_fds_log%ROWTYPE INDEX BY PLS_INTEGER;
TYPE fds_message_id
IS TABLE OF ib_fds_log.message_id%TYPE INDEX BY PLS_INTEGER;
v_fds_log FDS_TABS;
v_message_id FDS_MESSAGE_ID;
BEGIN
SELECT *
bulk collect INTO v_fds_log
FROM ib_fds_log2
WHERE direction = 0
AND status_fds_message = 0
AND time_request < Trunc(SYSDATE - ' || SUCCESS_PERIOD || ' - 1);
FOR i IN 1 .. v_fds_log.last LOOP
V_message_id(i) := V_fds_log(i).message_id;
END LOOP;
forall indx IN 1 .. v_fds_log.count
INSERT INTO ib_fds_log3
VALUES V_fds_log(indx);
COMMIT;
forall indx IN 1 .. v_fds_log.count
DELETE FROM ib_fds_log2
WHERE message_id = V_message_id(indx);
COMMIT;
END;
有人可以帮我解决我的问题。
答案 0 :(得分:4)
这段代码几乎肯定会完全避免使用游标而只是使用SQL语句 - 这就像...
procedure ib_archive_fds(
table_name varchar2,
column_name varchar2,
success_period number ,
active_period number )
is
time_request_limit date;
begin
time_request_limit := trunc(sysdate - success_period - 1)
insert into
ib_fds_log3
select
*
from
ib_fds_log2
where
direction = 0 and
status_fds_message = 0 and
time_request < ib_archive_fds.time_request_limit;
delete from
ib_fds_log2
where
direction = 0 and
status_fds_message = 0 and
time_request < ib_archive_fds.time_request_limit;
end;
如果在执行此操作时查询的结果集不是常量,则可以进行各种增强,但所有PL / SQL只是要求出现错误和性能问题。
答案 1 :(得分:4)
虽然我同意David对您实施的缺点的分析,但该错误消息的实际原因是这个错误:
time_request < trunc(sysdate - ' || SUCCESS_PERIOD || '- 1);
SUCCESS_PERIOD
是一个参数,您可能希望在日期计算中使用它。但是,您已将其编码为字符串;字符串不是数字,因此我们不能在减法中使用。
我不太确定你想要实现什么算术,但我认为你想要这个......
time_request < trunc(sysdate - ( SUCCESS_PERIOD - 1));
......或者......
time_request < trunc(sysdate - ( SUCCESS_PERIOD + 1) );
...取决于您希望如何修改SUCCESS_PERIOD
的值。