是否可以动态地向sp_ExecuteSql提供参数列表?
在sp_ExecuteSql中,查询和参数定义是字符串。我们可以为这些变量使用字符串变量,并传入我们想要执行的任何查询和参数定义。但是,在为参数赋值时,我们似乎无法使用字符串或字符串变量作为参数名称。
例如:
DECLARE @SelectedUserName NVARCHAR(255) ,
@SelectedJobTitle NVARCHAR(255);
SET @SelectedUserName = N'TEST%';
SET @SelectedJobTitle = N'%Developer%';
DECLARE @sql NVARCHAR(MAX) ,
@paramdefs NVARCHAR(1000);
SET @sql = N'select * from Users where Name LIKE @UserName '
+ N'and JobTitle LIKE @JobTitle;'
SET @paramdefs = N'@UserName nvarchar(255), @JobTitle nvarchar(255)';
EXEC sp_ExecuteSql @sql, @paramdefs, @UserName = @SelectedUserName,
@JobTitle = @SelectedJobTitle;
查询@sql和参数定义@paramdefs可以作为字符串变量动态地传递给sp_ExecuteSql。但是,在我看来,在为参数赋值时,我们无法动态分配,并且必须始终提前知道参数的数量及其名称。在我的例子中注意我如何动态地声明参数@UserName和@JobTitle并将该声明作为字符串变量传递,但是当我想设置它时我必须显式指定参数名称。有没有解决这个限制的方法?
我希望能够动态声明参数并动态分配它们。类似的东西:
EXEC sp_ExecuteSql @sql, @paramdefs,
N'@UserName = @SelectedUserName, @JobTitle = @SelectedJobTitle';
请注意,这实际上并不起作用,但说明了我想要发生的事情。如果这种事情有效,那么我可以使用具有不同名称的不同数量的参数传递不同的查询。整个过程都是动态的,我不必事先知道参数的名称或数量。
答案 0 :(得分:3)
你试图在抽象中工作得太高。
任意参数需要动态SQL,a.k.a。通过字符串构建SQL,然后使整个参数点无法实现。
相反,这应该作为调用代码中的参数来处理,例如C#,将允许您在字符串中使用任何SQL语句,应用任意参数的数量,并执行它。
答案 1 :(得分:3)
您可以通过使用表值参数作为唯一参数来做到这一点:
DECLARE @YourQuery NVARCHAR(MAX0 = '<your dynamic query>'
CREATE TYPE dbo.SqlVariantTable AS TABLE
(
[Name] VARCHAR(255),
Type VARCHAR(255),
Value SQL_VARIANT
)
DECLARE @Table SqlVariantTable;
-- Insert your dynamic parameters here:
INSERT INTO @Table
VALUES
('Parameter1', 'VARCHAR(255)', 'some value'),
('Parameter2', 'INT', 3),
DECLARE @ParameterAssignment NVARCHAR(MAX)
SELECT @ParameterAssignment = ISNULL(@ParameterAssignment + ';','') + 'DECLARE ' + Name + ' ' + Type + ' = (SELECT CAST(Value AS ' + Type + ') FROM @p1 WHERE Name = ''' + Name + ''')'
FROM @Table
SET @YourQuery = @ParameterAssignment + ';' + @YourQuery
EXEC SP_EXECUTESQL @YourQuery, N'@p1 SqlVariantTable READONLY', @Table
现在,您可以简单地将参数插入@Table变量中,它们将以原始名称和类型出现在SP_EXECUTESQL中执行的查询中。仅使您不使用VARCHAR(MAX)或NVARCHAR(MAX)变量类型,因为SQL_VARIANT不支持它们。使用(例如)VARCHAR(4000)
答案 2 :(得分:2)
虽然这不能回答我的问题,但我认为它对类似情况下的其他人可能有用。我发现了以下内容:
如果您有一定数量的参数但不知道它们的名称,则可以按位置而不是名称传递参数值。以下内容适用:
exec sp_ExecuteSql
@sql,
@paramdefs,
@SelectedUserName, @SelectedJobTitle;
或
exec sp_ExecuteSql
@sql,
@paramdefs,
N'TEST%', N'%Developer%';
答案 3 :(得分:2)
我也考虑过这一点,找不到比这更好的东西了:
exec sp_executesql
@stmt = N'blah blah WHERE C1 = @p1 AND C2 = @p2'
@params = '@p1 int, @p2 int, @p3 int, @p4 int...'
@p1 = @p1, @p2 = @p2, @p3 = @p3, @p4 = @p4, ...
请注意,在@stmt中仅使用了2个参数,但是有许多已定义和提供的参数。您必须给定可以使用的参数数量,但是只能使用所需的参数来构建查询语句。 @params参数中的定义与稍后提供的参数匹配,但是在语句中不存在,因此基本上可以忽略它们。然后,您可以动态填充这些参数。
它不是100%通用的,但不少于60%通用的。
答案 4 :(得分:0)
请试一试。
声明@UName varchar(50)
声明@Job varchar(50)
设置@UName ='TEST%'
设置@Job ='%Developer%'
exec sp_ExecuteSql @sql,@ paramdefs,@ UserName = @UName,@ JobTitle = @Job;
愿这对你有所帮助。
实施例
DECLARE @IntVariable int;
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
/ *一次构建SQL字符串。* /
SET @SQLString = N'SELECT BusinessEntityID,NationalIDNumber,JobTitle,LoginID 来自AdventureWorks2012.HumanResources.Employee WHERE BusinessEntityID = @BusinessEntityID';
SET @ParmDefinition = N'@ BusinessEntityID tinyint';
/ *使用第一个参数值执行字符串。 * /
SET @IntVariable = 197;
执行sp_executesql @SQLString,@ ParmDefinition, @BusinessEntityID = @IntVariable;
/ *使用第二个参数值执行相同的字符串。 * /
SET @IntVariable = 109;
执行sp_executesql @SQLString,@ ParmDefinition, @BusinessEntityID = @IntVariable;
对于动态,你必须传递这样的东西
执行sp_executesql N'Select *来自Admin WHERE ID = @ID和FirstName = @FName',N'@ ID tinyint,@ FName varchar(250)',@ ID = 2,@ FName ='admin'; < / p>