0

我写了一个存储过程,我写了一个查询来获取userid. 每个userid. 因此,我正在尝试根据从我以前的选择查询中获得的用户 ID 在循环中运行选择查询。

我正在尝试将此选择查询中的列分配给声明的变量并进一步使用它们。但是我不明白如何将这些分配给变量,因为我遇到了错误

    USE DATABASE1
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    CREATE PROCEDURE [User].[update_client_details] 
    AS
    DECLARE
    @clientdata CURSOR,
    @clientid INT,
    @SQL VARCHAR(2000),
    @uid INT
    @isactive INT,
    @createdDate Date

    BEGIN
        SET @clientdata = CURSOR FOR
        SELECT clientuserid FROM User.queen_client


        OPEN @clientdata
        FETCH NEXT
        FROM @clientdata INTO @clientid
        WHILE @@FETCH_STATUS = 0
        BEGIN
            SET @SQL = N'SELECT @uid=userid, @isactive=isactive, @createdDate=createddate FROM ['+CAST(@clientid AS NVARCHAR(20))+'].User.queen_user';
            EXEC (@SQL)
            IF(@isactive = 1)
            BEGIN
            //do someting//
            END
        END

        CLOSE @clientdata
        DEALLOCATE @clientdata

    END

如果执行存储过程,它将被执行而不是停止。如果我强制停止执行,那么我会收到错误,因为“必须声明标量变量” uid“”

查询我试过的

EXEC sys.sp_executesql N'SELECT @uid=userid, @isactive=isactive, @createdDate=createddate FROM ' +QUOTENAME(@clientid)+'.QueenBase.queen_user', N'@clienid int, @uid int OUTPUT, @createDate date OUTPUT';
4

1 回答 1

2

变量仅在声明它们的范围内持久存在。因此,以下两个批处理都将失败:

DECLARE @I int = 1;
EXEC (N'SELECT @i;');

GO

EXEC (N'DECLARE @I int = 1;');
SELECT @i;

使用动态 SQL 时,不要使用EXEC(@SQL);,使用sp_executesql. 然后,您可以对语句进行参数化。例如:

DECLARE @I int = 1;
EXEC sys.sp_executesql N'SELECT @i;', N'@i int', @i;

这返回1。如果需要给外层SQL返回一个值,作为参数,需要使用OUTPUT参数:

DECLARE @I int = 10;
DECLARE @O int;

EXEC sys.sp_executesql N'SELECT @O = @I / 2;', N'@I int, @O int OUTPUT', @I, @O OUTPUT;

SELECT @O;

这会将值分配给5变量@O(然后选择该变量)。

另外,不要N'...[' + @SomeVariable + N'] ...'用于注入动态值,它不是注入安全的。使用QUOTENAMEN'...' + QUOTENAME(@SomeVariable) + N'...'

附加说明。您需要执行类似操作的事实N'FROM ['+CAST(@clientid AS NVARCHAR(20))+'].User.queen_user'表明存在严重的设计缺陷,但这是另一个话题。

如果您喜欢额外阅读,我会在我的文章动态 SQL 的注意事项中介绍您需要考虑的许多注意事项。


对于您的尝试,它不起作用,因为您对第一个参数(不是文字或变量)使用表达式,然后不传递您定义的任何参数:

DECLARE @SQL nvarchar(MAX) = N'SELECT @uid=userid, @isactive=isactive, @createdDate=createddate FROM ' +QUOTENAME(@clientid)+'.QueenBase.queen_user;';

EXEC sys.sp_executesql @SQL, N'@isactive int OUTPUT, @uid int OUTPUT, @createDate date OUTPUT', @isactive OUTPUT, @uid OUTPUT, @createDate OUTPUT;
于 2020-06-09T11:42:09.850 回答