Область применения переменных в процедуре SQL Server при использовании курсоров - PullRequest
0 голосов
/ 26 марта 2012

Я пытаюсь сохранить данные, извлеченные из БД, в одну переменную и вернуть их в код Java.

Возвращается значение NULL.Это из-за области видимости переменных в курсоре.Кто-нибудь может предложить решение для этого?

Вот моя процедура:

ALTER PROCEDURE [dbo].[rml_ups_profilerscheduler] @RuleIds varchar(200) output
    -- Add the parameters for the stored procedure here
    --<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>, 
    --<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @rulescheduleid varchar(50), @scheduletype varchar(50),@finalop varchar(50)
    DECLARE cursorName CURSOR GLOBAL
    FOR
    select distinct rulescheduleid,scheduletype
    from rml_ups_ruleschedulemaster 
    OPEN cursorName -- open the cursor
    FETCH NEXT FROM cursorName
    INTO @rulescheduleid, @scheduletype
     set @finalop=''
     if(lower(@scheduletype) ='daily')
     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE()))
     and a.rulescheduleid=1)))

    -- PRINT @rulescheduleid + ' ' + @scheduletype -- print the name
     if(lower(@scheduletype) ='weekly')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofweek =(SELECT DATEPART(dw, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='monthly')

      set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='yearly')

      set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE()))  and 
     a.schedulemonth=(SELECT DATEPART(mm, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='on at time')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
    where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
    and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE()))
    and schedulemonth=(SELECT DATEPART(mm, GETDATE()))  and 
    a.scheduleyear=(SELECT DATEPART(yy, GETDATE())) 
    and a.rulescheduleid=@rulescheduleid)))

    --PRINT @rulescheduleid + ' ' + @scheduletype -- print the name
    --PRINT @@FETCH_STATUS
    WHILE @@FETCH_STATUS = 0
    BEGIN
    ---PRINT @@FETCH_STATUS

     FETCH NEXT FROM cursorName
     INTO @rulescheduleid, @scheduletype

     if(lower(@scheduletype) ='daily')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE()))
     and a.rulescheduleid=@rulescheduleid)))

    -- PRINT @rulescheduleid + ' ' + @scheduletype -- print the name
     if(lower(@scheduletype) ='weekly')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofweek =(SELECT DATEPART(dw, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='monthly')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='yearly')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
     where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
     and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE()))  and 
     a.schedulemonth=(SELECT DATEPART(mm, GETDATE())) 
     and a.rulescheduleid=@rulescheduleid)))

     if(lower(@scheduletype) ='on at time')

     set @finalop=@finalop+','+(SELECT CONVERT(varchar(150),
    (select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
    where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
    and scheduleendhour >=(SELECT DATEPART(hh, GETDATE())) and a.scheduledayofmonth =(SELECT DATEPART(dd, GETDATE()))
    and schedulemonth=(SELECT DATEPART(mm, GETDATE()))  and 
    a.scheduleyear=(SELECT DATEPART(yy, GETDATE())) 
    and a.rulescheduleid=@rulescheduleid)))
    PRINT @finalop 
    set @RuleIds=@finalop
    PRINT  @RuleIds 
    -- print the name

    END
    --set @RuleIds=@finalop
    --PRINT @RuleIds 
    CLOSE cursorName
    -- close the cursor
    --PRINT  @RuleIds  
    DEALLOCATE cursorName
    -- Deallocate the cursor


END

Ответы [ 4 ]

1 голос
/ 26 марта 2012

Этот бит:

WHILE @@FETCH_STATUS = 0
BEGIN
---PRINT @@FETCH_STATUS

 FETCH NEXT FROM cursorName
 INTO @rulescheduleid, @scheduletype

Определенно неверно - @@FETCH_STATUS обновляется на основе результата предыдущего оператора FETCH - но вы уже использовали результат этого FETCH до того, как достигнете этого цикла, а затем немедленно выполните другой FETCH и не проверяйте его успешность до тех пор, пока вы его не используете.

