Sql server 如何在sql server中执行动态创建的查询

Sql server 如何在sql server中执行动态创建的查询,sql-server,stored-procedures,sql-server-2016,sql-server-2016-express,Sql Server,Stored Procedures,Sql Server 2016,Sql Server 2016 Express,我编写了一个存储过程,其中我编写了一个查询来获取userid。每个用户ID都有一个单独的数据库。因此,我尝试基于从循环中的上一个select查询获得的这个用户ID运行select查询 我试图将这个select查询中的列分配给声明的变量,并进一步使用它们。但我不知道如何分配这些变量,因为我得到了错误 USE DATABASE1 GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREAT

我编写了一个存储过程,其中我编写了一个查询来获取
userid
。每个
用户ID都有一个单独的数据库。因此,我尝试基于从循环中的上一个select查询获得的这个用户ID运行select查询

我试图将这个select查询中的列分配给声明的变量,并进一步使用它们。但我不知道如何分配这些变量,因为我得到了错误

    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

我试过的问题
变量只存在于声明它们的范围内。因此,以下两个批次都将失败:

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']…'
来注入动态值,这是不安全的。使用
QUOTENAME
N'…'+QUOTENAME(@SomeVariable)+N'…'

补充说明。您需要从['+CAST(@clientid AS NVARCHAR(20))+'].User.queen_User'
执行类似于
N'的操作,这表明存在严重的设计缺陷,但这是另一个主题

如果你喜欢额外阅读,我会在我的文章中介绍很多你需要考虑的因素


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

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;

变量只存在于声明它们的范围内。因此,以下两个批次都将失败:

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']…'
来注入动态值,这是不安全的。使用
QUOTENAME
N'…'+QUOTENAME(@SomeVariable)+N'…'

补充说明。您需要从['+CAST(@clientid AS NVARCHAR(20))+'].User.queen_User'
执行类似于
N'的操作,这表明存在严重的设计缺陷,但这是另一个主题

如果你喜欢额外阅读,我会在我的文章中介绍很多你需要考虑的因素


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

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;

请您帮助我以您所解释的格式重写查询,从['+CAST(@clientid AS NVARCHAR(20))+']中选择@uid=userid、@isactive=isactive、@createdDate=createdDate。User.queen_userWhat failed,@Saisri,或者您不理解的部分,我可以尝试详细说明,我已经尝试了我在上面的问题中发布的查询是的,我在上面的@Saisri中解释过,不要使用
EXEC(@SQL)
,因为你不能参数化它。使用
sys.sp_executesql
,就像我在上面演示的那样。我已经编辑了这个问题,并在标题“我尝试过的查询”下添加了尝试过的查询。你能帮助我按照你解释的格式重新编写查询吗?选择@uid=userid,@isactive=isactive,@createdDate=createdDate FROM['+CAST(@clientid AS NVARCHAR(20))+'].User.queen_userWhat failed what you try,@Saisri,或您不理解的部分,我可以尝试详细说明,我已经尝试了我在上面问题中发布的查询是的,我在上面的@Saisri中解释过,不要使用
EXEC(@SQL)
,因为您无法参数化它。使用
sys.sp_executesql
,就像我在上面演示的那样。我已经编辑了这个问题,并在“我尝试过的查询”标题下添加了尝试过的查询