Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase

Executing Dynamic SQL with input of dynamic parameter? Expand / Collapse
Author
Message
Posted Wednesday, July 01, 2009 5:23 AM
Valued Member

Valued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued Member

Group: General Forum Members
Last Login: Thursday, February 02, 2012 9:51 PM
Points: 56, Visits: 93
Hi Guys, this one has really got me stumped, I may have just been looking at it too long and missing an easier way to acomplish the same task. I'm providing a simple example to make it easier instead of my development TSQL.

What I'm looking to do is to execute a dynamic TSQL string via EXECUTE or sp_executesql while passing in a dynamic parameter dependend on another such as in the case below. I do not want to use a CASE statement if i can get away with it to set a common variable as the input parameter's vary at each runtime. The solution must be 2000 compatible. I've tried using sp_executesql as well although the common error i get back is:
Must declare the scalar variable @Date1



-- PARAMETERS COME FROM USER INPUT AND CAN INCREASE BASED ON REPORTING
DECLARE @Date1 DATETIME, @Date2 DATETIME, @Date3 DATETIME, @Date4 DATETIME
SET @Date1 = '1991/06/01'
SET @Date2 = '1991/06/29'
SET @Date3 = '1991/08/01'
SET @Date4 = '1991/09/04'

DECLARE @Count INT, @Month INT, @TSQL NVARCHAR(4000)
SET @Count = 1
SET @Month = 5

WHILE @Count <= @Month
BEGIN

SET @TSQL = 'Select COUNT(*)
FROM dbo.titles
WHERE pubdate >= @Date' + CONVERT(NVARCHAR(1),@Count) + '
AND pubdate < @Date' + CONVERT(NVARCHAR(1),@Count+1) + ''

EXEC (@TSQL)
PRINT (@TSQL)

SET @Count = @Count + 1
END

Any help or suggestions are appreciated.
Post #745252
Posted Wednesday, July 01, 2009 5:43 AM


SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Today @ 3:02 AM
Points: 1,854, Visits: 7,656
The error is happening as @Date1 is out of scope inside the dynamic sql statement.

There are a few potential solutions i can think of , but how are you receiving the input ?.
Is it a comma delimited list or do you have @Date1 through to @Date255.




Clear Sky SQL
My Blog
Kent user group
Post #745259
Posted Wednesday, July 01, 2009 5:54 AM
Valued Member

Valued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued Member

Group: General Forum Members
Last Login: Thursday, February 02, 2012 9:51 PM
Points: 56, Visits: 93
Hey Dave,

Inputs will be parameters @Date1 to @Date255 and anywhere in between.
In time (3 - 6 months) these dates will be in stored in a table (which i believe I may be able to cursor through) but until then it is all manual input.
The dates follow no particular order and are custom to our company.
Post #745264
Posted Wednesday, July 01, 2009 6:18 AM


SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Today @ 3:02 AM
Points: 1,854, Visits: 7,656
My personal option would be


DECLARE @Date1 DATETIME, @Date2 DATETIME, @Date3 DATETIME, @Date4 DATETIME
SET @Date1 = '1991/06/01'
SET @Date2 = '1991/06/29'
SET @Date3 = '1991/08/01'
SET @Date4 = '1991/09/04'

;with CteDates(Dates)
as
(
Select @Date1 union Select @Date2 union Select @date3 union Select @Date4 -- Thru 255
),
cteDatePairs(LoDate,HiDate)
as
(
Select cteDates.Dates,
nextDate.Dates
from cteDates cross apply (Select top 1 innerdates.Dates
from cteDates innerdates
where innerdates.Dates > cteDates.Dates order by cteDates.Dates) as nextdate
where cteDates.Dates is not null
)

Select cteDatePairs.LoDate,cteDatePairs.HiDate,COUNT(*)
FROM dbo.titles,
cteDatePairs
WHERE pubdate >= cteDatePairs.LoDate
AND pubdate < cteDatePairs.HiDate
group by cteDatePairs.LoDate,cteDatePairs.HiDate





Clear Sky SQL
My Blog
Kent user group
Post #745276
Posted Wednesday, July 01, 2009 7:13 AM
Valued Member

Valued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued MemberValued Member

Group: General Forum Members
Last Login: Sunday, January 22, 2012 9:47 PM
Points: 69, Visits: 47
Use This:

[color=Gray]-- PARAMETERS COME FROM USER INPUT AND CAN INCREASE BASED ON REPORTING
DECLARE @TSQL1 NVARCHAR(4000)
DECLARE @TSQLAll NVARCHAR(4000)
SET @TSQL1 = '
DECLARE @Date1 DATETIME
SET @Date1 = ''1991/06/01''
DECLARE @Date2 DATETIME
SET @Date2 = ''1991/06/29''
DECLARE @Date3 DATETIME
SET @Date3 = ''1991/08/01''
DECLARE @Date4 DATETIME
SET @Date4 = ''1991/09/04'';'
--PRINT @TSQL1
DECLARE @Count INT, @Month INT, @TSQL NVARCHAR(4000)
SET @Count = 1
SET @Month = 1



