2012-04-28 61 views
0

我正在创建存储过程,我需要动态地构建一个临时表。我尝试了下面的代码,但没有创建表。当我在查询窗口中执行生成的查询时,它在那里正常工作。为什么不是从存储过程内创建表?

--declare query variable 
DECLARE @Query nvarchar(MAX) 
SET @Query = 'CREATE TABLE #final (DATE int,' 


--DECLARE @COLUMNNAME VARIABLE 
DECLARE @ColName nvarchar(10) 

OPEN @taCur 

FETCH NEXT FROM @taCur INTO @ColName 
WHILE (@@FETCH_STATUS = 0) 
BEGIN 
    SET @Query = @Query + 'T_' + @ColName +' int,' 
    FETCH NEXT FROM @taCur INTO @ColName 
END 

SET @Query = @Query + 'TOTAL int,CUMM_TOTAL int)' 
print @Query 
EXEC sp_executesql @Query 
--SET @Query = 'INSERT INTO #final (DATE) VALUES (1)' 
SET @Query = 'SELECT * FROM #final' 
print @Query 
EXEC(@Query) 

最终生成创建表的查询是遵循

CREATE TABLE #final (DATE int,T_211E int,T_211G int,T_211H int,T_211J int,T_211L int,T_221F int,TOTAL int,CUMM_TOTAL int) 

回答

3

对象#final使用CREATESELECT语句不是在同一范围内。

以下是构建查询的一种方法。

  • 尝试用分号终止SQL语句。尽管它不是强制性的,但它会帮助您区分可读性陈述。请注意,我在的末尾包含分号CREATEINSERTSELECT语句。

  • 你可以注意到CREATEINSERT选择在同一事务执行。因此,您不会失去临时表的范围。

脚本

CREATE TABLE dbo.ColumnSchema 
    (
     ColName NVARCHAR(10) 
    ); 

    INSERT INTO dbo.ColumnSchema (ColName) VALUES 
     ('211E'), 
     ('211G'), 
     ('211H'), 
     ('211J'), 
     ('211L'), 
     ('211F'); 


DECLARE @Query  NVARCHAR(MAX); 
DECLARE @ColName NVARCHAR(10); 

SET @Query = 'CREATE TABLE #final (DATE int,'; 

DECLARE taCursor CURSOR FOR 
    SELECT ColName 
    FROM dbo.ColumnSchema; 

OPEN taCursor 

FETCH NEXT FROM taCursor 
    INTO @ColName 

    WHILE (@@FETCH_STATUS = 0) 
    BEGIN 

     SET @Query = @Query + 'T_' + @ColName + ' int, ' 

     FETCH NEXT FROM taCursor 
      INTO @ColName 
    END 

CLOSE  taCursor; 
DEALLOCATE taCursor; 

SET @Query = @Query + 'TOTAL int,CUMM_TOTAL int); ' 
SET @Query = @Query + 'INSERT INTO #final (DATE) VALUES (1); ' 
SET @Query = @Query + 'SELECT * FROM #final; ' 

EXEC (@Query); 

输出

DATE T_211E T_211G T_211H T_211J T_211L T_211F TOTAL CUMM_TOTAL 
---- ------ ------ ------ ------ ------ ------ ----- ---------- 
1 NULL NULL NULL NULL NULL NULL NULL NULL 
+0

+1对于代码示例.. – 2012-04-28 04:10:01

+0

谢谢@Siva ...你的回答很有帮助 – Dharmesh 2012-04-28 04:15:24

3

你的问题是,你的临时表只知道它创建的范围内是否存在...这是你的第一个sp_executesql的范围之内。当你打电话给你的select声明时,你的临时表不在范围之内。

为了解决这个问题,你就必须建立一个包含你需要用临时表尽一个字符串:你createinsertselect内的所有单sp_executesql电话。

但是,您应该知道,如果您没有完全控制用于构建命令的所有值,则您当前的方法可能容易受到SQL注入的攻击。

+0

我应该怎么做才能在范围选择语句? – Dharmesh 2012-04-28 04:06:38

+0

非常感谢.....你已经清除了我所有的疑惑 – Dharmesh 2012-04-28 04:13:17