【问题标题】:Stored procedure to drop table删除表的存储过程
【发布时间】:2011-05-18 14:38:01
【问题描述】:

我创建了一个存储过程,如果它存在于数据库中,它将删除一个表。使用 EXEC 运行存储过程时,出现以下错误:

消息 203,级别 16,状态 2,程序 sp_DropIfExists,第 13 行名称 'IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'table_name') AND 类型 = (N'U')) 删除表 [table_name]' 无效 标识符。

但是,如果我将生成的 T-SQL 复制并粘贴到管理工作室中,它似乎运行良好。有人可以解释为什么这是无效的吗?修复会很好,但我真的主要关注为什么,但如何会很好!提前致谢。

ALTER PROCEDURE [dbo].[sp_DropIfExists](@tableName VARCHAR(255)) 
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @SQL VARCHAR(MAX);
    SET @SQL = 'IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N''' + @tableName + ''') AND type = (N''U'')) DROP TABLE [' + @tableName + ']'
    PRINT @SQL;
    EXEC @SQL;
END

【问题讨论】:

    标签: sql tsql stored-procedures


    【解决方案1】:

    你可以使用sp_execute

    sp_executesql @SQL
    

    更多信息msdn document link

    【讨论】:

    • 成功了!谢谢您的帮助。你能告诉我为什么它没有按照我的方式工作吗?
    • 因为 t-sql 试图查找 sys.objects 中不存在的表。这是 t-sql/mssql 的工作方式。
    • 所以如果 t-sql 正在寻找不存在的东西,它会给出 Invalid Identifier 的错误,而不是 Invalid object?这对我来说没有多大意义。对不起,如果我读了很多,我只是想弄清楚为什么 EXEC @foo 不起作用但 EXEC sp_execsql @foo 会?
    • 啊,忘记补充了,我不得不将@SQL的数据类型从varchar改为nvarchar。
    • Since EXEC only permits string literals and string variables to be concatenated and not arbitrary expressions, this is not legal: EXEC('UPDATE STATISTICS ' + quotename(@tbl) + ' WITH FULLSCAN') - 来自paragraph from doc about dynamic sql
    【解决方案2】:

    不确定这是否能解决您的问题,但您最好检查一下是不是这样的功能

    CREATE FUNCTION [dbo].[TableExists] 
    (
    @TableName VarChar(100)
    )  
        RETURNS BIT
    AS  
    BEGIN 
        DECLARE @TableExists BIT
    
    IF EXISTS(SELECT name FROM sysobjects a
              WHERE a.name =  @TableName
              AND a.xtype = 'U')
        SET @TableExists = 1
    ELSE
        SET @TableExists = 0
    
    
    RETURN @TableExists
    END
    

    那么你可以如下使用它。

    IF dbo.TableExists('[table_name]') = 1
         DROP TABLE [table_name]
    

    试试这个,如果你仍然遇到同样的错误,请告诉我。

    【讨论】:

    • 我记不太清了,目前没有访问sql-server,但是不允许从函数访问数据库对象。
    • 太棒了!干净又合身。谢谢。
    【解决方案3】:
    --ALTER (if procedure exists)
    
    CREATE PROCEDURE sp_dropifexists (@tableName VARCHAR(255))
    
    AS
    
    BEGIN
    
        DECLARE @SQL VARCHAR(MAX);
    
        SET @SQL = 'IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N''' + @tableName + ''') AND type = (N''U'')) DROP TABLE [' + @tableName + ']'
    
        --if write EXEC @SQL without parentheses  sql says Error: is not a valid identifier
    
        EXEC (@SQL);
    
    END
    
    --test procedure
    
    exec sp_DropIfExists 'table'
    

    【讨论】:

    • 为了提高帖子的质量,请说明您的帖子将如何/为何解决问题。
    【解决方案4】:

    EXEC @SQL 应该是 EXEC (@SQL)。 (不过@maycil的建议也是正确的。)

    事实证明,没有括号 @SQL 的值被解释为要执行的存储过程的名称,而不是脚本。 (我之前不知道,但我做了一个小测试来验证确实如此。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 2011-01-17
      相关资源
      最近更新 更多