WHILE @Count <= @Month
BEGIN

SET @TSQL = '

Select COUNT(*)
FROM dbo.titles
WHERE pubdate >= @Date' + CONVERT(NVARCHAR(1),@Count) + '
AND pubdate < @Date' + CONVERT(NVARCHAR(1),@Count+1) + ''
SET @TSQLAll=@TSQL1 + @TSQL
EXEC (@TSQLAll)

PRINT (@TSQLAll)

SET @Count = @Count + 1
END[/color]
Post #745342
Posted Wednesday, July 01, 2009 8:32 AM


SSCertifiable

SSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiable

Group: General Forum Members
Last Login: Monday, February 06, 2012 6:03 PM
Points: 5,928, Visits: 7,363
Dave Ballantyne (7/1/2009)
My personal option would be


DECLARE @Date1 DATETIME, @Date2 DATETIME, @Date3 DATETIME, @Date4 DATETIME
SET @Date1 = '1991/06/01'
SET @Date2 = '1991/06/29'
SET @Date3 = '1991/08/01'
SET @Date4 = '1991/09/04'

;with CteDates(Dates) as


This won't work for sql 2000, as requested .


Wayne
If you can't explain to another person how the code that you're copying from the internet works, then DON'T USE IT on a production system! After all, you will be the one supporting it!
Links: For better assistance in answering your questions, How to ask a question, Performance Problems, Common date/time routines,
CROSS-TABS and PIVOT tables Part 1 & Part 2, Using APPLY, Splitting Delimited Strings
Post #745456
Posted Wednesday, July 01, 2009 8:36 AM


SSCertifiable

SSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiable

Group: General Forum Members
Last Login: Monday, February 06, 2012 6:03 PM
Points: 5,928, Visits: 7,363
Dave, you are actually pretty close.
Instead of using EXEC(), use sp_executesql. This will allow you to pass in the appropriate parameter also - see BOL for how to do this.

In order to enable execution plan reuse, you might want to have one parameter (@Date) inside the dynamic sql, and then just pass the appropriate @Date1, etc. variable to it as the parameter.


Wayne
If you can't explain to another person how the code that you're copying from the internet works, then DON'T USE IT on a production system! After all, you will be the one supporting it!
Links: For better assistance in answering your questions, How to ask a question, Performance Problems, Common date/time routines,
CROSS-TABS and PIVOT tables Part 1 & Part 2, Using APPLY, Splitting Delimited Strings
Post #745459
Posted Wednesday, July 01, 2009 9:23 AM


SSCertifiable

SSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiableSSCertifiable

Group: General Forum Members
Last Login: Monday, February 06, 2012 6:03 PM
Points: 5,928, Visits: 7,363
Dave,
Here's a solution that eliminates the dynamic sql.
-- declare and set the looping variables
DECLARE @Count INT, @Month INT
SET @Count = 1
SET @Month = 5

-- build a table to hold the dates
declare @Test TABLE (
RowID int IDENTITY,
DateValue datetime)
-- insert the test data
insert into @Test
SELECT '1991/06/01' UNION ALL
SELECT '1991/06/29' UNION ALL
SELECT '1991/08/01' UNION ALL
SELECT '1991/09/04'

-- build a table to hold the titles... only need the pubdate field for this test
declare @Titles table (
pubdate datetime)
-- put @Month # of entries in for each date so we will get some counts.
insert into @Titles
select DateValue
from @Test
cross join master.dbo.spt_values
where type = 'P'
and number between 1 and @Month

--get separate results per @count - this duplicates what you're doing now
set @Count = 1
while @Count <= @Month begin
select [Quantity] = COUNT(*)
from @Titles t
INNER JOIN @Test t1 ON t1.RowID = @Count
INNER JOIN @Test t2 ON t2.RowID = @Count + 1
where t.pubdate >= t1.DateValue
and t.pubdate < t2.DateValue
set @Count = @Count + 1
end

--get combined results per @count - in case you want the results in one resultset
-- I'm using a pseudo-tally table here... you can use a real tally table here if you already have one
select [Count#] = c.number ,
[Quantity] = COUNT(*)
from master.dbo.spt_values c
CROSS JOIN @Titles t
INNER JOIN @Test t1 ON t1.RowID = c.number
INNER JOIN @Test t2 ON t2.RowID = c.number + 1
where t.pubdate >= t1.DateValue
and t.pubdate < t2.DateValue
and c.number between 1 and @Month
and c.[type] = 'P'
group by c.number



Wayne
If you can't explain to another person how the code that you're copying from the internet works, then DON'T USE IT on a production system! After all, you will be the one supporting it!
Links: For better assistance in answering your questions, How to ask a question, Performance Problems, Common date/time routines,
CROSS-TABS and PIVOT tables Part 1 & Part 2, Using APPLY, Splitting Delimited Strings
Post #745514
« Prev Topic | Next Topic »

Add to briefcase

Permissions Expand / Collapse