查看与存储过程结果的连接

时间:2013-08-07 12:40:14

标签: sql-server sql-server-2008 sql-server-2008-r2

我在应用程序使用的SQL服务器中有一个现有视图。我需要加入从存储过程返回的表。存储过程执行很多操作,例如在返回结果之前插入多个#temp表。

我尝试将存储过程转换为Table值函数。但是在TVF内插入临时表会导致编译错误。

还有其他方法可以达到这个目的。

由于

3 个答案:

答案 0 :(得分:3)

您可以将存储过程中的结果插入到临时表中,然后将其连接到视图中。

看一下下面的例子

SQL Fiddle DEMO

CREATE TABLE TADA(
  ID INT
);
INSERT INTO TADA VALUES (1),(2);

CREATE VIEW vw_TADA
AS
SELECT *
FROM TADA
WHERE ID <= 1;

CREATE PROCEDURE sp_TADA
AS
SELECT *
FROM TADA
WHERE ID > 1;

CREATE TABLE #TADA(
  ID INT
)
INSERT INTO #TADA EXEC sp_TADA

SELECT *
FROM vw_TADA
UNION ALL
SELECT *
FROM #TADA

答案 1 :(得分:0)

另一个技巧是使用OPENQUERY。来自my answer here

需要使用OPENQUERY和环回链接服务器,并将'DATA ACCESS'属性设置为true。您可以查看sys.servers以查看您是否已拥有有效的服务器,但我们只需创建一个名为loopback的手动服务器:

EXEC master..sp_addlinkedserver 
    @server = 'loopback',  
    @srvproduct = '',
    @provider = 'SQLNCLI',
    @datasrc = @@SERVERNAME;

EXEC master..sp_serveroption 
    @server = 'loopback', 
    @optname = 'DATA ACCESS',
    @optvalue = 'TRUE';

现在您可以将其作为链接服务器进行查询,您可以将任何查询的结果(包括存储过程调用)用作常规SELECT。所以你可以这样做(注意数据库前缀 很重要,否则你会得到错误11529和2812):

SELECT * FROM OPENQUERY(loopback, 'EXEC db.dbo.procedure;') AS x;

现在您可以加入您的视图。

但老实说,如果你把这个程序重写为TVF并停止在逻辑中使用#temp表会更好。以上可能适用于您当前的实例,但它不能在SQL Server 2012中工作(因为过程中的#temp表无法确定元数据),如果您有某些数据库或服务器,它将无法工作 - 级别DDL触发(出于相同类型的原因)。

另请参阅http://www.sommarskog.se/share_data.html#OPENQUERY了解其他信息和限制。

答案 2 :(得分:0)

只是要添加另一种方法来处理这样的数据,您可以使用共享临时表或输出xml参数来从存储过程中获取数据。实际上它需要修改你的程序,所以它可能不是一个选项。一般建议是尝试将您的过程重写为表函数(您可以将临时表更改为表变量)

xml参数

CREATE PROCEDURE sp_Process2
(
  @Data xml = null output,
  @Fill_Data bit = 0
)
AS
begin
   create table #Test1 (ID int, Name nvarchar(128), Col3 nvarchar(128))

   -- do some work
   insert into #Test1
   select 1, 'From Procedure', 'Unused'

   if @Fill_Data = 1 -- put data into xml parameter
   begin
      select @Data = 
      (
          select *
          from #Test1
          for xml raw('Data')
      )
   end
   else -- just return recordset
   begin
      select * from #Test1
   end
end;

共享表(动态SQL完全是可选的,只是将表名和列传递给过程)

CREATE PROCEDURE sp_Process
(
  @Table_Name nvarchar(128) = null,
  @Columns nvarchar(max) = null
)
AS
begin
   declare @stmt nvarchar(max)
   create table #Test1 (ID int, Name nvarchar(128), Col3 nvarchar(128))

   -- do some work
   insert into #Test1
   select 1, 'From Procedure', 'Unused'

   if @Table_Name is not null -- put data into temporary table
   begin
      select @stmt = 'insert into ' + quotename(@Table_Name) + ' select ' + @Columns + ' from #Test1'
      exec sp_executesql @stmt = @stmt
   end
   else -- just return recordset
   begin
      select * from #Test1
   end
end;

请参阅sql fiddle示例