Sql server 在创建临时表之前,请检查临时表是否存在,并将其删除

Sql server 在创建临时表之前,请检查临时表是否存在,并将其删除,sql-server,sql-server-2005,temp-tables,alter-table,Sql Server,Sql Server 2005,Temp Tables,Alter Table,我使用下面的代码检查临时表是否存在,如果存在,在再次创建之前删除该表。只要我不更改列,它就可以正常工作。如果我稍后添加一列,它将给出一个错误,称为invalid column。请让我知道我做错了什么 IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results CREATE TABLE #Results ( Company CHAR(3), StepId

我使用下面的代码检查临时表是否存在,如果存在,在再次创建之前删除该表。只要我不更改列,它就可以正常工作。如果我稍后添加一列,它将给出一个错误,称为invalid column。请让我知道我做错了什么

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

我无法重现这个错误

也许我不理解这个问题

在SQL Server 2005中,以下操作对我来说很好,第二个select结果中会出现额外的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
正在使用GO将查询分解为多个批次,并使用ALTER

您似乎正在运行同一批,但在更改后运行了两次:DROP。。。创造编辑滴创建


可能会发布您的确切代码,以便我们看到发生了什么。

我通常在创建临时表时遇到此错误;检查SQL语句是否存在错误的代码会看到旧的临时表,并在以后的语句中返回列数的错误计数,就好像临时表从未被删除一样


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

语句的顺序应为

表的Alter语句 去 Select语句。 如果中间没有“GO”,整个过程将被视为一个脚本,当select语句查找该列时,将找不到它

使用“go”,它将把脚本的一部分“一行”作为一个批次,并在“go”进入查询之前执行。

< p>这对我起作用:


只是我这边的一点评论,因为OBJECT_ID不适合我。它总是返回

