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
,就像我在上面演示的那样。我已经编辑了这个问题,并在“我尝试过的查询”标题下添加了尝试过的查询