SQL Server 中的临时表导致“已经有一个名为”的对象错误

Posted

技术标签:

【中文标题】SQL Server 中的临时表导致“已经有一个名为”的对象错误【英文标题】:Temporary table in SQL server causing ' There is already an object named' error 【发布时间】:2013-08-21 16:32:37 【问题描述】:

我在 SQL Server 中遇到以下问题,我有一些看起来像这样的代码:

DROP TABLE #TMPGUARDIAN
CREATE TABLE #TMPGUARDIAN(
LAST_NAME NVARCHAR(30),
FRST_NAME NVARCHAR(30))  

SELECT LAST_NAME,FRST_NAME INTO #TMPGUARDIAN  FROM TBL_PEOPLE

当我这样做时,我得到一个错误'数据库中已经有一个名为'#TMPGUARDIAN'的对象'。谁能告诉我为什么会出现这个错误?

【问题讨论】:

【参考方案1】:

您正在删除它,然后创建它,然后尝试使用SELECT INTO 再次创建它。改为:

DROP TABLE #TMPGUARDIAN
CREATE TABLE #TMPGUARDIAN(
LAST_NAME NVARCHAR(30),
FRST_NAME NVARCHAR(30))  

INSERT INTO #TMPGUARDIAN 
SELECT LAST_NAME,FRST_NAME  
FROM TBL_PEOPLE

在 MS SQL Server 中,您可以使用 SELECT INTO 创建没有 CREATE TABLE 语句的表

【讨论】:

我使用的是 SELECT INTO 而不是 CREATE TABLE,但仍然收到错误 There is already an object named '#MyTempTable' in the database. @naz786 在这种情况下它必须已经存在,对于临时表,您可能会发现在创建之前包含 DROP TABLE IF EXISTS #yourTable; 会很有帮助。 是的,我试过了,但是没有用。由于这个 SELECT INTO 对我不起作用,我不得不编写两个查询:一个用于创建表,另一个用于插入到表中。这对我来说是一种解决方法。不管怎样,谢谢你。 :)【参考方案2】:

我通常将这些行放在存储过程的开头,然后放在结尾。

这是对#temp 表的“存在”检查。

IF OBJECT_ID('tempdb..#MyCoolTempTable') IS NOT NULL
begin
        drop table #MyCoolTempTable
end

完整示例:

CREATE PROCEDURE [dbo].[uspTempTableSuperSafeExample]
AS
BEGIN
    SET NOCOUNT ON;


    IF OBJECT_ID('tempdb..#MyCoolTempTable') IS NOT NULL
    BEGIN
            DROP TABLE #MyCoolTempTable
    END


    CREATE TABLE #MyCoolTempTable (
        MyCoolTempTableKey INT IDENTITY(1,1),
        MyValue VARCHAR(128)
    )  

    INSERT INTO #MyCoolTempTable (MyValue)
        SELECT LEFT(@@VERSION, 128)
        UNION ALL SELECT TOP 10 LEFT(name, 128) from sysobjects

    SELECT MyCoolTempTableKey, MyValue FROM #MyCoolTempTable


    IF OBJECT_ID('tempdb..#MyCoolTempTable') IS NOT NULL
    BEGIN
            DROP TABLE #MyCoolTempTable
    END


    SET NOCOUNT OFF;
END
GO

【讨论】:

就我而言,这似乎还不够。我在同一个选择相同的“SELECT MyField INTO #TempTable”中写了两次这一事实足以导致编译错误。两个 select into 不能同时命中,因为它们位于 IF THEN ELSE 的不同分支中:尽管如此,我不能写两次相同的 SELECT INTO 不要使用 Select-Into。它是一个“捷径”。创建#tempTable,使用“Insert Into #MyTemp Select Col1, Col2 from dbo.MyTable”语法。 IF OBJECT_ID('tempdb..#TMPGUARDIAN') IS NOT NULL begin drop table #TMPGUARDIAN end Select LAST_NAME,FRST_NAME INTO #TMPGUARDIAN from TBL_PEOPLE SELECT * FROM #TMPGUARDIAN Amresh,在这种情况下不起作用 - 正如其他地方所指出的那样,即使 select-into 位于互斥分支中,仅将它们中的两个放入同一个临时表的事实就会导致编译器错误。显然,这是词法分析器的缺陷。【参考方案3】:

你必须像这样修改查询

CREATE TABLE #TMPGUARDIAN(
LAST_NAME NVARCHAR(30),
FRST_NAME NVARCHAR(30))  

INSERT INTO #TMPGUARDIAN(FRST_NAME,LAST_NAME)
SELECT LAST_NAME,FRST_NAME  FROM TBL_PEOPLE

-- 为清除所有临时表创建最后一个会话。总是落到最后。在您的情况下,有时,如果表不存在,则在您尝试删除时可能会发生错误。

DROP TABLE #TMPGUARDIAN

避免使用插入 因为如果您将来使用插入,那么如果您想通过添加一个新列来修改临时表,该列可以在某些过程之后填充(而不是与插入一起)。到时候,你需要用同样的方式返工和设计。

使用表变量http://odetocode.com/articles/365.aspx

declare @userData TABLE(
 LAST_NAME NVARCHAR(30),
    FRST_NAME NVARCHAR(30)
)

优势 不需要 Drop 语句,因为这类似于变量。范围在执行后立即结束。

【讨论】:

【参考方案4】:

有时您可能会犯一些愚蠢的错误,例如在同一个 .sql 文件(在同一个工作区/选项卡中)编写插入查询,所以一旦您执行插入查询,其中创建查询刚刚在上面编写并且已经执行,它会再次执行与插入查询一起开始执行。

这就是我们获取对象名(表名)已经存在的原因,因为它是第二次执行。

所以转到一个单独的选项卡来编写插入或删除或您将要执行的任何查询。

或者在同一工作区中的所有查询之前使用注释行,例如

CREATE -- …
-- Insert query
INSERT INTO -- …

【讨论】:

【参考方案5】:

在 Azure 数据仓库中有时也会发生这种情况,因为为用户会话创建了临时表。我通过重新连接数据库解决了同样的问题,

【讨论】:

因为断开连接删除了临时表,所以“修复”了它。这与原始问题无关。

以上是关于SQL Server 中的临时表导致“已经有一个名为”的对象错误的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2016 - 临时表 - 如何识别用户

SQL Server SELECT INTO 和临时表阻塞

sql server中的临时表表变量和公用表表达式

sql server中的用户临时表和全局临时表的区别

sql server 临时表占用硬盘吗?

SQL Server 中的临时表和表变量有啥区别?