【问题标题】:Process Each row in stored procedure or SQL in DB2处理 DB2 中存储过程或 SQL 中的每一行
【发布时间】:2018-01-18 16:58:23
【问题描述】:

我基本上来自 Oracle 背景并尝试创建一个 SQL 代码或存储过程,它将为每个处于重组挂起状态的表执行 REORG

我已经想出办法来获取下面给出的这些表格的列表

SELECT 'CALL SYSPROC.ADMIN_CMD(''REORG TABLE', substr(rtrim(TABSCHEMA)||'.'||rtrim(TABNAME),1,20) ||''')', ';'来自 SYSIBMADM.ADMINTABINFO,其中 REORG_PENDING = 'Y' AND TABSSCHEMA=CURRENT SCHEMA

现在我的要求是为找到的每一行将这个结果集作为 DB2 SQL 命令运行,我没有使用 shell 脚本或批处理文件的选项,它必须使用 SQL 或存储过程来完成。我尝试创建 proc 但有很多问题,有人可以帮忙

【问题讨论】:

    标签: db2


    【解决方案1】:

    没有必要为此编写存储过程,除非您有特殊要求。您可以通过以下方式要求 Db2 完成工作:

    CALL SYSPROC.ADMIN_REVALIDATE_DB_OBJECTS('table', current schema, NULL)

    您可以阅读有关该功能的信息here

    否则,如果您确实对重组有特殊要求,使用游标查找完全限定表名可能更简单,即使用游标填充数组并迭代该数组以进行重组.

    在生产环境中使用离线重组要格外小心,因此您可能需要内置一些防御性代码来防止导致服务中断。

    否则,您可以使用"Receiving procedure result sets in SQL routines" 文档中提到的技术处理从存储过程返回的结果集

    此外,如果您的 Db2 数据库是为支持 Oracle 兼容性而创建的,那么您可以使用 Oracle PLSQL 语法并且只添加 ADMIN_CMD() 内容。在这种情况下,您不必使用 Db2 的 ANSI SQLPL 样式。

    这是一个使用游标和数组的愚蠢的简单示例,还有许多其他方法可以做到这一点,包括更优雅的方法:

    --#SET TERMINATOR @
    
    create or replace  type reorg_list  as VARCHAR(1024) array[]
    @
    
    create or replace procedure sp_reorgpending ()
    language sql 
    specific sp_reorgpending
    begin 
        declare v_sqlcode integer default 0; 
        declare v_stmt varchar(1024); 
        declare v_tabname varchar(1024);
        declare tables_to_reorg reorg_list;
        declare v_counter integer;
        declare c1 cursor with hold for select rtrim(tabschema)||'.'||rtrim(tabname) from SYSIBMADM.ADMINTABINFO where REORG_PENDING = 'Y' AND TABSCHEMA=CURRENT SCHEMA;
        declare continue handler for not found set v_sqlcode=100;
    
        set v_counter=0;
        open c1;
        fetch c1 into v_tabname;
        while ( v_sqlcode = 0 ) do
            set v_counter = v_counter + 1 ;
            set tables_to_reorg[v_counter] = v_tabname;
            fetch c1 into v_tabname;
        end while;
        close c1;
        while ( v_counter > 0 ) do
            set v_stmt='reorg table '||tables_to_reorg[v_counter] ;
            call admin_cmd(v_stmt);
            set v_counter = v_counter -1 ;
        end while;
       return 0; 
    end
    @
    

    【讨论】:

    • mao,这是一个很大的帮助,非常感谢。还有一个问题,有什么方法可以在执行过程时打印每个表名的值,即过程执行应该给出每个表名的输出
    • 您可以添加逻辑以将进度插入另一个表(最好通过自主存储过程完成),这将允许另一个进程查询该表的进度。或者,如果您想等到作业结束,请使用 dbms_output.put_line()。
    • 是的,我已经通过创建一个临时表来跟踪它来解决这个问题。谢谢。
    • 是否有任何文件说明哪些活动会导致表格进入重组待定状态?我知道更改数据类型是其中之一,但是我不确定是什么其他原因导致了这种情况,找不到关于此的适当文档。连续更改表格 3 次会导致这种情况吗?
    猜你喜欢
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    相关资源
    最近更新 更多