问题描述
如果我分别运行这些批次中的每一个,它就可以工作。但是,如果将它们组合到一个脚本中(就像运行 DACPAC 脚本时所做的那样,或者将它们都放在 SSMS 中的一个选项卡中),我会在第二次插入时收到 Invalid column name
错误。这是为什么?如果我需要这些在一个脚本中运行,我是否需要为第二批的临时表使用不同的名称?还是我遗漏了一些可以让我使用相同名称的东西?
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
SELECT FirstName,LastName INTO #source FROM Musician WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( FirstName,LastName )
VALUES
('Geddy','Lee'),('Alex','Lifeson')
SELECT * FROM #source
GO
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
SELECT [Name],Genre INTO #source FROM Band WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( [Name],Genre )
VALUES
('rush','Rock'),('Ratt','Rock')
SELECT * FROM #source
GO
解决方法
每个批次都是独立解析的。所以当您使用 GO
时它有效,因为它们在不同的批次中。
当你把所有东西都放在同一个批处理中时,SQL Server 会解析它看到的东西,它对隐藏在 DROP
条件后面的 IF
命令之类的逻辑视而不见。尝试以下操作,您会发现相同的内容:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
IF (1=1) DROP TABLE IF EXISTS #x; CREATE TABLE #x(j date);
你我都知道只有其中一个会执行,但解析器会在它开始执行(或评估任何条件)之前发现冗余表名。
这是可行的,因为现在每个批次都是单独解析的:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
GO
IF (1=1) DROP TABLE IF EXISTS #x; CREATE TABLE #x(j date);
这实际上会失败,即使它通过了解析(突出显示并选择 Parse
而不是 Execute
),所以盲目是双向的:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
GO
IF (1=1) CREATE TABLE #x(j date);
,
在删除两个块中的表后使用 go 可以解决问题。
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
go
SELECT FirstName,LastName INTO #source FROM Musician WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( FirstName,LastName )
VALUES
('Geddy','Lee'),('Alex','Lifeson')
SELECT * FROM #source
GO
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
go
SELECT [Name],Genre INTO #source FROM Band WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( [Name],Genre )
VALUES
('Rush','Rock'),('Ratt','Rock')
SELECT * FROM #source
GO