在动态SQL中设置变量

时间:2018-03-28 10:22:28

标签: sql-server

我已经创建了一个存储过程,我计划将表名传递给允许我从控制表中收集URN,并通过将现有的URN(int identity)添加到存储的表中将其分配给传递的表控制表中的值。

这是存储过程:

ALTER PROCEDURE [dbo].[System_IndividualURN_Processing]
    @TableName Varchar(100)

AS Begin

DECLARE @iCounter           INT,
        @NextCustomerURN    INT,
        @TSQL               Varchar(Max)

SET @TSQL = '
        SET '+@iCounter+' = COUNT(*)
        FROM  dbo.' +@TableName+'
        '

EXEC @TSQL

PRINT @iCounter

SELECT @NextCustomerURN = URN --select URN
FROM   dbo.System_NextNumbers A
where [Type] = 'NextCustomerURN'

UPDATE A
SET URN = URN + @iCounter
FROM   dbo.System_NextNumbers A
where [Type] = 'NextCustomerURN'

SET @TSQL = '

        UPDATE A
        SET           IndividualURN = URN + CONVERT(INT, @NextCustomerURN)-1
        FROM  dbo.'+@TableName+' A
        '
EXEC @TSQL

End

执行时我收到以下错误:

Msg 245,Level 16,State 1,Procedure dbo.System_IndividualURN_Processing,Line 12 [Batch Start line 2] 转换varchar值时转换失败         SET'到数据类型int。

我已将其缩小到以下声明:

SET @TSQL = '
        SET '+@iCounter+' = COUNT(*)
        FROM  dbo.' +@TableName+'
    '

建议不可能以这种方式使用动态SQL设置变量,或者语法中缺少某些内容。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

您无法访问在当前批次之外声明的变量(除非它作为参数传递)。因此,尝试在@iCounter内设置EXEC将始终失败。

您可以切换到临时表,可以在EXEC内访问该表。只需确保在外面创建它,否则您将无法在EXEC之外选择结果。

DECLARE @iCounter INT
DECLARE @TSQL Varchar(Max)

IF OBJECT_ID('tempdb..#CountTotals') IS NOT NULL
    DROP TABLE #CountTotals

CREATE TABLE #CountTotals (
    TableName VARCHAR(100),
    TotalRows INT)

SET @TSQL = '

    INSERT INTO #CountTotals (
        TableName,
        TotalRows)
    SELECT
        TableName = ''' + @TableName + ''',
        TotalRows = COUNT(1)
    FROM
        dbo.' + @TableName

EXEC (@TSQL)

SET @iCounter = (SELECT C.TotalRows FROM #CountTotals AS C WHERE C.TableName = @TableName)

当您尝试在其他动态SQL上使用@NextCustomerURN时,会发生同样的事情。您必须将@NextCustomerURN值呈现为字符串才能正确使用它。

SET @TSQL = '

        UPDATE A
        SET           IndividualURN = URN + CONVERT(INT, ''' + CONVERT(VARCHAR(200), @NextCustomerURN) + ''')-1
        FROM  dbo.'+@TableName+' A
        '
EXEC @TSQL

答案 1 :(得分:0)

您需要使用sys.sp_executesql

您可以参数。 @TSQL参数需要NVARCHAR数据类型

这是与你想要的相似的例子。

DECLARE @tableName          NVARCHAR(50) = 'Test';
DECLARE @iCounter           INT,
        @TSQL               NVarchar(Max);

CREATE TABLE dbo.Test(Id INT);
INSERT INTO dbo.Test(Id) VALUES(1);

SET @TSQL =
    N'
        SET @iCounter = (SELECT COUNT(*) FROM dbo.'+@tableName +' )
    '
--PRINT @TSQL; 
--you pass the @iCounter as an OUTPUT parameter
EXEC sys.sp_executesql @TSQL, N'@iCounter INT OUTPUT', @iCounter OUTPUT
SELECT @iCounter