I've a cursor which fetch dynamic number of columns because the "SELECT STATEMENT" which I use to declare this cursor is dynamic.
Since I do not know at any point of time, how many columns this cursor will have, I cannot declare fixed number of variables into fetch.
So I have built FETCH statement as dynamic and stored in one @variable... but when i run fetch statement using EXEC sp_executesql its failing with error ..Must declare the scalar variable "@objcursor".
I know that @objcursor variable is not accessible becasue while sp_executesql run which run on isolate THREAD
is there any way someone can advise, how to handle this code to run without an error?
Here is my T-SQL code:
/* ==== Variable Declaration ==== */
declare @AllValues nvarchar(max)
declare @objcursor as cursor
declare @MonthCount integer
declare
@vsql as nvarchar(max)
,@vquery as nvarchar(max)
,@id as int
,@value as varchar(50)
BEGIN
SELECT @AllValues = CASE
WHEN t.column_id=1 THEN
(COALESCE(@AllValues +'"', '')+ t.name)+'"'
WHEN t.column_id > 1 THEN
(COALESCE(@AllValues + ',"', '') + t.name)+'"'
END
FROM
(
SELECT sc.name, sc.column_id FROM sys.objects o
INNER JOIN sys.columns sc ON o.object_id = sc.object_id
WHERE o.name = 'temp_daywise' AND o.type = 'U' AND (sc.name like '%Curr Yr%' or column_id=1)
) AS t
ORDER BY t.column_id
SET @AllValues='SELECT "'+@AllValues+' FROM dbo.temp_daywise'
set @vquery = @AllValues
set @vsql = 'set @cursor = cursor forward_only static for ' + @vquery + ' open @cursor;'
exec sys.sp_executesql
@vsql
,N'@cursor cursor output'
,@objcursor output
---Handling Dynamic number of columns in a cursor, get the column count first and build FETCH statement dynamically
Select @CurCount=COUNT(*) from sys.columns where object_id in(
SELECT object_id from sys.objects where name = 'dbo.temp_daywise' and type = 'U' )
and (name like '%Curr Yr%');
SET @LoopCount = 1
--here building my fetch statement
SET @fetchsql ='fetch next from @objcursor into @AgreementID'
WHILE @LoopCount <= @CurCount
BEGIN
SET @fetchsql = @fetchsql+','+'@CY_Day'+CONVERT(VARCHAR(2),@LoopCount)
SET @LoopCount = @LoopCount + 1
END
--EXEC @fetchsql
EXEC sp_executesql @fetchsql
while (@@fetch_status = 0)
begin
BEGIN
'update ...here something'
END
EXEC @fetchsql
end
close @objcursor
deallocate @objcursor
END
Here is my data and expected resullts:
1) My dynamic cusror will read column name from sys.columns because coulmns are not static that's based on columns count I'm building FETCH statement. following code build cusrsor SELECT statement
SELECT @AllValues = CASE
WHEN t.column_id=1 THEN
(COALESCE(@AllValues +'"', '')+ t.name)+'"'
WHEN t.column_id > 1 THEN
(COALESCE(@AllValues + ',"', '') + t.name)+'"'
END
FROM
(
SELECT sc.name, sc.column_id FROM sys.objects o
INNER JOIN sys.columns sc ON o.object_id = sc.object_id
WHERE o.name = 'temp_daywise' AND o.type = 'U' AND (sc.name like '%Curr Yr%' or column_id=1)
) AS t
ORDER BY t.column_id
SET @AllValues='SELECT "'+@AllValues+' FROM dbo.temp_daywise'
set @vquery = @AllValues
set @vsql = 'set @cursor = cursor forward_only static for ' + @vquery + ' open @cursor;'
exec sys.sp_executesql
@vsql
,N'@cursor cursor output'
,@objcursor output
2) I want to update fetch data into following table for columns Day1...Day31. if cusrsor found 20 columns data will update until CY_Day20.

