Plsql DBMS_输出到带有时间戳的表

Plsql DBMS_输出到带有时间戳的表,plsql,Plsql,我正在删除一个大型表,并希望批量删除该表。我正在删除超过467天的记录。我想在以下过程中插入dbms_输出状态,将其写入一个表中,该表有两列,例如要删除的记录数和时间戳列: CREATE OR REPLACE PROCEDURE delete_tab (tablename IN VARCHAR2, nrows IN NUMBER ) IS sSQL1 VARCHAR2(2000); sSQL2 VARCHAR2(2000); nCount NUMBER; BEGIN DBMS_OUTPUT

我正在删除一个大型表,并希望批量删除该表。我正在删除超过467天的记录。我想在以下过程中插入dbms_输出状态,将其写入一个表中,该表有两列,例如要删除的记录数和时间戳列:

CREATE OR REPLACE PROCEDURE delete_tab (tablename IN VARCHAR2, nrows IN NUMBER ) IS

sSQL1 VARCHAR2(2000);
sSQL2 VARCHAR2(2000);
nCount NUMBER;

BEGIN

DBMS_OUTPUT.enable (100000);
nCount := 0;
sSQL1:='delete from '|| tablename ||
' where ROWNUM < ' || nrows || ' and where cast(time_stamp as date) < sysdate - 467';
sSQL2:='select count(ROWID) from ' || tablename ||
' where cast(time_stamp as date) < sysdate - 467';

EXECUTE IMMEDIATE sSQL2 INTO nCount;

LOOP

EXECUTE IMMEDIATE sSQL1;

nCount := nCount-nrows;

DBMS_OUTPUT.PUT_LINE('Existing records to be deleted: ' || to_char(nCount));

commit;

EXIT WHEN nCount = 0;

END LOOP;

END delete_tab;
/
CREATE或REPLACE PROCEDURE delete_选项卡(VARCHAR2中的tablename,数字中的nrows)为
sSQL1 VARCHAR2(2000年);
sSQL2-VARCHAR2(2000);
n计数;
开始
DBMS_OUTPUT.enable(100000);
n计数:=0;
sSQL1:='delete from'| | tablename||
“where ROWNUM<'| | nrows | | |”和where cast(时间戳为日期)

让我知道如何在块中添加insert语句来编写进度。

除了缺少insert之外,此代码还存在一些其他小问题和一个大问题

ssql1:='delete from '|| tablename ||
' where ROWNUM < ' || nrows || ' and where cast(time_stamp as date) < sysdate - 467';
ssql1:='delete from'|| tablename||
“where ROWNUM<'| | nrows | | |”和where cast(时间戳为日期)
如果上述内容有效,那么在每次执行时,只要有那么多行仍然存在,就使用nrows-1(而不是我怀疑您所想的nrows)。但是,它是无效的;where子句无效。where子句的正确格式为 “哪里和……”;不要在其中重复

ssql2:='select count(ROWID)from'| | tablename||
“where cast(time_stamp as date)
没有理由计算rowid,每行正好有1个。ROWID是一个伪列,告诉Oracle行在磁盘上的位置。您可能听说过,这是检索特定对象的最快方法-这是真的-但它是而不是真的选择rowid本身更快,如果有什么区别的话,它会更慢。它需要一次完整的表扫描,并计算表中每一行的值。优化器可能会注意到发生了什么,并将其更改为选择count(),但为什么希望从count()开始呢

现在我们来谈谈最糟糕的问题。除非要删除的行总数是参数nrows的精确倍数,否则该过程将成为一个永无止境的循环,直到抛出异常ORA-22054:下溢错误。 这是因为作为唯一退出条件的结果是“ncount=0时退出”。假设要删除1002行,nrows为1000。第一次迭代删除999,然后将ncount减少到2(1002-1000)。然后第二次迭代删除另一个999,并将ncount减少到-998(2-1000)。该过程继续迭代,直到ncount最终达到这个值(类似于-1*10^39-1)。 您可以将退出条件更改为“nCount<1时退出”。但即使这样也没有必要,代码根本不需要计算退出条件。让甲骨文告诉你吧。delete语句返回SQL%rowcount,其中包含最后一条DML语句处理的行数。如果没有处理,则返回0。因此,exist条件变成了一个简单的“当sql%rowcount=0时退出”。教训:在0等于0的条件下,始终要小心
考虑到所有这些因素,程序变得简单。(还更改了变量名,因为我不喜欢ssql1、ssql2和为两件事重用一个变量。使用这些变量时,我会搞不清哪个是哪个,尤其是在大型过程中。):

创建或替换过程删除选项卡
(varchar2中的表名)
,在数目上
) 
是
删除第2条(2000年);
伯爵2(2000年);
删除计数编号;
期望删除号码;
开始
dbms_output.enable(100000);
count_sql:=“从”|| tablename中选择count(*)||
'其中时间戳<当前时间戳-467';
dbms_output.put_line('COUNT_SQL:'| COUNT_SQL
);                  
在expect\u delete中执行立即计数\u sql;
dbms_output.put_line('要删除的现有记录:'|| to_char(除_delete外));
delete_sql:='delete from'| | tablename||

'rownum在哪里可以不简单地添加INSERT语句?也许可以看看感谢您的帮助!!它起作用了!!如果这解决了你的问题,请接受答案,因为它有助于未来有同样问题的提问者。请不要将已成功回答的问题保留为未回答。
ssql2:='select count(ROWID) from ' || tablename ||
' where cast(time_stamp as date) < sysdate - 467';
create or replace procedure delete_tab 
                          ( tablename in varchar2
                          , nrows in number 
                          ) 
is
    delete_sql     varchar2(2000);
    count_sql      varchar2(2000);
    deleted_count  number;   
    expect_delete  number; 
begin

    dbms_output.enable (100000);
                   
    count_sql := 'select count(*) from ' || tablename ||
                 ' where  time_stamp  < current_timestamp - 467';
    dbms_output.put_line('COUNT_SQL: ' || count_sql
                        );                  
    
    execute immediate count_sql into expect_delete;
    dbms_output.put_line('Existing records to be deleted: ' || to_char(expect_delete));  
    
    delete_sql := 'delete from '|| tablename ||
                  ' where rownum <= ' || nrows || 
                  ' and cast(time_stamp as date) < sysdate - 467';
    dbms_output.put_line('DELETE_SQL: '
                        || delete_sql
                        );    
    
    deleted_count := 0;
    loop 
       execute immediate delete_sql; 
       exit when sql%rowcount = 0;
       deleted_count := deleted_count+sql%rowcount;             
       commit;
    end loop;
    
    insert into delete_log( table_name, date_deleted, rows_deleted) 
      values (tablename, sysdate, deleted_count) ;
      
    commit;    -- commit the deletes in final loop and insert
end delete_tab;