首页 > 解决方案 > 为什么我在使用临时表两次时会收到无效的列名错误?

问题描述

如果我分别运行这些批次中的每一个,它就可以工作。但是,如果将它们组合到一个脚本中(例如运行 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

标签: sqlsql-serversql-server-2017

解决方案


每个批次都是独立解析的。所以它在你使用时有效,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);

推荐阅读