Executing Dynamic SQL with input of dynamic parameter?

  • 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
    [/code]

    Any help or suggestions are appreciated.

  • 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[/url]

  • 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.

  • 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[/url]

  • Use This:

    -- 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 = @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

  • 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
    Microsoft Certified Master: SQL Server 2008
    Author - SQL Server T-SQL Recipes


    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
    Performance Problems
    Common date/time routines
    Understanding and Using APPLY Part 1 & Part 2

  • 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
    Microsoft Certified Master: SQL Server 2008
    Author - SQL Server T-SQL Recipes


    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
    Performance Problems
    Common date/time routines
    Understanding and Using APPLY Part 1 & Part 2

  • 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-2 TABLE (

    RowID int IDENTITY,

    DateValue datetime)

    -- insert the test data

    insert into @test-2

    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-2

    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 = t1.DateValue

    and 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
    Microsoft Certified Master: SQL Server 2008
    Author - SQL Server T-SQL Recipes


    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
    Performance Problems
    Common date/time routines
    Understanding and Using APPLY Part 1 & Part 2

Viewing 8 posts - 1 through 7 (of 7 total)

You must be logged in to reply to this topic. Login to reply