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

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

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
1832691 次浏览

我不能重复这个错误。

也许我不理解这个问题。

以下代码在SQLServer 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

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

您似乎正在运行相同的批处理,但在更改后运行了两次:删除…创建…编辑…删除…创建…

也许发布你的确切代码,这样我们就可以看到发生了什么。

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

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

声明应该是顺序的

  1. 表的Alter语句
  2. 选择语句。

如果中间没有'GO',整个事情将被视为一个脚本,当选择语句查找该列时,将找不到它。

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

这对我有用: 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;

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

'#temTable不存在

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

#tempTable________

这对我很有效:

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

而不是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,请使用以下语法删除临时表并重新创建它。更多信息在这里MS DNS

语法

DROP TABLE[如果存在][database_name.[schema_name].| schema_name。]table_name[,… n]

查询:

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

我的代码使用更改的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

我最近看到一个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语句来将执行分成批处理。由于第二个删除脚本即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

现在,如果您使用的是SQLServer(2016+)的新版本之一,则可以使用以下语法。

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

是的,“无效列”此错误从“选择公司,stepid,field did,NewCol的#结果”行引发。

运行t-sql有两个阶段,

首先,解析,在这个阶段sql服务器检查你提交的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.dbo(dbo只不过是您的模式)更重要。

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

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

注意:这种类型的命令只适合发布SQLServer 2016。 问问你自己…我有任何客户仍在SQL服务器2012?

DROP TABLE IF EXISTS ##AuditLogTempTable1