`诱惑是不存在的

…即使它确实存在。我刚刚发现它是用不同的名称存储的,后面用uu下划线固定,如下所示:

诱人的

这对我来说很有效:

IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#tempTable%') BEGIN
   DROP TABLE #tempTable;
END;
您可以截断并重用临时表,而不是删除并重新创建临时表

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    Truncate TABLE #Results
else
    CREATE TABLE #Results
    (
        Company             CHAR(3),
        StepId              TINYINT,
        FieldId             TINYINT,
    )
如果您使用的是Sql Server 2016或Azure Sql数据库,请使用以下语法删除临时表并重新创建它。更多信息请点击这里

语法

删除表[IF EXISTS][database\u name.[schema\u name]| 模式名称]表名称[,…n]

查询:

我的代码使用更改的源表和必须匹配这些更改的目标表

-- 
-- 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

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

begin try
    drop table #temp
end try

begin catch 
    print 'table does not exist'
end catch 

create table #temp(a int, b int)

我认为问题在于,您需要在中间添加GO语句,以便将执行分为多个批。作为第二个删除脚本,即如果对象_ID'tempdb..Results'不为NULL,则删除表结果不会删除作为单个批处理一部分的临时表。你能试试下面的脚本吗

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

现在,如果您使用的是SQL Server 2016+的一个新版本,则可以使用以下语法

DROP TABLE IF EXISTS schema.yourtable(even temporary tables #...)

是,无效列此错误从“从结果中选择公司、步骤ID、字段ID、新列”行引发

运行t-sql有两个阶段

首先,在解析阶段,sql server会检查您提交的sql字符串(包括表的列)的更正,并优化您的查询以实现最快的检索

第二,运行、检索数据


如果表结果存在,则解析过程将检查您指定的列是否有效,否则表不存在解析将通过您指定的检查列进行传递。

这可以通过一行代码完成:

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

更改临时表中的列时,必须先删除该表,然后才能再次运行查询。是的,很烦人。这就是你必须做的

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

这对我很有效

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

这里tempdb.dbodbo什么都不是,但是您的模式更重要。

注意:这也适用于临时表

i、 e

注意:此类型的命令仅适用于SQL Server 2016之后的版本。 问问你自己。。我是否有任何客户仍然使用SQL Server 2012

DROP TABLE IF EXISTS ##AuditLogTempTable1

您要在哪里添加列?您能发布给您一个错误的确切代码吗?我正在将该列添加到结果表中。如果您复制上面的代码并第一次运行它,您不会得到任何错误。现在,如果在TEMP表中添加一列,并将列添加到SELECT语句,它将表示未找到列或类似的内容。请考虑使用以下模式:开始事务;创建表格结果。。。;下拉表结果;犯罪如果事务成功,表将被删除。如果失败,该表也将消失,因为它是在事务中创建的。在任何情况下:不需要检查表是否已经存在。看起来您只需要转到statem
ents.IF OBJECT_ID'tempdb..Results'不为NULL DROP TABLE Results`CREATE TABLE Results Company CHAR3,StepId INT select Company,StepId from Results现在返回CREATE语句并在末尾添加列fieldid。更改select语句以包含fieldid并运行它。'tempdb..name'正是我所需要的。我在用“dbo.name”,就像个傻瓜。我得到了tempdb部分,但双点是什么?@Conrad.Dean双点是.dbo的缩写。@deutschZuid更准确地说,双点是用户的默认模式,通常是dbo,这不是一个好主意,使dbo成为用户的默认模式,但通常情况下就是这样。您的代码与OP非常不同,因此您的“无法复制”语句毫无意义。我为你感到高兴,你让它以不同的方式工作。注意:如果表是由任何线程创建的,那么代码将检测到它。单个临时表是针对存储的进程的每个线程/调用方单独创建的,这就是为什么名称中会加下划线,以便每个线程/进程都存在不同的副本。只要您使用的是SQL 2005或更高版本,对象ID对于当前线程应该可以正常工作。如果SQL Server 2016和Azure SQL数据库上也存在删除表,则截断/重用方法似乎比删除表更有效。不是这样吗?@prdp如果SQL 2016或Azure存在表,为什么建议删除表?该语法可从SQL 2008开始使用。请参阅答案中的MSDN链接?性能因素?没关系。我现在意识到,SQL Server 2008支持DROP TABLE,但IF EXISTS子句是在2016年引入的。我使用INTO:select*INTO HISTORCOUSERTABLE from dbo.HISTORCOUSERTABLE技术上,如果临时表已经存在,则无法保证表的架构匹配。这很可能是相同的,但您可能已经对表做了其他操作,特别是如果您使用的是结果、产品或客户等通用名称。这是我使用drop/create over truncate的主要原因。这应该被标记为正确答案。并不是SELECT实际上要在create表之前运行,而是它正在被解析并在运行之前抛出一个错误,因为在解析SELECT语句时,有一个名为Results的现有表还没有FieldId列。在那里添加一个GO in将查询分为多个批次,每个批次分别进行分析和运行。我无法相信这与最上面的答案之间的票数差异,这改变了代码太多-没有解释为什么-它作为响应毫无意义。这只是条件表drop的不同语法。这很有趣,但不能解决OP的问题,而且大部分都是多余的。如果只检查对象_IDN'tempdb..Results'不为null,则足以证明该对象已存在。此try语句将捕获在尝试删除表时可能发生的其他错误。此代码假定尝试失败的唯一原因是该表不存在。它可能大部分时间都能用,但我不能保证。如果try语句由于其他原因失败,那么在创建表时会出现错误,因为这掩盖了删除表的真正问题。这是有效的,但不好。如果存在智能和完美的解决方案,我不鼓励采用艰难的方法。而且,尽管OP指定了2005版本,但旧版本不支持try-catch块。另一个问题是使用try/catch vs-logic的思想。您可以在这里看到更多的争论:我使用的是SSMS 17.3,这在关键字“IF”附近给出了不正确的语法。@StingyJack,因为SQL语法与SSMS版本无关,而与SQL Server版本相关。SQL Server 2016提供了IF[NOT]EXISTS子句。您使用的SSMS版本并不重要;tempdb。。在上面的代码中是非常重要的。它需要位于临时表名称之前。仅仅检查对象ID“结果”是不够的。临时表存储在TempDB数据库中。Per Microsoft:TempDB system database是一种全局资源,可供连接到SQL Server实例或连接到SQL数据库的所有用户使用。谢谢,@iCode。这是删除临时表的关键:它必须在tempdb上完成,否则它不会消失。我必须每天都看这个
IF OBJECT_ID('tempdb.dbo.#tempTable') IS NOT NULL 
DROP TABLE #tempTable; 
IF OBJECT_ID('tempdb.dbo.##AuditLogTempTable1', 'U') IS NOT NULL
DROP TABLE ##AuditLogTempTable1
DROP TABLE IF EXISTS ##AuditLogTempTable1