如何在不需要分布式事务的情况下存储存储过程的结果?

时间:2014-05-13 16:00:04

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

我正在运行一个远程存储过程:

EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'

并且此远程存储过程返回行集:

EmployeeID  EmployeeName    StartDateTime            EndDateTime
----------  --------------  -------------            -----------------------
619         Guyer, Kirsten  2014-05-13 19:00:00.000  2014-05-13 19:00:00.000
...

优异。完善。好。甜。

现在我有了这些结果,我需要将它们存储在一个表中。任何一种表。我不在乎什么样的表:

  • 物理表
  • 临时表
  • 全球临时表
  • 表变量

我只需要存储它们以便我可以处理它们。问题是,当我尝试将结果插入表中时,是否为:

  • 物理表

    INSERT INTO EmployeeSchedule
    EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'
    
  • 临时表

    INSERT INTO #EmployeeSchedule
    EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'
    
  • 全局临时表

    INSERT INTO ##EmployeeSchedule
    EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'
    
  • 表变量

    INSERT INTO @EmployeeSchedule
    EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'
    

SQL Server 坚持(不,要求)它开始分布式事务

  

链接服务器“Contoso”的OLE DB提供程序“SQLNCLI10”返回消息“伙伴事务管理器已禁用其对远程/网络事务的支持。”。
  Msg 7391,Level 16,State 2,Line 41
  无法执行该操作,因为链接服务器“Contoso”的OLE DB提供程序“SQLNCLI10”无法启动分布式事务。

为什么不......

现在,无法对Contoso服务器进行更改。为什么?无所谓。假装杰克鲍尔将出庭并关注任何试图修改Contoso的人。这意味着我无法在\\Contoso上启用或重新配置MSDTC。

您是否尝试使用READ UNCOMMITTED

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
INSERT INTO @EmployeeSchedule 
EXECUTE wclnightdb.NGDemo.dbo.tbtGetSchedule @StartDate, @EndDate 

合作伙伴事务管理器已禁用其对远程/网络事务的支持。

INSERT INTO #EmployeeSchedule 
WITH (NOLOCK)
EXECUTE wclnightdb.NGDemo.dbo.tbtGetSchedule @StartDate, @EndDate 

对不起。没有nolock。 Nolock是一个不,不是:

  

Msg 1065,Level 15,State 1,Line 15
  INSERT,UPDATE,DELETE或MERGE语句的目标表不允许使用NOLOCK和READUNCOMMITTED锁提示。

我总是可以放弃SQL Server

如果我在编程环境中这样做,那么修复起来相当容易:

using (IDataReader rdr = ADOHelper.Execute(conn, "EXECUTE Contoso.Frob.dbo.Grobber @StartDate='20140513', @EndDate='20140518'")
{
   while (rdr.Read())
   {
       InsertRowIntoTable(conn, rdr);
   }
}

虽然这需要我创建一个二进制文件,然后发送它并安排它。我正在寻找适用于SQL Server的选项(因此SQL代理可以安排作业)。

奖金阅读

3 个答案:

答案 0 :(得分:1)

尝试的两个选项是:

  1. 由于您已经设置了链接服务器,因此请将其与OPENQUERY一起使用,如:  SELECT column1, column2 FROM OPENQUERY(Contoso, 'EXECUTE Frob.dbo.Grobber @StartDate=''20140513'', @EndDate=''20140518''')

  2. 如果返回的列保持一致,请创建一个SQLCLR表值函数。这假设远程proc是只读的(即SELECT-only)。但与T-SQL函数不同,SQLCLR函数可以使用连接字符串执行存储过程" Context Connection = True;"只要存储过程是SELECT-only(即不通过DML,DDL等改变DB的状态)。

答案 1 :(得分:1)

  

SQL Server坚持(不,要求)它开始分发   事务:

如果由于某种原因无法将服务器配置为使用分布式事务,则可以告诉它不要。

USE [master]
GO

EXEC master.dbo.sp_serveroption 
    @server   = N'Contoso', 
    @optname  = N'remote proc transaction promotion', 
    @optvalue = N'false'
GO

或者在SSMS GUI中: linked server properties

我不知道关闭此选项的所有含义,但至少现在我的INSERT ... EXEC [LinkedServer]...有效。

答案 2 :(得分:0)

这个怎么样:

- 创建一个通过SQLSMD命令运行远程sql的作业,或者只运行以下命令: EXEC master..xp_cmdshell' SQLCMD -S Server \ SQLSERVERDEV2005 -i" c:\ DML.sql"' (使用作业可能会更容易,因为您可以通过sp_update_jobstep轻松修改作业步骤,以获取参数的正确值)

- 将sqlcmd的结果输出到文件

- 通过批量导入将文件加载到表中。