插入语句工作后为什么不改变?

时间:2017-08-30 17:40:55

标签: sql-server

我有一个带有动态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

3 个答案:

答案 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退出时放弃了。

<强>更新

根据具体情况,有不同的方法可以解决这个问题。

  1. 将所有内容放入相同的字符串中:

    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);
    
  2. 在填充它的动态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;
    
  3. 在此选项中,可以通过将附加列添加到alter table语句来删除create table语句。另请注意,alter tableupdate语句可以在动态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。