SQL Server中的临时表导致“已存在名为的对象”错误

dddzy1tm  于 2022-11-21  发布在  SQL Server
关注(0)|答案(6)|浏览(784)

我在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“的对象”。有人能告诉我为什么会得到这个错误吗?

xe55xuns

xe55xuns1#

您正在删除它,然后创建它,然后尝试使用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语句的表

wgeznvg7

wgeznvg72#

我通常将这些行放在存储过程的开头,然后放在结尾。
这是对#temp表的“存在”检查。

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

完整示例:
(Note缺少任何“SELECT INTO”语句)

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 3 LEFT(name, 128) FROM sysobjects       

    INSERT INTO #MyCoolTempTable (MyValue)
        SELECT TOP 3 LEFT(name, 128) FROM sysobjects ORDER BY NEWID()

    ALTER TABLE #MyCoolTempTable 
        ADD YetAnotherColumn VARCHAR(128) NOT NULL DEFAULT 'DefaultValueNeededForTheAlterStatement'

    INSERT INTO #MyCoolTempTable (MyValue, YetAnotherColumn)
       SELECT TOP 3 LEFT(name, 128) , 'AfterTheAlter' FROM sysobjects ORDER BY NEWID()

    SELECT MyCoolTempTableKey, MyValue, YetAnotherColumn FROM #MyCoolTempTable


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

    SET NOCOUNT OFF;
END
GO

输出样本(~ S):
另外,请看我在这里的回答(关于“#temp表的作用域是什么”):https://stackoverflow.com/a/20105766/214977

olmpazwi

olmpazwi3#

必须按如下方式修改查询

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

避免使用insert into因为如果您使用insert into,那么将来如果您想通过添加一个新列来修改临时表,该列可以在某个进程(而不是与insert沿着)之后填充。此时,您需要以相同的方式重新修改和设计它。

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

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

优点不需要Drop语句,因为这与变量类似。作用域在执行后立即结束。

f1tvaqid

f1tvaqid4#

有时候,您可能会犯一些愚蠢的错误,例如在同一个.sql文件(在同一个工作区/选项卡中)上编写插入查询,因此,一旦您在上面编写了创建查询并已执行的位置执行插入查询,它将再次与插入查询沿着开始执行。
这就是为什么我们获取的对象名(表名)已经存在的原因,因为它是第二次执行。
因此,请转到一个单独的选项卡,编写插入或删除查询或您要执行的任何查询。
或者在同一工作区中的所有查询之前使用注解行,如

CREATE -- …
-- Insert query
INSERT INTO -- …
7gyucuyw

7gyucuyw5#

我发现我也有同样的问题:

DROP TABLE IF EXISTS #MyTempTable
CREATE TABLE #MyTempTable (
    MyTempTableID INT,
    OtherColID INT
);

但我可以通过使用GO分隔语句来解决这个问题。

DROP TABLE IF EXISTS #MyTempTable
GO
CREATE TABLE #MyTempTable (
    MyTempTableID INT,
    OtherColID INT
);
pcrecxhr

pcrecxhr6#

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

相关问题