Обычная форма будет:

DECLARE <cursor>
OPEN <cursor>

FETCH NEXT FROM <cursor>
WHILE @@FETCH_STATUS = 0
BEGIN
    <process result from previous fetch>

    FETCH NEXT FROM <cursor>
END

CLOSE <cursor>
DEALLOCATE <cursor>

По-видимому, всякий раз, когда вы выходите за пределы конца набора результатов, он устанавливает локальные переменные (например, @rulescheduleid) в NULL, а затем вы выполняете конкатенацию с NULL, получая результаты NULL.

При этом я не прочитал оставшуюся часть кода, чтобы понять, что вы пытаетесь сделать, и нужен ли вообще курсор.

0 голосов
/ 27 марта 2012

Лично я бы вообще не использовал курсор.Я бы использовал операторы CASE для выбора, чтобы получить поля, которые вы хотите отправить обратно в приложение, и вернуть весь набор данных.Затем я зациклил бы набор данных на стороне приложения, чтобы установить значения параметров в соответствии с требованиями приложения.

0 голосов
/ 27 марта 2012
i had modified my code procedure is running without any error but at the end of the loop values(retrived from db based on conditoins) asaigned to a variable is becoming empty after the loop is completed here is my modified code 

set @ RuleIds = '' ОБЪЯВИТЬ @RuleIds ОБЪЯВИТЬ cName CURSOR ЗА выберите отличный идентификатор, стиль из таблицы1 OPEN cursorName - открыть курсор ПОЛУЧИТЬ СЛЕДУЮЩУЮ ОТ cName INTO @rul, @sche

WHILE @@FETCH_STATUS = 0
BEGIN
 if(lower(@sched) ='daily')
 set @RuleIds=@RuleIds+','+(SELECT CONVERT(varchar(150),
(select ruleid from rml_ups_ruleschedulemaster  a,rml_ups_rulescheduletimemapping b
 where a.rulescheduleid=b.rulescheduleid and b.schedulestarthour <= (SELECT DATEPART(hh, GETDATE()))
 and scheduleendhour >=(SELECT DATEPART(hh, GETDATE()))
 and a.rulescheduleid=@rulescheduleid)))
-- here iam trying to store retreved values in to variable and returning to the java code it is retuning null values
PRINT @RuleIds 
-- it prints the values assaigned to @RuleIds variable ex values(13,12,2)
 FETCH NEXT FROM cName
 INTO @rul, @sche
END
CLOSE cName
DEALLOCATE cName
--after deaalocating of cursor the valuse stored in  @RuleIds(variable) is becoming empty
PRINT @RuleIds 
---this print statement printing  nothing 
0 голосов
/ 26 марта 2012

По сути, ваш курсор организован так:

open cursor

fetch first row into vars

process the fetched values

while @@fetch_status = 0

  fetch next row into vars
  process the fetched values

end

close cursor

Теперь, часть process the fetched values значительна в вашей процедуре, и она повторяется дважды в вашем коде, что одно.Еще одна, более важная вещь: когда вы обрабатываете извлеченные значения в теле цикла, вы, по сути, делаете это сразу же после извлечения значений.Но если это последняя итерация, она будет извлекать NULL и, в результате вашей обработки NULL, ваша выходная переменная также будет иметь значение NULL.

Итак, что вам следует делать в этой ситуации?Просто опустите стадию process the fetched values перед циклом и переместите другую, которая идет после шага fetch next row into vars, в позицию перед , чтобы структура вашего курсора стала такой:

open cursor

fetch first row into vars

while @@fetch_status = 0

  process the fetched values
  fetch next row into vars

end

Таким образом, у вас есть только одно место, где вы обрабатываете значения и , вы делаете это только тогда, когда значения не равны NULL, потому что, как только другой FETCH NEXT вызываетNULL, вы выходите из цикла, сохраняя накопленный вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...