2012-03-12 93 views
1

使用SQL Server 2008中引用一個#temp表,我有兩個存儲過程 -從外部進程

create procedure [dbo].[SH_Export_data] (@unit varchar(5)) as 
    declare @sqlquery varchar(max) = 'select check_dt from chk_data where unit = ' 
    + @unit 

    IF object_id('tempdb..#TempTbl') IS NOT NULL 
    DROP TABLE #TempTbl 
    create TABLE #TempTbl (
    col1 varchar(max), col2 varchar(max) 
) 

    insert #TempTbl(col1) 
    exec(@sqlquery) 



create procedure [dbo].[SH_Export] as 
    DECLARE @unit varchar(5), @sql varchar(max) = '', @file_name = 'c:\export.xls' 

    DECLARE crsr CURSOR for 
    select unit 
    from communities 

    OPEN crsr 
    FETCH NEXT FROM crsr 
    into @unit 

    while @@FETCH_STATUS = 0 
    BEGIN 
    set @sql = 'exec master..xp_cmdshell ''bcp "exec dbo.SH_Export_data ' + 
     @unit + '" queryout "' + @file_name + '" -c -T "'' 
    END 

注意,有一個存儲過程調用另一個。被調用的存儲過程將創建一個臨時表並在其內部使用它。

當我運行 -

exec dbo.SH_Export 

我得到這個錯誤信息 -

Error = [Microsoft][SQL Server Native Client 10.0][SQL Server] 
Invalid object name '#TempTbl'. 

但我可以運行,而不會出現錯誤 -

exec dbo.SH_Export_data 63058 

是什麼原因造成的?

回答

2

你需要一個全局臨時表或永久表。

create TABLE ##TempTbl (
    col1 varchar(max), col2 varchar(max) 
) 

create TABLE dbo.TempTbl (
    col1 varchar(max), col2 varchar(max) 
) 

他們都完成同樣的事情 - 你的外部進程可以訪問表(本地#TEMP表被限制主叫方的範圍)。不同之處在於##全局臨時表不需要顯式刪除,但是永久性的。

這意味着什麼,不過,是如果兩個用戶同時調用這個存儲過程,他們中的一個將產生一個錯誤(或完全取消其他的什麼一個開始做)。如果您可以在動態SQL中執行所有#temp表魔術,則可以考慮將當前會話的spid或某個其他唯一性添加到表名中。

+0

作品。謝謝Aaron。 – duckmike 2012-03-12 20:49:50

0

除了什麼阿龍貝特朗寫道。我將補充一點,你也可以傳遞一個表作爲表值參數。

從MSDN:http://msdn.microsoft.com/en-us/library/bb510489.aspx

USE AdventureWorks2008R2; 
GO 

/* Create a table type. */ 
CREATE TYPE LocationTableType AS TABLE 
(LocationName VARCHAR(50) 
, CostRate INT); 
GO 

/* Create a procedure to receive data for the table-valued parameter. */ 
CREATE PROCEDURE usp_InsertProductionLocation 
    @TVP LocationTableType READONLY 
    AS 
    SET NOCOUNT ON 
    INSERT INTO [AdventureWorks2008R2].[Production].[Location] 
      ([Name] 
      ,[CostRate] 
      ,[Availability] 
      ,[ModifiedDate]) 
     SELECT *, 0, GETDATE() 
     FROM @TVP; 
     GO 

/* Declare a variable that references the type. */ 
DECLARE @LocationTVP 
AS LocationTableType; 

/* Add data to the table variable. */ 
INSERT INTO @LocationTVP (LocationName, CostRate) 
    SELECT [Name], 0.00 
    FROM 
    [AdventureWorks2008R2].[Person].[StateProvince]; 

/* Pass the table variable data to a stored procedure. */ 
EXEC usp_InsertProductionLocation @LocationTVP; 
GO 
+0

我也在考慮補充說,有可能還有其他更好的方法來做到這一點。例如,爲什麼不使用'bcp -queryout'並首先繞過整個臨時表的麻煩? – 2012-03-12 22:16:49

+0

這是一個很好的觀點。我甚至沒有仔細檢查他的代碼,他似乎使用非常迂迴/非理想的方式到達那裏。 – 2012-03-12 22:23:34