检查是否存在临时表,并在创建临时表之前删除它是否存在

时间:2009-03-18 16:34:34

标签: sql-server sql-server-2005 temp-tables alter-table

我使用以下代码检查临时表是否存在,如果存在,则在再次创建之前删除该表。只要我不更改列,它就可以正常工作。如果我稍后添加一列,则会显示错误“无效列”。请让我知道我做错了什么。

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

select company, stepid, fieldid from #Results

--Works fine to this point

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

select company, stepid, fieldid, NewColumn from #Results

--Does not work

16 个答案:

答案 0 :(得分:644)

我无法重现错误。

也许我不理解这个问题。

以下在SQL Server 2005中对我来说很好,在第二个选择结果中出现了额外的“foo”列:

IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO
CREATE TABLE #Results ( Company CHAR(3), StepId TINYINT, FieldId TINYINT )
GO
select company, stepid, fieldid from #Results
GO
ALTER TABLE #Results ADD foo VARCHAR(50) NULL
GO
select company, stepid, fieldid, foo from #Results
GO
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO

答案 1 :(得分:69)

声明应该是

的顺序
  1. 表格的变更声明
  2. GO
  3. 选择陈述。
  4. 中间没有'GO',整个事物将被视为一个单独的脚本,当select语句查找列时,它将无法找到。

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

答案 2 :(得分:48)

而不是dropping并重新创建临时表,您可以truncate并重复使用

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    Truncate TABLE #Results
else
    CREATE TABLE #Results
    (
        Company             CHAR(3),
        StepId              TINYINT,
        FieldId             TINYINT,
    )

如果您使用的是Sql Server 2016Azure Sql Database,请使用以下语法删除临时表并重新创建它。更多信息MSDN

<强>语法

  

DROP TABLE [IF EXISTS] [database_name。 [schema_name]。 |   schema_name。 ] table_name [,... n]

<强>查询:

DROP TABLE IF EXISTS tempdb.dbo.#Results
CREATE TABLE #Results
  (
   Company             CHAR(3),
   StepId              TINYINT,
   FieldId             TINYINT,
  )

答案 3 :(得分:47)

我认为问题是您需要在两者之间添加GO语句以将执行分成批处理。由于第二个删除脚本即IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results没有删除临时表是单个批处理的一部分。你可以试试下面的剧本。

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

GO

select company, stepid, fieldid from #Results

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

GO

select company, stepid, fieldid, NewColumn from #Results

答案 4 :(得分:28)

这对我有用: social.msdn.microsoft.com/Forums/en/transactsql/thread/02c6da90-954d-487d-a823-e24b891ec1b0?prof=required

if exists (
    select  * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') 

   and o.id = object_id(N'tempdb..#tempTable')
)
DROP TABLE #tempTable;

答案 5 :(得分:17)

由于OBJECT_ID对我不起作用,所以只是我方面的一点评论。它总是返回

  