3) In short, i do not know the cusror retrieving columns at design time so i can't produce fetching variable. Since columns are known at run tiume, i have to build fetch & update statment in while loop as like below:
Note: ignore DECLARE which is on start of the code... but i placed here to get an idea.
DECLARE
@CY_Day1 Numeric(18,2), @CY_Day2 Numeric(18,2), @CY_Day3 Numeric(18,2), @CY_Day4 Numeric(18,2), @CY_Day5 Numeric(18,2),
, @CY_Day7 Numeric(18,2), @CY_Day8 Numeric(18,2), @CY_Day9 Numeric(18,2), @CY_Day10 Numeric(18,2), @PY_Day10 Numeric(18,2), @CY_Day11 Numeric(18,2), @CY_Day12 Numeric(18,2),........ @CY_Day31 Numeric(18,2)
Select @CurCount=COUNT(*) from sys.columns where object_id in(
SELECT object_id from sys.objects where name = 'dbo.temp_daywise' and type = 'U' )
and (name like '%Curr Yr%');
SET @LoopCount = 1
SET @fetchsql ='fetch next from @objcursor into @AgreementID'
SET @updatesql ='UPDATE dbo.TPDD_Report_Monthly_Details SET '
WHILE @LoopCount <= 2
BEGIN
SET @fetchsql = @fetchsql+','+'@CY_Day'+CONVERT(VARCHAR(2),@LoopCount)
SET @updatesql= @updatesql +'CY_Day'+CONVERT(VARCHAR(2),@LoopCount)+' = @CY_Day'+CONVERT(VARCHAR(2),@LoopCount)+',CY_TPDD_Day'+CONVERT(VARCHAR(2),@LoopCount)+' = (@CY_Day'+CONVERT(VARCHAR(2),@LoopCount)+'/1/1),'
SET @LoopCount = @LoopCount + 1
END
SET @updatesql =@updatesql + ' dss_update_time = @v_dss_update_time WHERE AgreementId = @AgreementID and TpddYear=CONVERT(VARCHAR(4),@Current_year)+CONVERT(VARCHAR(4),@Previous_year) and Running_Month = @MonthNo'
--EXEC @fetchsql
PRINT @fetchsql
PRINT @updatesql
---executing FETCH statement
EXEC sp_executesql @fetchsql
while (@@fetch_status = 0)
begin
BEGIN
---updating table columns
EXEC sp_executesql @updatesql
END
EXEC @fetchsql
end
close @objcursor
deallocate @objcursor
Finally my cusrsor fetch & udpate statement will looks like below:
fetch next from @objcursor into @AgreementID,@CY_Day1,@CY_Day2,@CY_Day3,@CY_Day4,@CY_Day5,@CY_Day6,@CY_Day7,@CY_Day8,@CY_Day9,@CY_Day10
UPDATE dbo.TPDD_Report_Monthly_Details SET
CY_Day1 = @CY_Day1, CY_TPDD_Day1 = (@CY_Day1/1/1),
CY_Day2 = @CY_Day2, CY_TPDD_Day2 = (@CY_Day2/1/1),
CY_Day3 = @CY_Day3, CY_TPDD_Day3 = (@CY_Day3/1/1),
CY_Day4 = @CY_Day4, CY_TPDD_Day4 = (@CY_Day4/1/1),
CY_Day5 = @CY_Day5, CY_TPDD_Day5 = (@CY_Day5/1/1),
CY_Day6 = @CY_Day6, CY_TPDD_Day6 = (@CY_Day6/1/1),
CY_Day7 = @CY_Day7, CY_TPDD_Day7 = (@CY_Day7/1/1),
CY_Day8 = @CY_Day8, CY_TPDD_Day8 = (@CY_Day8/1/1),
CY_Day9 = @CY_Day9, CY_TPDD_Day9 = (@CY_Day9/1/1),
CY_Day10 = @CY_Day10, CY_TPDD_Day10 = (@CY_Day10/1/1),
dss_update_time = @v_dss_update_time
WHERE AgreementId = @AgreementID
Hope I;m able to present my problem correctly.