我正在使用以下代码检查临时表是否存在,并在再次创建之前删除该表(如果存在)。只要我不更改列,它就可以正常工作。如果我稍后添加一列,它会给出“无效列”的错误。请让我知道我做错了什么。
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
BEGIN TRANSACTION; CREATE TABLE #Results; ...; DROP TABLE #Results; COMMIT
。如果事务成功,该表将被删除。如果失败,表也会消失(因为它是在事务中创建的)。在任何情况下:无需检查表是否已经存在。
我无法重现该错误。
也许我不明白这个问题。
以下在 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
声明应该是有序的
表 GO Select 语句的 Alter 语句。
如果中间没有“GO”,整个事情将被视为一个单独的脚本,当 select 语句查找该列时,它不会被找到。
使用 'GO' ,它会将脚本中直到 'GO' 的部分视为一个批处理,并将在进入 'GO' 之后的查询之前执行。
除了 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 2016
或 Azure Sql Database
,则使用以下语法删除临时表并重新创建它。更多信息在这里MSDN
句法
删除表 [如果存在] [数据库名称。 [模式名称]。 |模式名称。 ] 表名 [ ,...n ]
询问:
DROP TABLE IF EXISTS #Results
CREATE TABLE #Results
(
Company CHAR(3),
StepId TINYINT,
FieldId TINYINT,
)
truncate/reuse
方法也比 Sql Server 2016
和 Azure Sql Database
上的 DROP TABLE IF EXISTS
更有效。不是这样吗?
DROP TABLE IF Exists
用于 SQL 2016 或 Azure?该语法从 SQL 2008 开始可用。请参阅答案中的 MSDN 链接?性能因素?
DROP TABLE
,但 IF EXISTS
子句是在 2016 年引入的。
INTO
:select * INTO #HistoricoUserTable from dbo.HistoricoUser
#Results
、#Products
或 #Customers
之类的通用名称时。这是我会使用 drop/create 而不是截断的主要原因。
我认为问题是您需要在两者之间添加 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
tempdb..
非常重要。它需要在您的临时表名称之前。仅检查 OBJECT_ID('#Results')
是不够的。临时表存储在 TempDB 数据库中。根据 Microsoft:TempDB 系统数据库是一个全局资源,可供连接到 SQL Server 实例或连接到 SQL 数据库的所有用户使用
tempdb
上完成,否则它不会消失。
这可以通过一行代码来完成:
IF OBJECT_ID('tempdb..#tempTableName') IS NOT NULL DROP TABLE #tempTableName;
if exists (
select * from tempdb.dbo.sysobjects o
where o.xtype in ('U')
and o.id = object_id(N'tempdb..#tempTable')
)
DROP TABLE #tempTable;
现在,如果您使用的是 SQL Server (2016+) 的新版本之一,则可以使用以下语法。
DROP TABLE IF EXISTS schema.yourtable(even temporary tables #...)
Incorrect syntax near the keyword 'IF'.
IF [NOT] EXISTS
子句可从 SQL Server 2016 获得。您使用的 SSMS 版本无关紧要。
由于 OBJECT_ID
对我不起作用,因此只是我的一点评论。它总是返回
`#tempTable 不存在
..即使它确实存在。我刚刚发现它以不同的名称存储(后缀为 _
下划线),如下所示:
#tempTable________
这对我很有效:
IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#tempTable%') BEGIN
DROP TABLE #tempTable;
END;
这对我有用,
IF OBJECT_ID('tempdb.dbo.#tempTable') IS NOT NULL
DROP TABLE #tempTable;
这里 tempdb.dbo(dbo is nothing but your schema) 更重要。
pmac72 正在使用 GO 将查询分解为批次并使用 ALTER。
您似乎正在运行相同的批处理,但在更改后运行了两次: DROP... CREATE... edit... DROP... CREATE..
也许发布您的确切代码,以便我们了解发生了什么。
当我已经创建临时表时,我通常会遇到这个错误;检查 SQL 语句是否有错误的代码会看到“旧”临时表就位,并在后面的语句中返回对列数的错误计数,就好像临时表从未被删除一样。
在创建具有较少列的版本之后更改临时表中的列数后,删除该表,然后运行您的查询。
我最近看到一个 DBA 做了类似的事情:
begin try
drop table #temp
end try
begin catch
print 'table does not exist'
end catch
create table #temp(a int, b int)
注意:这也适用于 ## 临时表。
IE
IF OBJECT_ID('tempdb.dbo.##AuditLogTempTable1', 'U') IS NOT NULL
DROP TABLE ##AuditLogTempTable1
注意:这种类型的命令只适用于 SQL Server 2016 之后。问问自己 .. 我有任何客户仍在使用 SQL Server 2012 吗?
DROP TABLE IF EXISTS ##AuditLogTempTable1
我的代码使用更改的 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
是的,“列无效”这个错误是从“从#Results 中选择公司、stepid、fieldid、NewColumn”行引发的。
运行t-sql有两个阶段,
首先,解析,在这个阶段sql server会检查你提交的sql字符串的更正,包括表的列,并优化你的查询以获得最快的检索。
第二,运行,检索数据。
如果表#Results 存在,则解析过程将检查您指定的列是否有效,否则(表不存在)解析将通过您指定的检查列。
当您更改临时表中的列时,您必须在再次运行查询之前删除该表。 (是的,这很烦人。正是你必须做的。)
我一直认为这是因为“无效列”检查是在查询运行之前由解析器完成的,所以它是基于表中的列在它被删除之前......这也是 pnbs 所说的。
'tempdb..#name'
正是我所需要的。我像个傻瓜一样使用'dbo.#name'
。我得到了tempdb
部分,但是双点是什么?