存储过程,其中包含表名作为参数

时间:2013-06-15 00:03:38

标签: sql-server stored-procedures dynamic-sql

我试图更新一个工作正常但不需要使用sp_executesql的存储过程。我现在想要将表名作为参数,因为我有许多具有相同结构的表,并且不希望为每个表创建新的存储过程。

我遇到的问题是这个版本似乎需要所有参数,而前一个版本接受任意数量的参数。例如,如果我删除所有WHERE参数并且只有@TableName参数,它可以正常工作。我试过寻找一个例子,但我找不到这样的东西。解析表名的所有示例都只有该参数。

CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = 'SELECT * FROM [' + @TableName + ']' + 
    'WHERE ([Square] LIKE ''' + @Square + ''' OR ''' + @Square + ''' IS NULL)' + 
    'AND ([Location] = ''' + @Location + ''' OR ''' + @Location + ''' IS NULL)' +
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql
END

建议请。

1 个答案:

答案 0 :(得分:10)

建议1: 使用QUOTENAME()来处理正确的表名转义。

建议2:您正在将参数的值插入@sql。不要那样做。相反,你应该使用pameterized sql。

建议3:通过有条件地构建查询的WHERE子句来消除OR逻辑。

 CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = N'SELECT * FROM ' + QUOTENAME(@TableName ) + 
    ' WHERE 1=1 '
    IF  @Square IS NOT NULL
      SET @sql = @sql + ' AND ([Square] LIKE   @Square )'  -- still patameterized
   IF @Location IS NOT NULL
      SET @sql = @sql + N'  AND ([Location] = @Loc )'
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql, N'@Square nvarchar(100), @Loc nvarchar(100)...', @square=@square, @loc=@location  -- the param names can be the same or different, sp_executesql has it's own scope.
END

除了普通的sql之外,Sp_executesql还可以执行参数化的sql。它是客户端库用于执行参数化代码的底层系统存储过程。例如,如果添加了任何参数,System.Data.SqlClient.SqlCommand将调用sp_executesql。这是非典型的,因为它接受可变数量的参数。 sp_executesql上的msdn文档提供了一些很好的信息,但不清楚。在SQL事件探查器中捕获活动是查看sp_executesql的最简单方法。