【问题标题】:Stored procedure with table name as parameter amongst others以表名作为参数的存储过程
【发布时间】:2013-06-11 17:15:46
【问题描述】:

我尝试更新一个运行良好的存储过程,而无需使用 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

请提出建议。

【问题讨论】:

  • 检查@sql 的值并确保它可以执行。你能通过硬编码表名来构建一个 sql 字符串并让 Where 子句起作用吗?
  • 尝试在WHERE 和AND 之前添加一个空格,你要连接的没有空格。

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


【解决方案1】:

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

建议2:您将参数的值插入@sql。不要那样做。相反,您应该使用参数化的 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

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

【讨论】:

  • 太棒了。感谢@StrayCatDBA。多年来我一直使用简单的 sql,但我才刚刚开始使用 sp,而且我仍在为它们苦苦挣扎。我明天会继续工作,因为我今天很忙。我可以假设使用此方法,那么在调用此过程时我可以不包含任何参数或包含任意数量的参数吗?
  • 抱歉,能否请您解释一下 EXEC 行? IE。为什么要声明。
  • 成功了,谢谢。除了,我仍然看不到 exec 行的作用,就好像我在其中包含参数一样,我收到一个错误:Procedure 需要类型为“ntext/nchar/nvarchar”的参数“@parameters”。
  • 确保您使用 Nvarchar 的参数而不是 varchars。即 N'...' 而不是 '...'
  • 感谢您的所有帮助@StrayCatDBA,非常感谢。
猜你喜欢
  • 2011-09-30
  • 1970-01-01
  • 2016-08-23
  • 2022-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-02
  • 2014-01-01
相关资源
最近更新 更多