从外部进程引用#temp表

时间:2012-03-12 19:26:57

标签: sql-server-2008

使用SQL Server 2008,我有两个存储过程 -

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 个答案:

答案 0 :(得分:2)

您需要一个全局临时表或永久表。

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

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

它们都完成了同样的事情 - 外部进程可以访问的表(本地#temp表仅限于调用者的范围)。不同之处在于,##全局临时表不需要显式删除,但永久表不会。

这意味着,如果两个用户同时调用此存储过程,其中一个将生成错误(或完全撤消另一个用户开始执行的操作)。如果您可以在动态SQL中执行所有#temp表魔术,则可以考虑将当前会话的spid或其他一些唯一符添加到表名中。

答案 1 :(得分:0)

除了Aaron Bertrand所写的内容。我将补充说,您还可以将表作为表值参数传递。

来自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