3

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

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

有没有其他方法可以实现这一点。

谢谢

4

3 回答 3

3

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

看看下面的例子

SQL 小提琴演示

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
于 2013-08-07T12:43:57.440 回答
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 with examples

于 2013-08-07T13:08:09.773 回答
0

另一个技巧是使用OPENQUERY. 从我在这里的回答

它需要使用属性设置为 trueOPENQUERY的环回链接服务器。'DATA ACCESS'您可以检查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了解其他信息和限制。

于 2013-08-07T12:48:15.657 回答