处理 DB2 中存储过程或 SQL 中的每一行

Posted

技术标签:

【中文标题】处理 DB2 中存储过程或 SQL 中的每一行【英文标题】:Process Each row in stored procedure or SQL in DB2 【发布时间】: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 但有很多问题,有人可以帮忙

【问题讨论】:

【参考方案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 次会导致这种情况吗?

以上是关于处理 DB2 中存储过程或 SQL 中的每一行的主要内容,如果未能解决你的问题,请参考以下文章

从 DB2 存储过程出口处理程序传播默认 SQL 异常

db2如何创建存储过程

如何使用 SQL 使用 DB2 中的存储过程插入表?

db2 存储过程 异常处理

DB2 LUW - 在存储过程中获取错误行

从SQL服务器为数据集的每一行发送电子邮件。