在 SQL 服务器的临时表中添加和更新后验列
Adding and updating columns a posteriori in temp tables in SQL Server
我正在尝试更改现有的临时文件 table,它是在调用此存储过程的存储过程中创建和填充的,我正在其中进行这些更改。我无法更改调用存储过程,我需要将列添加到临时 table,所以我尝试了这个:
ALTER TABLE #MyTemp
ADD Column1 VARCHAR(100);
UPDATE x
SET Column1 = a.SomeColumn
FROM #MyTemp x
INNER JOIN dbo.AnotherTable a (NOLOCK) ON a.ColumnName = x.ColumnName
WHERE somecondition;
它可以编译,但是当我 运行 它时,我得到:
Msg 207, Level 16, State 1, Procedure ProcName, Line #
Invalid column name 'Column1'
看起来这段代码甚至没有被执行。
有人能告诉我这是否可行以及如何实现吗?
谢谢。
存储过程将具有与您在过程运行后尝试更新它时不同的作用域。您需要将 alter 语句放在 proc 中才能生效,或者将存储过程的内容带到存储过程之外,这样您的 temp table 将与您的更新语句共享相同的范围。
例如:
CREATE PROC SPX_TEST
AS
SELECT 1 AS ABC INTO #TEMP_A
EXEC SPX_TEST
SELECT * FROM #TEMP_A
生成错误,指出临时 table 不存在。
你显然可以做到这一点,但你不能在你改变它的同一范围内插入改变的温度table。不要问我为什么。
您可以在第二个过程中使用动态 sql 来获得较低的嵌套级别,或调用另一个过程。像这样:
use tempdb
go
create or alter proc a
as
begin
create table #t(id int)
exec b
select * from #t
end
go
create or alter proc b
as
begin
alter table #t add a int
exec c
end
go
create or alter proc c
as
begin
insert into #t(id,a) values (1,1)
end
go
正如 David Browne 在他上面的回答中提到的,这也可以通过使用动态 sql 来实现,但是有一个问题,方法如下:
DECLARE @ColName1 NVARCHAR(100)
DECLARE @DynamicSQL NVARCHAR(500)
SET @ColName1='Column1'
SET @DynamicSQL = 'ALTER TABLE #MyTemp ADD ['+ CAST(@ColName1 AS NVARCHAR(100)) +']
NVARCHAR(100) NULL; '
EXEC(@DynamicSQL)
SET @DynamicSQL = 'UPDATE x SET '+ CAST(@ColName1 AS NVARCHAR(100)) + = a.SomeColumn
FROM #MyTemp x INNER JOIN dbo.AnotherTable a (NOLOCK) ON a.ColumnName = x.ColumnName
WHERE somecondition;
EXEC(@DynamicSQL)
如果把Alter和Update放在同一个执行是不行的,它们不能同时执行,否则又是静态代码一样的问题。这种方式就像模拟对另一个存储过程的额外调用,但没有额外的过程。
我正在尝试更改现有的临时文件 table,它是在调用此存储过程的存储过程中创建和填充的,我正在其中进行这些更改。我无法更改调用存储过程,我需要将列添加到临时 table,所以我尝试了这个:
ALTER TABLE #MyTemp
ADD Column1 VARCHAR(100);
UPDATE x
SET Column1 = a.SomeColumn
FROM #MyTemp x
INNER JOIN dbo.AnotherTable a (NOLOCK) ON a.ColumnName = x.ColumnName
WHERE somecondition;
它可以编译,但是当我 运行 它时,我得到:
Msg 207, Level 16, State 1, Procedure ProcName, Line #
Invalid column name 'Column1'
看起来这段代码甚至没有被执行。
有人能告诉我这是否可行以及如何实现吗?
谢谢。
存储过程将具有与您在过程运行后尝试更新它时不同的作用域。您需要将 alter 语句放在 proc 中才能生效,或者将存储过程的内容带到存储过程之外,这样您的 temp table 将与您的更新语句共享相同的范围。
例如:
CREATE PROC SPX_TEST
AS
SELECT 1 AS ABC INTO #TEMP_A
EXEC SPX_TEST
SELECT * FROM #TEMP_A
生成错误,指出临时 table 不存在。
你显然可以做到这一点,但你不能在你改变它的同一范围内插入改变的温度table。不要问我为什么。
您可以在第二个过程中使用动态 sql 来获得较低的嵌套级别,或调用另一个过程。像这样:
use tempdb
go
create or alter proc a
as
begin
create table #t(id int)
exec b
select * from #t
end
go
create or alter proc b
as
begin
alter table #t add a int
exec c
end
go
create or alter proc c
as
begin
insert into #t(id,a) values (1,1)
end
go
正如 David Browne 在他上面的回答中提到的,这也可以通过使用动态 sql 来实现,但是有一个问题,方法如下:
DECLARE @ColName1 NVARCHAR(100)
DECLARE @DynamicSQL NVARCHAR(500)
SET @ColName1='Column1'
SET @DynamicSQL = 'ALTER TABLE #MyTemp ADD ['+ CAST(@ColName1 AS NVARCHAR(100)) +']
NVARCHAR(100) NULL; '
EXEC(@DynamicSQL)
SET @DynamicSQL = 'UPDATE x SET '+ CAST(@ColName1 AS NVARCHAR(100)) + = a.SomeColumn
FROM #MyTemp x INNER JOIN dbo.AnotherTable a (NOLOCK) ON a.ColumnName = x.ColumnName
WHERE somecondition;
EXEC(@DynamicSQL)
如果把Alter和Update放在同一个执行是不行的,它们不能同时执行,否则又是静态代码一样的问题。这种方式就像模拟对另一个存储过程的额外调用,但没有额外的过程。