2

我有一个触发器After Update

此触发器适用于将更新链接服务器上的 2 个表的服务器

查看代码

ALTER TRIGGER [dbo].[tgAfterUpdate] ON  [dbo].[KS_3EToVision]
   AFTER UPDATE
AS 
BEGIN

  BEGIN TRY
  BEGIN TRANSACTION    -- Start the transaction

  DECLARE @MatterNumber varchar(15);
  SELECT @MatterNumber = i.MatterNumber FROM inserted i; 

    IF EXISTS(SELECT * FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE         Ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT)
       --UPDATE
        IF (SELECT Ch_matter_status FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE Ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT ) = 'Current'
             BEGIN 
                --Parent table 
                UPDATE [FSSQLDEV01].[collnab].[dbo].[collection_header]
                SET 
                    Ch_start_date = i.OpenDate 
                FROM 
                    Inserted i 
                WHERE ch_file_number COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT  

                ----Child table 
                UPDATE [FSSQLDEV01].[collnab].[dbo].[collections] 
                SET 
                    Defendant_1 = i.Description 
                    , Loan_Number_1 = i.Comments 
                    , Client = i.KS_BookName 
                    , Date_Instructed = i.OpenDate 
                    , Person_Responsible_name = i.ResponsibleFeeEarnerName 
                    , Person_Responsible_Email = i.ResponsibleFeeEarnerEmail 
                    , Person_Acting_name = i.BillingFeeEarnerName 
                    , Person_Acting_email = i.BillingFeeEarnerEmail 
                    , Agent_Acting_name = i.BillingFeeEarnerName 
                    , Agent_Acting_email = i.BillingFeeEarnerEmail 
                    , CBA_Panel_Service_Area = i.KS_ServiceCat 
                    , HBN_Number = i.KS_ClientAcctRef 
                    , St_George_Contact = i.KS_Instructor 
                FROM 
                    Inserted i 
                WHERE Left(Collections.file_number,6) COLLATE DATABASE_DEFAULT = @MatterNumber COLLATE DATABASE_DEFAULT
             END

--If we reach here, success!
   COMMIT
END TRY
BEGIN CATCH
  -- Whoops, there was an error
  IF @@TRANCOUNT > 0
     ROLLBACK

  -- Raise an error with the details of the exception
  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
     @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

END 

如果我在触发器之外尝试使用相同条件的更新语句,它只需要 1 秒,但在触发器内部可能需要 45 秒。

我已将其缩小到第二个更新语句是问题所在,因为如果我删除第二个更新语句,它将快速执行。

我还附上了显示的图片

我还有一个用于插入的触发器,它可以在一秒钟内快速工作,而一个用于删除的触发器将在触发器中花费很长时间,但如果我在触发器之外删除 2 个删除语句,则功能正常。

USE [TE_3E_TRG]
GO
/****** Object:  Trigger [dbo].[tgAfterDelete]    Script Date: 08/30/2012 11:24:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tgAfterDelete] ON  [dbo].[KS_3EToVision]
   AFTER DELETE
AS 

begin

BEGIN TRY
   BEGIN TRANSACTION    -- Start the transaction
            Begin
                --Parent table 
                DELETE FROM [FSSQLDEV01].[collnab].[dbo].[collection_header] WHERE ch_file_number COLLATE DATABASE_DEFAULT = (SELECT d.MatterNumber FROM deleted  d) COLLATE DATABASE_DEFAULT

                --Child table 
                DELETE FROM [FSSQLDEV01].[collnab].[dbo].[collections] WHERE Left(file_number,6) COLLATE DATABASE_DEFAULT = (SELECT d.MatterNumber FROM deleted  d) COLLATE DATABASE_DEFAULT            

            END
   -- If we reach here, success!
   COMMIT
END TRY
BEGIN CATCH
  -- Whoops, there was an error
  IF @@TRANCOUNT > 0
     ROLLBACK

  -- Raise an error with the details of the exception
  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
         @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

有谁知道为什么在触发器内部和触发器外部执行语句之间可能会出现这种执行时间的巨大差异?

4

1 回答 1

0

您正在将远程表与本地虚拟插入表连接起来。这可能涉及将整个表从远程服务器复制到本地并在本地过滤。

这是非常罕见的情况,使用游标和逐行更新可能会提高性能。

顺便说一句,marc_s 的观点是正确的,您的代码应该考虑到插入表超过 1 行的可能性。

于 2012-12-19T17:53:39.827 回答