日期:2014-05-18  浏览次数:20591 次

纠结的并发动态游标问题
今天在程序中使用动态游标(考虑到SP并发问题),于是将原有的简单动态游标加以处理,使得游标名称也动态执行,发现了新问题,很是纠结,如下:

SET @V_SQL_SUB = 'DECLARE CUR_SCR_SUB_'+@V_BTCH_EXAM_ID+' SCROLL CURSOR FOR '+CHAR(13)+
'SELECT DISTINCT T1.SUB_ID '+CHAR(13)+
'FROM EXAM.SCR_SGMNT_SET_CD T1 '+CHAR(13)+
'where T1.BTCH_EXAM_ID = '+ @V_BTCH_EXAM_ID+
' AND T1.SUB_ID<>-1'
PRINT '@V_SQL_SUB='+@V_SQL_SUB
EXEC (@V_SQL_SUB)
SET @V_END_TIME =GETDATE()
EXEC PUB_PLFM.USP_LOG_CHK_SQL_RUN @SP_ID,@SP_NM,@I_TRM_ID,@I_SCHL_ID,@V_STEP_ID, @V_STEP_DSC,NULL, @V_CRNT_TIME,@V_END_TIME,@@rowcount,NULL,@V_SQL_SUB,NULL

SET @V_TMP_SQL_CUR= 'OPEN CUR_SCR_SUB_'+@V_BTCH_EXAM_ID;
EXEC (@V_TMP_SQL_CUR)
PRINT '共计科目数='+CAST(@@cursor_Rows AS VARCHAR(10))

  SET @V_TMP_SQL_CUR='CUR_SCR_SUB_'+@V_BTCH_EXAM_ID
---DECLARE @V_CUR CURSOR;
---SET @V_CUR = 'CUR_SCR_SUB_'+@V_BTCH_EXAM_ID;
SET @V_SUB_CNT = @@cursor_Rows ---获得科目数
IF (@V_SUB_CNT>0) --如果科目大于0,则进行条件判断SQL串组织
BEGIN
SET @i=0;
--FETCH NEXT FROM @V_TMP_SQL_CUR into @V_SUB_ID;
SET @V_TMP_SQL_CUR = 'FETCH NEXT FROM CUR_SCR_SUB_'+@V_BTCH_EXAM_ID +' into @V_SUB_ID '
----报错信息:(1 行受影响)
共计科目数=4
@V_TMP_SQL_CUR=FETCH NEXT FROM CUR_SCR_SUB_20111208140702884 into @V_SUB_ID
消息 137,级别 15,状态 2,第 1 行
Must declare the scalar variable "@V_SUB_ID". PRINT '@V_TMP_SQL_CUR='+@V_TMP_SQL_CUR
EXEC (@V_TMP_SQL_CUR)
WHILE @@FETCH_STATUS = 0
BEGIN
SET @i = @i+1;
IF @V_SET_SUB = '' 
SET @V_SET_SUB = CAST(@V_SUB_ID AS nVARCHAR(20))
ELSE 
SET @V_SET_SUB =@V_SET_SUB+ ','+CAST(@V_SUB_ID AS nVARCHAR(20))
PRINT '@V_SET_SUB='+@V_SET_SUB
PRINT '@i='+CAST(@i AS VARCHAR(2))
IF (@i = 1)
BEGIN
SET @V_SQL_STR = 'CASE WHEN SUB_ID = '+CAST(@V_SUB_ID AS VARCHAR(20))+' THEN '+CHAR(13)
SET @V_SQL_SGMNT_NM = @V_SQL_STR;
END
ELSE
BEGIN
SET @V_SQL_STR = @V_SQL_STR + 'WHEN SUB_ID = '+CAST(@V_SUB_ID AS VARCHAR(20))+' THEN '+CHAR(13)
SET @V_SQL_SGMNT_NM = @V_SQL_SGMNT_NM+ 'WHEN SUB_ID = '+CAST(@V_SUB_ID AS VARCHAR(20))+' THEN '+CHAR(13)
END

---======================================================================================
--定义分段游标
SET @V_STEP_ID = 10000130+@i;
SET @V_STEP_DSC = '建立分档游标';
SET @V_CRNT_TIME = GETDATE();

-----判断游标是否存在
SELECT @V_CUR_ST=CURSOR_STATUS('global','CUR_SCR_SGMNT_'+@V_BTCH_EXAM_ID)
IF @V_CUR_ST<>-3
BEGIN
SET @V_TMP_SQL_CUR= 'DEALLOCATE CUR_SCR_SGMNT_'+@V_BTCH_EXAM_ID;
EXEC (@V_TMP_SQL_CUR)
END

----定义单科成绩分段游标
SET @V_SQL_CUR= ' DECLARE CUR_SCR_SGMNT_'+@V_BTCH_EXAM_ID+' SCROLL CURSOR FOR '+  
' SELECT T.SGMNT_ID,T.LWR_SCR,T.LWR_CNDTN '+
',T.LMT_SCR,T.LMT_CNDTN,T.SGMNT_NM '+
' FROM EXAM.SCR_SGMNT_SET_CD T '+
' WHERE T.BTCH_EXAM_ID = '+@V_BTCH_EXAM_ID +
' AND T.SUB_ID='+CAST(@V_SUB_ID AS VARCHAR(20))+
' ORDER BY SEQ_ID ASC ';

  PRINT @V_SQL_CUR
EXEC (@V_SQL_CUR)
 
----记录SQL日志
SET @V_END_TIME =GETDATE()
EXEC PUB_PLFM.USP_LOG_CHK_SQL_RUN @SP_ID,@SP_NM,@I_TRM_ID,@I_SCHL_ID,@V_STEP_ID, @V_STEP_DSC,NULL, @V_CRNT_TIME,@V_END_TIME,@@rowcount,NULL,@V_SQL_CUR,NULL


SET @V_TMP_SQL_CUR='OPEN CUR_SCR_SGMNT_'+@V_BTCH_EXAM_ID;--打开游标
EXEC (@V_TMP_SQL_CUR);
SET @V_SGMNT_CNT = @@cursor_Rows ---获得分段数
--PRINT '@V_SGMNT_CNT='+CAST(@V_SGMNT_CN