分离和附加分区 db2 版本 10.5 给出 sqlstate 55007 错误

Posted

技术标签:

【中文标题】分离和附加分区 db2 版本 10.5 给出 sqlstate 55007 错误【英文标题】:Detach and attach partition db2 version 10.5 giving sqlstate 55007 error 【发布时间】:2019-01-30 13:49:02 【问题描述】:

我有一个 db2 过程,它将一个分区分离到临时表中,然后附加回该分区。当我从快速 sql 执行分离、删除和附加时,它工作得非常好,但是当我从存储过程执行它时,我看到了这个错误。

table 类型的对象“udbadm.table_name”无法更改,因为它当前正被同一个应用程序进程使用。请指教。下面是我的存储过程。

编辑代码以包含 dbms_alert.sleep(120);看到错误在不允许空值的上下文中指定了空值。sqlstate 22004

db2 版本是 10.5。我正在从快速 sql 执行此操作,但是当从线路处理器调用 db2 => call OSL_CLNUP_MNTHLY_SBLDGR_DET(98,56,'08/31/2018',5) 时,我收到了同样的错误。

DROP SPECIFIC PROCEDURE OSLD02.OSL_CLNUP_MNTHLY_SBLDGR_DET
;
  CREATE PROCEDURE OSLD02.OSL_CLNUP_MNTHLY_SBLDGR_DET(IN    
                                          IN_ID_BUS_PROCSS SMALLINT,
                                                IN IN_ID_RUN SMALLINT,
                                                IN IN_DT_EOP DATE,
                                                IN IN_BATCH_SIZE INTEGER)
SPECIFIC OSLD02.OSL_CLNUP_MNTHLY_SBLDGR_DET
MODIFIES SQL DATA
NOT DETERMINISTIC
NULL CALL
LANGUAGE SQL EXTERNAL ACTION
INHERIT SPECIAL REGISTERS

 BEGIN

--------------------------------------------------------------------------    ---------------------------------------
-------------------- Declarations
--------------------------------------------------------------------------   ---------------------------------------
declare v_id_task_log    integer;
declare v_cnt_deleted    integer;
declare v_cnt_initial    integer;
declare v_count integer;
declare v_cd_acctg_purp character(10);
declare v_month_eop integer;
declare SQLCODE int default 0; 
declare v_sqlcode int;
declare v_partitionName character(20);
declare v_lowValue character(10);
declare v_highValue character(10);
declare v_detachStmt varchar(512);    
declare v_dropTable varchar(512);   
declare SQL_STMT varchar(512);   
declare v_exist int;
declare v_stagingSchemaTable varchar(512);
DECLARE v_outmessage VARCHAR(32672);
 DECLARE v_outstatus integer default 0;
 DECLARE v_seconds INTEGER default 300;
 declare wait_until timestamp;
declare detach_complete_flg character(2) default 'N';
declare loop_limit int default 0;

declare global temporary table session.detail_tmp
( partition character(10), start character(30), end character(30) ) on    
  commit preserve rows with replace not logged;

 BEGIN

 DECLARE C1 CURSOR WITH HOLD FOR
 select   DATAPARTITIONNAME, LOWVALUE, HIGHVALUE
 from syscat.DATAPARTITIONS  where tabname='SBLDGR_DET'
 and  (SUBSTR(HIGHVALUE, 2,LOCATE(',',HIGHVALUE)-3)
,SUBSTR(HIGHVALUE, LOCATE(',',HIGHVALUE)+1) ) in (
 select  CD_ACCTG_PURP, mo_eop
 from SBLDGR_DET
 where mo_eop< cast (month(IN_DT_EOP) as char(2))
 group by CD_ACCTG_PURP, mo_eop
 having count(*)>0
 )
with ur;

OPEN C1;--
set v_sqlcode=0;--

L1: LOOP
 FETCH C1 INTO v_partitionName, v_lowValue,v_highValue;
 IF SQLCODE<> 0 THEN 
 LEAVE L1; 
 END IF;

set v_detachStmt = 'ALTER TABLE SBLDGR_DET DETACH PARTITION '   
 ||v_partitionName|| ' INTO TABLE OSLSTG.SL_DET_'||v_partitionName;
 EXECUTE IMMEDIATE v_detachStmt ;
 commit;


 while (loop_limit < 10000 and detach_complete_flg = 'N') DO
call dbms_alert.sleep(60);

 IF EXISTS (SELECT 1 FROM SYSCAT.DATAPARTITIONS WHERE TABSCHEMA='OSLSTG'
     AND 
         TABNAME='SL_DET_'|| v_partitionName AND STATUS=' ')    
