在触发器或过程中测试链接的服务器conccetion

时间:2009-05-29 15:04:21

标签: sql-server stored-procedures triggers linked-server

我写了一个触发器来更新链接服务器上的本地表和类似表。

CREATE TRIGGER myTtableUpdate ON myTable
AFTER UPDATE AS
IF (COLUMNS_UPDATED() > 0)
BEGIN
DECLARE @retval int;
BEGIN TRY
EXEC @retval = sys.sp_testlinkedserver N'my_linked_server';
END TRY
BEGIN CATCH
SET @retval = sign(@@error);
END CATCH;

IF (@retval = 0)
BEGIN
UPDATE remoteTable SET remoteTable.datafield = i.datafield
FROM my_linked_server.remote_database.dbo.myTable remoteTable
INNER JOIN inserted i ON (remoteTable.id = i.id)
END
END -- end of trigger

不幸的是,当连接断开时,我收到错误消息
'Msg 3616,Level 16,State 1,Line 2'
'交易在触发器中注定失败。批次已中止'
并回滚本地更新。

有没有办法维护此错误并保留本地更新? 请注意,我在运行Windows XP Pro的两台PC上都使用SQL Server 2005 Express Edition。

edit1:SQL Server是Express Edition
edit2:两台PC都运行Windows XP Pro,因此这些不是服务器

2 个答案:

答案 0 :(得分:1)

不要在触发器中写入远程服务器。

  • 创建一个本地表来存储需要推送到远程服务器的行
  • 在触发器
  • 中插入此新本地表
  • 创建一个每N分钟运行一次的作业,以便从此本地表插入远程服务器。

这个作业可以运行一个可以测试连接的过程,当它被备份时,它将处理新本地表中的所有行。它可以这样处理本地表中的行:

declare @OutputTable table (RowID int not null)

insert into my_linked_server.remote_database.dbo.myTable remoteTable(...columns...)
    OUTPUT INSERTED.RowID
    INTO @OutputTable
    SELECT ...columns...
        from NewLocalTable

delete NewLocalTable
   from NewLocalTable           n
       inner join @OutputTable  o ON n.RowID=o.RowID

基于编辑的OP评论
插入这个新的本地表后,从触发器(sp_start_job)启动作业,它将在自己的范围内运行。如果你不能使用sql server作业,使用xp_cmdshell来执行存储过程(查找SQLCMD或ISQL或OSQL,我不知道你有什么)。仍然每N分钟安排一次工作,所以当连接出现时它最终会运行。

答案 1 :(得分:0)

至少有一个服务器Workgroup版本或更高版本?您可以使用Service Broker来发送记录而不是链接服务器,但由于许可限制,它不能用于Express版本。是一个完全依赖于SQL的解决方案,在事件发生时提供可靠性(其中一个服务器不可用),并且您的更新将实时传播(一旦提交)。我的网站有很多关于如何执行此操作的示例,您可以从how to achieve high message throughput上的这篇文章开始。