Referencing a table type In Dynamic SQL

  • I want to use a table variable in a merge statement using Dynamic SQL

    I know that you cant reference table variables in Dynamic SQL as they are out of scope.

    So instead ive elected to use a Table type but having problems.

    My code as follows:

    /****** Object:  UserDefinedTableType [dbo].[ChannelReadingType]    Script Date: 28/03/2023 14:18:44 ******/
    CREATE TYPE [dbo].[ChannelReadingType] AS TABLE(
    [ReadingDateTime] [datetime2](7) NULL,
    [RawReading] [int] NULL,
    [SIReading] [real] NULL
    )
    GO
    CREATE TABLE [dbo].[t](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [SerialNumber] [nvarchar](60) NULL,
    [ChannelID] [int] NULL,
    [Si] [decimal](10, 2) NULL,
    [Raw] [decimal](10, 2) NULL,
    [Conversion] [int] NULL,
    [TimeStamp] [datetime] NULL
    ) ON [PRIMARY]
    GO

    DECLARE@t [dbo].[ChannelReadingType];
    DECLARE@ChannelReadingTableName NVARCHAR(500) = '[ChannelReading_939029_11_F0EA4CCA-3522-4175-AA53-83563F91235F]'
    DECLARE@ChannelID INT = 11
    DECLARE@SQL NVARCHAR(4000)

    -- insert test data into [dbo].[t]
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24073, N'939029', 14, CAST(53.60 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T13:11:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24074, N'939029', 14, CAST(53.01 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T13:21:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24075, N'939029', 14, CAST(52.42 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T13:31:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24076, N'939029', 14, CAST(53.79 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T13:41:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24077, N'939029', 14, CAST(50.74 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T13:51:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24078, N'939029', 14, CAST(54.00 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:01:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24079, N'939029', 14, CAST(53.23 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:11:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24080, N'939029', 14, CAST(52.74 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:21:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24081, N'939029', 14, CAST(53.99 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:31:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24082, N'939029', 14, CAST(50.80 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:41:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24083, N'939029', 14, CAST(54.02 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T14:51:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24084, N'939029', 14, CAST(52.42 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T15:01:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24085, N'939029', 14, CAST(53.68 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T15:11:31.000' AS DateTime))
    GO
    INSERT [dbo].[t] ([ID], [SerialNumber], [ChannelID], [Si], [Raw], [Conversion], [TimeStamp]) VALUES (24086, N'939029', 14, CAST(53.74 AS Decimal(10, 2)), CAST(0.00 AS Decimal(10, 2)), 0, CAST(N'2022-09-13T15:21:31.000' AS DateTime))
    GO


    SET @sql = 'MERGE ' + @ChannelReadingTableName + ' T '+ CHAR(13) + CHAR(10) +
    ' USING
    (
    SELECT
    Sias SIReading,
    [Raw]as RawReading,
    [TimeStamp]as ReadingDateTime
    FROM
    @tt
    WHERE
    ChannelID = ' + '''' + CAST(@ChannelID as nvarchar(10)) + '''' + CHAR(13) + CHAR(10) +

    --) AS ChannelReading ' + CHAR(13) + CHAR(10) +

    ' ) S on T.ReadingDateTime = S.ReadingDateTime ' + CHAR(13) + CHAR(10) +

    ' WHEN NOT MATCHED BY TARGET '+ CHAR(13) + CHAR(10) +
    ' THEN '+ CHAR(13) + CHAR(10) +
    ' INSERT (ReadingDateTime,SIReading, RawReading)'+ CHAR(13) + CHAR(10) +
    ' VALUES (S.ReadingDateTime,S.SIReading, S.RawReading); '+ CHAR(13) + CHAR(10) +
    ' ' + CHAR(13) +
    ' SET @Count= @@ROWCOUNT '

    DECLARE @ParmDefinition NVARCHAR(500);
    SET @ParmDefinition = N'@Count int OUTPUT';
    PRINT @SQL

    -- EXECUTE sp_executesql @SQL, N' @tt myTable READONLY', @t;


    EXECUTE sp_executesql @SQL,@ParmDefinition, N' @tt [dbo].[ChannelReadingType] READONLY', @t,@Count = @rowcount OUTPUT;

    When i run this i get the following error

    Msg 1087, Level 15, State 2, Line 9

    Must declare the table variable "@tt"

    But i have declared the table variable here

    EXECUTE sp_executesql @SQL,@ParmDefinition, N' @tt dbo.ChannelReadingType READONLY', @t,@Count = @rowcount OUTPUT;

    what am I doing wrong?

     

  • You can't parameterize a from clause. You could parameterize the WHERE clauses.

    You could concatenate the table type into dynamic sql as described here: https://odetocode.com/articles/365.aspx

     

  • ratbak wrote:

    You can't parameterize a from clause. You could parameterize the WHERE clauses.

    You could concatenate the table type into dynamic sql as described her: https://odetocode.com/articles/365.aspx

    Sorry I dont understand , what do you mean by concatenate the table type into dynamic sql?

  • You can reference a temp table in dynamic SQL.  Could you create a temp table and load it instead?

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • ScottPletcher wrote:

    You can reference a temp table in dynamic SQL.  Could you create a temp table and load it instead?

     

    I dont want to use a temp table because we are running this on Azure.. and temp table creation takes costly execution time

  • Can be done your logic is just a little off.

    The "ParamDefinition" must be a continuous string of all params for the dynamic SQL

    DECLARE @t [dbo].[ChannelReadingType];
    DECLARE @ChannelReadingTableName NVARCHAR(500) = '[ChannelReading_939029_11_F0EA4CCA-3522-4175-AA53-83563F91235F]'
    DECLARE @ChannelID INT = 11
    DECLARE @SQL NVARCHAR(4000)
    DECLARE @CountOUT INT


    SET @sql = 'MERGE ' + @ChannelReadingTableName + ' T '+ CHAR(13) + CHAR(10) +
    ' USING
    (
    SELECT
    Sias SIReading,
    [Raw]as RawReading,
    [TimeStamp]as ReadingDateTime
    FROM
    @tt
    WHERE
    ChannelID = ' + '''' + CAST(@ChannelID as nvarchar(10)) + '''' + CHAR(13) + CHAR(10) +

    --) AS ChannelReading ' + CHAR(13) + CHAR(10) +

    ' ) S on T.ReadingDateTime = S.ReadingDateTime ' + CHAR(13) + CHAR(10) +

    ' WHEN NOT MATCHED BY TARGET '+ CHAR(13) + CHAR(10) +
    ' THEN '+ CHAR(13) + CHAR(10) +
    ' INSERT (ReadingDateTime,SIReading, RawReading)'+ CHAR(13) + CHAR(10) +
    ' VALUES (S.ReadingDateTime,S.SIReading, S.RawReading); '+ CHAR(13) + CHAR(10) +
    ' ' + CHAR(13) +
    ' SET @Count= @@ROWCOUNT '

    DECLARE @ParmDefinition NVARCHAR(500);
    SET @ParmDefinition = N'@Count int OUTPUT, @tt [dbo].[ChannelReadingType] READONLY';
    PRINT @SQL

    -- EXECUTE sp_executesql @SQL, N' @tt myTable READONLY', @t;


    EXECUTE sp_executesql @SQL,@ParmDefinition, @tt = @t,@Count = @CountOUT OUTPUT;

    Can't test it fully as the "merge" table isn't provided as a create but that should do what you want it to do

  • Ant-Green wrote:

    Can be done your logic is just a little off.

    The "ParamDefinition" must be a continuous string of all params for the dynamic SQL

    DECLARE @t [dbo].[ChannelReadingType];
    DECLARE @ChannelReadingTableName NVARCHAR(500) = '[ChannelReading_939029_11_F0EA4CCA-3522-4175-AA53-83563F91235F]'
    DECLARE @ChannelID INT = 11
    DECLARE @SQL NVARCHAR(4000)
    DECLARE @CountOUT INT


    SET @sql = 'MERGE ' + @ChannelReadingTableName + ' T '+ CHAR(13) + CHAR(10) +
    ' USING
    (
    SELECT
    Sias SIReading,
    [Raw]as RawReading,
    [TimeStamp]as ReadingDateTime
    FROM
    @tt
    WHERE
    ChannelID = ' + '''' + CAST(@ChannelID as nvarchar(10)) + '''' + CHAR(13) + CHAR(10) +

    --) AS ChannelReading ' + CHAR(13) + CHAR(10) +

    ' ) S on T.ReadingDateTime = S.ReadingDateTime ' + CHAR(13) + CHAR(10) +

    ' WHEN NOT MATCHED BY TARGET '+ CHAR(13) + CHAR(10) +
    ' THEN '+ CHAR(13) + CHAR(10) +
    ' INSERT (ReadingDateTime,SIReading, RawReading)'+ CHAR(13) + CHAR(10) +
    ' VALUES (S.ReadingDateTime,S.SIReading, S.RawReading); '+ CHAR(13) + CHAR(10) +
    ' ' + CHAR(13) +
    ' SET @Count= @@ROWCOUNT '

    DECLARE @ParmDefinition NVARCHAR(500);
    SET @ParmDefinition = N'@Count int OUTPUT, @tt [dbo].[ChannelReadingType] READONLY';
    PRINT @SQL

    -- EXECUTE sp_executesql @SQL, N' @tt myTable READONLY', @t;


    EXECUTE sp_executesql @SQL,@ParmDefinition, @tt = @t,@Count = @CountOUT OUTPUT;

    Can't test it fully as the "merge" table isn't provided as a create but that should do what you want it to do

    Perfect I see what was missing now and added that in

    Works very well. thank you very much for your help Ant

     

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

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