`#tempTable不存在

..即使确实存在。我发现它以不同的名称存储(后缀为_下划线),如下所示:

#tempTable________

这对我很有用:

IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#tempTable%') BEGIN
   DROP TABLE #tempTable;
END;

答案 6 :(得分:10)

pmac72使用GO将查询分解为批次并使用ALTER。

您似乎正在运行相同的批处理,但在更改后运行它两次:DROP ... CREATE ... edit ... DROP ... CREATE ..

也许发布您的完全代码,以便我们可以看到正在发生的事情。

答案 7 :(得分:7)

这对我有用,

IF OBJECT_ID('tempdb.dbo.#tempTable') IS NOT NULL 
DROP TABLE #tempTable; 

在这里tempdb.dbo(dbo就是您的架构,别无所求)。

答案 8 :(得分:6)

当我已经创建临时表时,我经常遇到这个错误;检查SQL语句是否有错误的代码会看到“旧”临时表,并返回后续语句中列数的错误计数,就好像临时表从未被删除一样。

在创建具有较少列的版本后更改临时表中的列数后,删除该表,然后运行查询。

答案 9 :(得分:4)

我最近看到DBA做了类似的事情:

begin try
    drop table #temp
end try

begin catch 
    print 'table does not exist'
end catch 

create table #temp(a int, b int)

答案 10 :(得分:4)

现在,如果您使用的是新版本的SSMS

,则可以使用以下语法
<c:out value="${NameList}" />

答案 11 :(得分:3)

我的代码使用了一个更改的Source表,以及一个必须与这些更改匹配的Destination表。

-- 
-- Sample SQL to update only rows in a "Destination" Table
--  based on only rows that have changed in a "Source" table
--


--
-- Drop and Create a Temp Table to use as the "Source" Table
--
IF OBJECT_ID('tempdb..#tSource') IS NOT NULL drop table #tSource
create table #tSource (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Insert some values into the source
--
Insert #tSource (Col1, Col2, Col3, Col4) Values(1,1,1,1)
Insert #tSource (Col1, Col2, Col3, Col4) Values(2,1,1,2)
Insert #tSource (Col1, Col2, Col3, Col4) Values(3,1,1,3)
Insert #tSource (Col1, Col2, Col3, Col4) Values(4,1,1,4)
Insert #tSource (Col1, Col2, Col3, Col4) Values(5,1,1,5)
Insert #tSource (Col1, Col2, Col3, Col4) Values(6,1,1,6)

--
-- Drop and Create a Temp Table to use as the "Destination" Table
--
IF OBJECT_ID('tempdb..#tDest') IS NOT NULL drop Table #tDest
create table #tDest (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Add all Rows from the Source to the Destination
--
Insert #tDest
Select Col1, Col2, Col3, Col4 from #tSource


--
-- Look at both tables to see that they are the same
--
select *
from #tSource
Select *
from #tDest

--
-- Make some changes to the Source
--
update #tSource
    Set Col3=19
    Where Col1=1
update #tSource
    Set Col3=29
    Where Col1=2
update #tSource
    Set Col2=38
    Where Col1=3
update #tSource
    Set Col2=48
    Where Col1=4

--
-- Look at the Differences
-- Note: Only 4 rows are different. 2 Rows have remained the same.
--
Select Col1, Col2, Col3, Col4
from #tSource
except
Select Col1, Col2, Col3, Col4
from #tDest

--
-- Update only the rows that have changed
-- Note: I am using Col1 like an ID column
--
Update #tDest
    Set Col2=S.Col2,
        Col3=S.Col3,
        Col4=S.Col4
From    (   Select Col1, Col2, Col3, Col4
            from #tSource
            except
            Select Col1, Col2, Col3, Col4
            from #tDest
        ) S
Where #tDest.Col1=S.Col1 

--
-- Look at the tables again to see that
--  the destination table has changed to match
--  the source table.

select *
from #tSource
Select *
from #tDest

--
-- Clean Up
--
drop table #tSource
drop table #tDest

答案 12 :(得分:3)

注意:这也适用于 ## 临时表。

IF OBJECT_ID('tempdb.dbo.##AuditLogTempTable1', 'U') IS NOT NULL
DROP TABLE ##AuditLogTempTable1

注意:此类命令仅适用于 SQL Server 2016 之后。 问问自己 .. 我是否有仍在使用 SQL Server 2012 的客户?

DROP TABLE IF EXISTS ##AuditLogTempTable1

答案 13 :(得分:2)

这可以用一行代码来完成:

IF OBJECT_ID('tempdb..#tempTableName') IS NOT NULL DROP TABLE #tempTableName;   

答案 14 :(得分:0)

是,“无效列”此错误来自“从#Results选择公司,stepid,fieldid,NewColumn”这一行。

运行t-sql有两个阶段,

首先解析,在这个阶段,sql server检查你提交的sql字符串的更正,包括表的列,并优化你的查询以获得最快的retreival。

第二,运行,检索数据。

如果表#Results存在,那么解析过程将检查您指定的列是否有效,否则(表不存在)解析将通过您指定的检查列传递。

答案 15 :(得分:0)

更改临时表中的列时,必须先删除表,然后再次运行查询。 (是的,这很烦人。这就是您要做的。)

我一直认为这是因为“无效列”检查是在运行查询之前由解析器完成的,因此它基于表中被删除之前的列.....这就是pnbs也说。