【问题标题】:Subtleties of SQL Server VariablesSQL Server 变量的微妙之处
【发布时间】:2012-07-13 12:00:23
【问题描述】:

我有以下 SQL Server 存储过程:

CREATE PROCEDURE ispsDcOhcAgg @TmpTableName NVARCHAR(50), @ListItem NVARCHAR(50) 
AS
IF EXISTS (SELECT name 
           FROM sys.tables 
           WHERE name = @TmpTableName) 
DROP TABLE @TmpTableName; -- This will not work.
GO

这显然行不通(请参阅上面代码段中的评论)。我发现解决这个问题的唯一(也是非常丑陋的)方法是执行以下操作

CREATE PROCEDURE ispsDcOhcAgg @TmpTableName NVARCHAR(50), @ListItem NVARCHAR(50) 
AS
DECLARE @SQL NVARCHAR(4000) 
SET @SQL = N'IF EXISTS (SELECT name ' +
           N'FROM sys.tables ' + 
           N'WHERE name = N' + N'''' + @TmpTableName + N''') ' + 
           N'DROP TABLE ' + @TmpTableName + N';'
EXEC sp_executesql @SQL;
GO

这真的很臭,对于大型存储过程来说,这太可怕了!

还有其他我不知道的方法吗?

感谢您的宝贵时间。

【问题讨论】:

  • 不行,没有别的办法,只能使用动态 SQL 来实现。
  • if exists 部分可以作为带有变量的内联语句正常工作,它只是一个where 子句,如果满足条件,则需要动态执行drop

标签: tsql variables stored-procedures sql-server-2008-r2


【解决方案1】:

不,如果你想像这样动态使用表名,你需要使用动态SQL。

因此,您应该确保自己不会面临令人讨厌的 SQL 注入风险!

试试这样的:

SET @SQL = 'IF EXISTS (SELECT name ' +
           N'FROM sys.tables ' + 
           N'WHERE name = @TableName) ' + 
           N'DROP TABLE ' + QUOTENAME(@TmpTableName) + ';'

EXEC sp_executesql @SQL, N'@TableName sysname', @TmpTableName;

【讨论】:

    【解决方案2】:

    不,如果要在运行时确定要删除的表,除了动态 SQL 之外别无选择。

    有一个稍微不那么丑陋的方法:你只对需要动态的命令使用动态 SQL(DROP 命令):

    DECLARE @SQL NVARCHAR(100) 
    IF EXISTS (SELECT name 
           FROM sys.tables 
           WHERE name = @TmpTableName) 
    BEGIN
        SET @SQL = N'DROP TABLE ' + @TmpTableName + N';'
        EXEC sp_executesql @SQL;
    END
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 2022-01-09
      • 2013-08-12
      相关资源
      最近更新 更多