【问题标题】:Repeatedly creating and dropping temp table of the same name重复创建和删除同名临时表
【发布时间】:2014-12-30 11:59:15
【问题描述】:

我了解调试器在做什么,但我并不完全同意,因为以下内容应该可以正常工作:

IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );

IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );

错误信息如下:

Msg 2714, Level 16, State 1, Line 15 已经有一个对象名为 数据库中的“#extract”。

请注意 - 我在整个脚本中声明了我需要的变量,即脚本是存储过程的一部分,并且变量应该具有整个过程的范围。

【问题讨论】:

  • 如果要在整个过程中使用相同的临时表结构,为什么不使用TRUNCATE TABLE 而不是DROP 后跟CREATE
  • @alroc 公平的建议。不使用GOTRUNCATE 是否可以?
  • 这个问题没有意义。我建议您使用TRUNCATE,但您问是否可以在不使用TRUNCATE 的情况下使用TRUNCATE?我的意思是:创建表一次。如果您需要清空并重新填充它,请使用 TRUNCATE TABLE 而不是 DROPping 来重新创建它。
  • 为什么不使用唯一的临时表名称?是否明确需要将它们都命名为#Extract?此外,您正在使用术语“脚本”和“程序”。如果此 SQL 在存储过程内部,则需要知道这一点才能回答问题,因为 GO 不能在过程内部使用。

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

只要使用Go语句,保证当前批处理执行的范围

:setvar TotalScope 10
IF OBJECT_ID('tempdb..#extract') IS NOT NULL

 DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );


//what ever Operation what you want to Perform on `#extract`

 GO


// So here `#extract` is not available then You can Create New One Now
select $(TotalScope)


 IF OBJECT_ID('tempdb..#extract') IS NOT NULL

 DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );


   // Again Do what ever Operation what you want to Perform on `#extract`


 GO

  // So here `#extract` is not available then You can Create New One Now

编辑

您不能在批处理执行之间使用这种类型的@TotalScope 变量,但您需要打开SQL CMD MODE,然后您可以使用我更新的上述代码

For Reference

注意:正如 alroc 所建议的那样,如果你截断表而不是创建新表一,它会更好

【讨论】:

  • 如果我声明了希望在整个脚本范围内的变量怎么办?
  • 这里GO有什么用。为什么当语句在不同批次中时问题得到解决。甚至不需要Begin and End,只需要GO
  • @NoDisplayName - GO 确实消除了错误消息,所以我认为您的批评有点苛刻。但我希望在整个过程中都有可用的变量,所以 GO 确实与该要求发生冲突(我的错是不包括在 OP 中)
  • @whytheq - 哥们在这里没有批评。只是要求解释,以便我能理解发生了什么:)。对以后的读者很有帮助
  • @NoDisplayName 现已更新
【解决方案2】:

临时表不会在查询结束时自动删除,只有当当前与数据库的连接被删除或您使用 DROP TABLE #tablename 显式删除它们时

已编辑:只要您在循环中运行它,它就会作为 SP 工作,这对我有用,试试这个:

IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;

CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );

IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;

中间没有“GO”,整个事情将被视为一个单独的脚本,所以当 CREATE 语句尝试创建一个同名的表时,在之前删除它之后,它表明它已经存在,因为它是一个单一的脚本,其中同一表的 DROP 和 CREATE 不能同时进行,因为 DROP 在执行语句之前不会完全生效,在这种情况下,它是一个大语句,会发生 CREATE 错误

使用 'GO' ,它会将脚本中直到 'GO' 的部分视为一个批处理,并将在进入 'GO' 之后的查询之前执行。

所以我再次建议:

IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );
GO
IF OBJECT_ID('TEMPDB..#extract') IS NOT NULL DROP TABLE #extract;
CREATE TABLE #extract(
    x                   VARCHAR(100),
    NumX_Rank           NUMERIC(18,2),  
    NumG_Rank           NUMERIC(18,2)
    );

【讨论】:

  • 谢谢 - 我在 OP 中添加了一些额外的细节。我有想要在整个脚本中作用域的变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多