在创建临时表时获取“已经有一个名为的对象”

时间:2010-11-19 05:08:28

标签: sql-server-2008

消息2714,级别16,状态1,过程QOTD,第12行数据库中已存在名为“#tmpID3”的对象。

ALTER PROCEDURE QOTD (@source INT) AS 
BEGIN 
  IF @source = 1 
    SELECT ID INTO #tmpID3 FROM tbl1 
  ELSE 
    SELECT ID INTO #tmpID3 FROM tbl2 

  SELECT ID FROM #tmpID3 

  DROP TABLE #tmpID3 
END 

消息2714,级别16,状态1,过程QOTD,第7行数据库中已存在名为“#tmpID3”的对象。 - jesvin 11月19日5:37

添加此内容我收到错误

6 个答案:

答案 0 :(得分:2)

尝试创建过程时,您看到解析器错误。临时表尚不存在,但解析器认为它确实存在。

看看我对这个问题的回答:There is already an object named '#columntable' in the database.

我最初认为,正如其他已回答您问题的人一样,您会收到此错误,因为您没有在程序结束时明确删除临时表。然而,正如克鲁库塞克在他的评论中首先指出的那样:

  

在过程结束时自动删除本地临时表   他们被创造了

所以我尝试在我的SQL Server 2008实例中创建你的程序并得到同样的错误。

更改过程以使用不同的临时表名称(如下所示)可以避免问题证明在过程结束后删除临时表。

CREATE TABLE tbl1 ( ID INT )
GO
CREATE TABLE tbl2 ( ID INT )
GO
INSERT INTO tbl1(ID) VALUES (1),(2),(3)
INSERT INTO tbl2(ID) VALUES (4),(5),(6)
GO
CREATE PROCEDURE QOTD ( @source INT )
AS 
    SET NOCOUNT ON
    BEGIN 
        IF @source = 1 
            BEGIN
                SELECT  ID INTO #tmpID13 FROM tbl1
                SELECT  ID FROM #tmpID13
            END
        ELSE 
            BEGIN 
                SELECT  ID INTO #tmpID23 FROM tbl2
                SELECT  ID FROM #tmpID23
            END
    END 
GO
EXEC QOTD 1
EXEC QOTD 2

输出:

ID
-----------
1
2
3

ID
-----------
4
5
6

答案 1 :(得分:0)

它已经存在了。如果您要将此表创建为常规运行脚本的一部分,请在开头添加DROP TABLE#tmpID3。

临时表是单线程的(即服务器在创建时不能执行任何其他操作)。如果您经常使用它,请考虑使用表变量。

答案 2 :(得分:0)

启动程序QOTD:

Drop Table #tmpID3

答案 3 :(得分:0)

查看Check If Temporary Table Exists

编辑如何检查临时表并删除它(如果存在)

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

编辑2 看起来2选择进入是相互冲突的。尽管手工创建表格。像

这样的东西
ALTER PROCEDURE QOTD (@source INT) 
AS 
BEGIN 
    IF OBJECT_ID('tempdb..#tmpID3') IS NOT NULL 
    BEGIN 
        DROP TABLE #tmpID3 
    END
    CREATE TABLE #tmpID3(
            ID INT
    )
    IF @source = 1 
    BEGIN
        INSERT INTO #tmpID3 SELECT ID FROM tbl1 
    END
    ELSE 
    BEGIN
        INSERT INTO #tmpID3 SELECT ID FROM tbl2
    END
    SELECT ID FROM #tmpID3 
    DROP TABLE #tmpID3 
END

编辑3 此实例中不需要临时表。一个简单的if会做

这样的东西
ALTER PROCEDURE QOTD (@source INT) 
AS 
BEGIN 
    IF @source = 1 
    BEGIN
        SELECT ID FROM tbl1 
    END
    ELSE 
    BEGIN
        SELECT ID FROM tbl2
    END
END

答案 4 :(得分:0)

对象必须在整个数据库中具有唯一的名称。 SQL Server处理临时表名称的唯一性。但是,如果存在补充对象(例如单独创建的主键),则当两个用户同时尝试创建表时,可能会发生冲突。

你引用的错误信息在其名称中有一个带有ID的对象,所以我猜这是你发现自己的情况.Andy Novick已经写了一个关于这个主题的说明,解释了它为什么会发生并给出一些解决方法。 Check it out

答案 5 :(得分:0)

我有完全相同的问题,请在此处查看我的答案:
There is already an object named '#columntable' in the database

这种情况下的解决方案似乎是首先创建表,然后添加行。这样解析器就不会抱怨(因为这是known parser issue)。

ALTER PROCEDURE QOTD (@source INT) AS 
BEGIN
  -- Create the table without having to declare any column types or sizes
  SELECT TOP 0 ID INTO #tmpID3 FROM tbl1

  -- Prevent IDENTITY_INSERT error
  SET IDENTITY_INSERT #tmpID3 ON

  -- Add the actual rows required
  IF @source = 1 
    INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl1
  ELSE 
    INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl2

  SET IDENTITY_INSERT #tmpID3 OFF

  SELECT ID FROM #tmpID3 

  DROP TABLE #tmpID3 
END