THEN             
 set detach_complete_flg = 'Y'; 
 END IF; 

 set loop_limit = loop_limit + 1;
 end while;

 set v_dropTable = 'drop table OSLSTG.SL_DET_'||v_partitionName; 
 EXECUTE IMMEDIATE v_dropTable ;
commit;

 SET SQL_STMT   = 'ALTER TABLE sbldgr_det ADD    
PARTITION '||v_partitionName||' STARTING FROM (' || v_lowValue|| ' )
ENDING AT (' || v_highValue|| ')';
 EXECUTE IMMEDIATE SQL_STMT;   
commit;

END LOOP L1;

 CLOSE   C1;--

 END
 ;

END
;

commit;

【问题讨论】:

您必须等待分离完成(其中一部分是异步的)。考虑睡觉,定期检查实用程序状态。 谢谢毛。在我的程序中,我添加了睡眠,但将其注释掉了。如何检查实用程序状态。有什么可以指点的吗? 对于睡眠使用 DBMS_ALERT.SLEEP()(未记录)或 DBMS_ALERT.WAITONE(记录)。要检查实用程序完成检查 MON_GET_UTILITY 或查询 syscat.datapartitions。还有 SNAP_GET_UTIL_PROGRESS()。 谢谢毛。我使用了 dbms_alert.sleep(300) 但是在运行存储过程时,我得到了在不允许的上下文中指定的空值。 sqlstate 22004 错误。请指教。 更新了代码以包含睡眠方法。我正在尝试查看如何使用您实现的方法实现实用程序完成的示例,但无法弄清楚我们需要使用这些函数检查什么。请提供任何指示或示例。 【参考方案1】:

您的代码中存在许多问题。我不会为您提供完整的解决方案,只是一些说明。

1) 如果您在游标处理期间commit,则必须在DECLARE CURSOR 中使用WITH HOLD 子句。

2) 下面的游标处理不正确。

WHILE (v_sqlcode = 0) DO
  FETCH C1 INTO v_partitionName, v_lowValue,v_highValue;
  set v_sqlcode=sqlcode;
  set v_detachStmt = 'ALTER TABLE SBLDGR_DET DETACH PARTITION'
    ||v_partitionName||' INTO TABLE OSLSTG.SL_DET_'||v_partitionName;
  EXECUTE IMMEDIATE v_detachStmt;
  ...
END WHILE;

即使您在FETCH 之后获得了END OF CURSOR 代码,您仍然会尝试处理数据。 您必须在FETCH 之后立即检查SQLCODE。使用这样的东西:

L1: LOOP
  FETCH C1 INTO v_partitionName, v_lowValue,v_highValue;
  IF SQLCODE<>0 THEN LEAVE L1; END IF;
  ...
END LOOP L1;

3) 您应该执行以下操作。

之后:

EXECUTE IMMEDIATE v_detachStmt;
commit;

你应该实现:

-- Check in loop (sleep, let's say N sec, after each check) 
-- until you get a row with the following statement
-- (construct your table name dynamically):

SELECT 1 
FROM SYSCAT.DATAPARTITIONS
WHERE TABSCHEMA='OSLSTG' AND TABNAME='SL_DET_v_partitionName' AND STATUS=''
WITH UR;

查看Detaching data partitions 主题了解更多详情。

【讨论】:

感谢马克您的意见。我将合并这些并进行测试。 Mark 感谢您提供的所有输入。我按照您提到的进行了更改,但分区没有被删除。程序的返回码为零,但分区数据没有被删除;你能检查一下,如果这里有什么不正确的地方,请告诉我。 CALL DBMS_OUTPUT.PUT_LINE('msg: '||v_*); 的调试调用插入到您的代码中,并在调用DB2 CLP 中的例程之前使用SET SERVEROUTPUT ON 命令来了解会发生什么。或者使用调试器告诉我们例程在执行过程中到底发生了什么。

以上是关于分离和附加分区 db2 版本 10.5 给出 sqlstate 55007 错误的主要内容,如果未能解决你的问题,请参考以下文章

db2 v10安装

Vmware Workstation + Suse Linux 11 SP3 + db2 purescale V10.5

db2 v10.5 HADR快速部署手册

DB2 Version 10.5 补丁下载

Vmware Workstation + Suse Linux 11 SP3 + db2 purescale V10.5

本地连接虚拟机db2V10.5遇到的问题