我应该检查存储过程中是否存在临时表?

Aka*_*ash 7 sql-server stored-procedures sql-server-2012 tempdb sql-server-2014

是否有任何边缘情况建议在存储过程开始时显式检查、删除和创建临时表,而不是仅仅创建它们?

同样,是否存在在存储过程结束时显式删除它们比让 SQL Server 清理它们更可取的情况?

Aar*_*and 7

检查#tbl

在过程开始时检查表是否存在(如果存在则将其删除)不会有什么坏处,但这取决于您希望如何处理该场景,并且在大多数情况下它不可能已经存在无论如何(至少如果我们谈论的是在该存储过程中定义的同一个#temp 表)。

您可以使用以下方法检查表是否存在:

IF OBJECT_ID('tempdb..#tablename') IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

您无法检查 tempdb.sys.tables,因为实际名称是#tablename__________some hex code,并且您不应该使用OBJECT_ID('...') > 0 因为这个潜在问题

当然,也有例外。想到的两个:

  • 如果您调用所有内容#temp, or #t, or #x,那么在调用该过程之前,外部作用域中可能已经存在这样的表。您可以提出一个案例,在这种情况下您应该放弃它并创建新的案例,但您也可以说明这是您想要了解的错误情况 - 所以也许CREATE TABLE #x失败也没关系。

  • 您实际上可能想要使用在外部作用域中创建的 #temp 表,并且仅在尚未在该外部作用域中定义的情况下创建一个。这是可能的,我一直使用这种技术,但通常只有当我想从系统过程中捕获数据时,我自己不能轻易操纵(例如sp_helptext)。所以我可能会这样做:

    CREATE TABLE #x([Text] NVARCHAR(MAX));
    GO
    CREATE PROCEDURE dbo.myhelp @p SYSNAME
    AS
      INSERT #x EXEC sp_helptext @p;
    GO
    EXEC dbo.myhelp N'dbo.myhelp'; -- inception
    GO
    SELECT [Text] FROM #x;
    
    Run Code Online (Sandbox Code Playgroud)

    即使#x在外部定义,这也有效。这是一个糟糕的例子,因为我宁愿使用sys.sql_modules,但我相信你明白了这一点,并且可以想象你如何用自己的程序来做到这一点。

在删除表#tbl;

我认为您是否应该在程序结束时明确删除 #temp 表是非常有争议的,因此将作为主要基于意见的方式关闭;请参阅Paul White撰写的这些出色的博客文章,仔细阅读它们,如果您的所有问题都没有得到解答,请返回并提出一个具体问题: