2017-08-30 44 views
0

我有,我有嵌入如下动态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 

然而,我注意到,所有的报表工作,但ALTER没有。当运行该过程时,我收到一条错误消息:“无效的列名称列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

编译器不知道你的动态sql中有什么。另外你的开始/提交转化看起来是多余的和不必要的。您需要插入GO命令(批量分隔符)才能通过编译器,认为没有这样的列。 – pmbAustin

+0

感谢。将删除开始/提交传送 – Bee

+0

您的第一个插入不会插入任何内容 - 没有从子句。它应该像“从some_other_table选择*到#temp_table” – Mike

回答

0

本地临时表表现出类似的动态范围。当您在对exec的调用中创建本地临时表时,它会从exec返回时超出范围并存在。

EXEC (N'create table #x (c int)') 
GO 
SELECT * FROM #x 

Msg 208, Level 16, State 0, Line 4 Invalid object name '#x'.

的选择动态SQL后进行解析,以创建#x是跑了。但#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; 
    

在这个选项中,alter table声明可以通过添加额外的列到create table声明被删除。”还要注意的是,alter tableupdate陈述可能处于动态SQL的单独调用中,如果这对您的上下文有益。

+0

谢谢。在这种情况下,正确的做法是什么?如果我必须使用动态sql插入到临时表中,请更改表并使用最初创建的临时表中的值更新添加的列? – Bee

0

1) It should be ALTER TABLE #temp... Not ALTER #temp.

2) Even if #1 weren't an issue, you're adding column1, as a NULLable column with no default value and, in the next statement setting it's value to itself * 100... NULL * 100 = NULL

3) Why are you using dynamic sql to alter the #temp table? It can just as easily be done with a regular ALTER TABLE script... or, better yet, can be included in the original table definition.

+0

对于#1,它肯定是一个错字。对于#2,这是我最初运行脚本的方式,没有alter和update的动态sql。但它错误地出现了一个“无效的列” - 认为它需要动态包装,并以这种方式重新运行。 – Bee

+0

@Bee,我已经更新了我的答案......将#2推到#3并添加了#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) 

嵌套一批创建的临时表的作用范围是嵌套的批次和后自动删除。 “嵌套批处理”可以是动态SQL查询或存储过程。这种行为在这里解释CREATE TABLE,但它只提到存储过程。动态SQL的行为相同。

如果您在顶级批次中创建临时表,则可以在动态SQL中访问它,但您不能在动态SQL中创建临时表并在外部批次中或在其后的同一批次中查看它级动态SQL。所以尝试使用INSERT INTO而不是SELECT INTO。

+0

啊..谢谢,理解。希望在前面创建一个表格,因为它跨越了300列 - 猜测没有任何其他选项。 – Bee

相关问题