我有一个带有动态sql的存储过程,我已经嵌入了如下:
delete from #temp_table
begin tran
set @sql = 'select * into #temp_table from sometable'
exec (@sql)
commit tran
begin
set @sql = 'alter table #temp_table add column1 float'
exec(@sql)
end
update #temp_table
set column1 = column1*100
select *
into Primary_Table
from #temp_table
但是,我注意到所有的陈述都有效,但改变了。运行该过程时,我收到一条错误消息:“无效的列名列1”
我在这里做错了什么?
编辑:已实现我没有提到第一个插件也是动态sql。更新了它。
尝试了替代方法,但抛出同样的错误:
delete from #temp_table
begin tran
set @sql = 'select * into #temp_table from sometable'
exec (@sql)
commit tran
alter table #temp_table add column1 float
update #temp_table set column1 = column1*100
答案 0 :(得分:0)
1)它应该是ALTER TABLE #temp ...不是ALTER #temp。
2)即使#1不是问题,你也要将column1添加为没有默认值的NULLable列,并在下一个语句中将它的值设置为自身* 100 ... NULL * 100 = NULL
3)为什么使用动态sql来改变#temp表?它可以很容易地使用常规的ALTER TABLE脚本...或者更好的是,可以包含在原始表定义中。
答案 1 :(得分:0)
本地临时表显示类似动态范围的内容。在对exec
的调用中创建本地临时表时,它会从exec
返回范围并且存在。
EXEC (N'create table #x (c int)')
GO
SELECT * FROM #x
Msg 208,Level 16,State 0,Line 4 无效的对象名称'#x'。
在运行动态SQL以创建#x
之后解析select。但是#x
不在那里,因为从exec
退出时放弃了。
<强>更新强>
根据具体情况,有不同的方法可以解决这个问题。
将所有内容放入相同的字符串中:
DECLARE @Sql NVARCHAR(MAX) = N'SELECT 1 AS source INTO #table_name;
ALTER TABLE #table_name ADD TARGET float;
UPDATE #table_name SET Target = 100 * source;';
EXEC (@Sql);
在填充它的动态sql之前创建表。
CREATE TABLE #table_name (source INT);
EXEC (N'insert into #table_name (source) select 1;');
ALTER TABLE #table_name ADD target FLOAT;
UPDATE #table_name SET target = 100 * source;
在此选项中,可以通过将附加列添加到alter table
语句来删除create table
语句。另请注意,alter table
和update
语句可以在动态SQL的单独调用中,如果这对您的上下文有益。
答案 2 :(得分:0)
这是因为外部批处理中的#temp_table引用是与动态SQL中创建的临时表不同的临时表。考虑:
use tempdb
drop table if exists sometable
drop table if exists #temp_table
go
create table sometable(id int, a int)
create table #temp_table(id int, b int)
exec( 'select * into #temp_table from sometable; select * from #temp_table;' )
select * from #temp_table
输出
id a
----------- -----------
(0 rows affected)
id b
----------- -----------
(0 rows affected)
在嵌套批处理中创建的临时表的范围限定为嵌套批处理,并在之后自动删除。 A&#34;嵌套批次&#34;是动态SQL查询还是存储过程。此行为在CREATE TABLE进行了解释,但它只提到了存储过程。动态SQL的行为相同。
如果您在顶级批处理中创建临时表,则可以在动态SQL中访问它,您只是无法在动态SQL中创建新临时表并在外部批处理或后续的同级动态SQL。因此,尝试使用INSERT INTO而不是SELECT INTO。