Sql 如果超过60秒,则跳过While循环中的批处理

Sql 如果超过60秒,则跳过While循环中的批处理,sql,sql-server,tsql,Sql,Sql Server,Tsql,我尝试使用WHILE循环来迭代批处理,以将客户引用与数据表匹配。我生成的SQL查询得到了所需的结果,因此我希望在更长的时间段内运行该查询,包括while循环和批处理 批处理大约需要2秒钟才能将另外10000行插入表中,我遇到的问题意味着,对于特定批处理,流程将继续运行,但不会发生插入。我已经确定,这似乎始终取决于批处理中没有插入的特定Call_id,但是当运行有问题的记录时,特别是将插入的记录 我正在寻找一种解决方案,该解决方案允许进程在10000条记录的批次中运行插入,但如果需要10秒以上的时

我尝试使用WHILE循环来迭代批处理,以将客户引用与数据表匹配。我生成的SQL查询得到了所需的结果,因此我希望在更长的时间段内运行该查询,包括while循环和批处理

批处理大约需要2秒钟才能将另外10000行插入表中,我遇到的问题意味着,对于特定批处理,流程将继续运行,但不会发生插入。我已经确定,这似乎始终取决于批处理中没有插入的特定Call_id,但是当运行有问题的记录时,特别是将插入的记录

我正在寻找一种解决方案,该解决方案允许进程在10000条记录的批次中运行插入,但如果需要10秒以上的时间,将跳过批次。我尝试将LOCK_TIMEOUT设置为60000,但这似乎没有改变任何提示问题与锁无关的内容

然后,我计划为跳过的批运行流程,但增量要小得多,这样我就可以识别导致问题的记录

仅供参考,我正在处理大约400万条记录

提前谢谢

CREATE PROCEDURE dbo.USR_FN_CRM_AGREEMENTS_BATCHES
AS

DECLARE @BatchStart  INT;
DECLARE @ResultCount INT;
DECLARE @Increment   INT;
DECLARE @BatchStartTime DATETIME;

SET @Increment = 10000;
SET @BatchStart = 2858110;
SET @ResultCount = 1;
SET @BatchStartTime = GETDATE()

WHILE(@ResultCount > 0)
    BEGIN

    SET LOCK_TIMEOUT 60000;


        WITH AccountReferences
             AS (SELECT ra.ID AS AccountReference, 
                        ra.MainAsset, 
                        cgct.Contact_ID, 
                        cgct.Group_Contact_ID, 
                        ra.AccountStartDate, 
                        ra.AccountEndDate
                 FROM SQLActiveH_Reporting.dbo.Contact_Group_Contacts_T cgct
                      LEFT JOIN SQLActiveH_Reporting.dbo.Rent_Accounts ra ON cgct.Group_ID = ra.ContactDatabaseReference
                ),
             CRM_Calls
             AS (SELECT cct.Call_ID, 
                        cct.Call_Made_By_Group_Contact_ID, 
                        cct.Call_Relates_To_Group_Contact_ID, 
                        cct.Call_Relates_To_Asset_ID AS Asset_ID, 
                        cct.Entered_Actual_DT AS Call_Date_Time
                 FROM SQLActiveH_Reporting.dbo.CRM_Calls_T cct
                 WHERE cct.Call_ID > @BatchStart
                       AND cct.Call_ID <= @BatchStart + @Increment
                       AND cct.Call_ID NOT IN (2873237)
             ),
             DataPrep
             AS (
             SELECT CASE WHEN AR1.AccountReference IS NOT NULL THEN AR1.AccountReference
                             WHEN AR2.AccountReference IS NOT NULL THEN AR2.AccountReference
                             WHEN AR3.AccountReference IS NOT NULL THEN AR3.AccountReference
                             WHEN AR4.AccountReference IS NOT NULL THEN AR4.AccountReference
                             WHEN AR5.AccountReference IS NOT NULL THEN AR5.AccountReference
                             WHEN AR6.AccountReference IS NOT NULL THEN AR6.AccountReference
                             WHEN AR7.AccountReference IS NOT NULL THEN AR7.AccountReference
                             WHEN AR8.AccountReference IS NOT NULL THEN AR8.AccountReference
                             WHEN AR9.AccountReference IS NOT NULL THEN AR9.AccountReference
                             ELSE NULL
                        END AS AccountReference, 
                        CRM.Call_ID, 
                        CRM.Call_Made_By_Group_Contact_ID, 
                        CRM.Call_Relates_To_Group_Contact_ID, 
                        CRM.Asset_ID, 
                        CRM.Call_Date_Time, 
                        ROW_NUMBER() OVER(PARTITION BY CRM.Call_ID ORDER BY CRM.Call_Date_Time) AS SEQ
                 FROM CRM_Calls CRM
                      LEFT JOIN AccountReferences AR1 ON CRM.Call_Made_By_Group_Contact_ID = AR1.Group_Contact_ID AND CRM.Asset_ID = AR1.MainAsset
                                                         AND CRM.Call_Date_Time BETWEEN AR1.AccountStartDate AND AR1.AccountEndDate
                      LEFT JOIN AccountReferences AR2 ON CRM.Call_Made_By_Group_Contact_ID = AR2.Group_Contact_ID
                                                         AND CRM.Call_Date_Time BETWEEN AR2.AccountStartDate AND AR2.AccountEndDate
                      LEFT JOIN AccountReferences AR3 ON CRM.Call_Relates_To_Group_Contact_ID = AR3.Group_Contact_ID
                                                         AND CRM.Asset_ID = AR3.MainAsset
                                                         AND CRM.Call_Date_Time BETWEEN AR3.AccountStartDate AND AR3.AccountEndDate
                      LEFT JOIN AccountReferences AR4 ON CRM.Call_Relates_To_Group_Contact_ID = AR4.Group_Contact_ID
                                                         AND CRM.Call_Date_Time BETWEEN AR4.AccountStartDate AND AR4.AccountEndDate
                      LEFT JOIN AccountReferences AR5 ON CRM.Call_Made_By_Group_Contact_ID = AR5.Group_Contact_ID
                                                         AND CRM.Asset_ID = AR5.MainAsset
                      LEFT JOIN AccountReferences AR6 ON CRM.Call_Made_By_Group_Contact_ID = AR6.Group_Contact_ID
                      LEFT JOIN AccountReferences AR7 ON CRM.Call_Relates_To_Group_Contact_ID = AR7.Group_Contact_ID
                                                         AND CRM.Asset_ID = AR7.MainAsset
                      LEFT JOIN AccountReferences AR8 ON CRM.Call_Relates_To_Group_Contact_ID = AR8.Group_Contact_ID
                      LEFT JOIN AccountReferences AR9 ON CRM.Asset_ID = AR9.MainAsset
                                                         AND CRM.Call_Date_Time BETWEEN AR9.AccountStartDate AND AR9.AccountEndDate
                       )
             INSERT INTO Admin_DBA.dbo.CRM_Accounts
                    SELECT dp.AccountReference, 
                           dp.Call_ID, 
                           dp.Call_Made_By_Group_Contact_ID, 
                           dp.Call_Relates_To_Group_Contact_ID, 
                           dp.Asset_ID, 
                           dp.Call_Date_Time,
                           @BatchStart
                    FROM DataPrep dp
                    WHERE Seq = 1
                 ;


        SET @BatchStart = @BatchStart + @Increment;
        SET @ResultCount = @@ROWCOUNT;

    END;

USE [Admin_DBA]
GO

/****** Object:  Table [dbo].[CRM_Accounts]    Script Date: 18/07/2019 
09:21:11 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CRM_Accounts](
    [AccountReference] [varchar](50) NULL,
    [Call_ID] [int] NOT NULL,
    [Call_Made_By_Group_Contact_ID] [int] NULL,
    [Call_Relates_To_Group_Contact_ID] [int] NULL,
    [Asset_ID] [int] NULL,
    [Call_Date_Time] [datetime] NOT NULL,
    [SEQ] [bigint] NULL
) ON [PRIMARY]
GO

这不能从t-SQL轻松完成,因为无法为单个命令包含超时。唯一的方法是创建一个资源调控器池,但即使要让它在该资源池上执行,实际上也需要从代理作业运行它,因为您也不能在t-SQL中显式地创建新连接。如果您需要一个稳定、可跟踪的解决方案来解决这类问题,那么客户端代码—无论是SSI、PowerShell还是您选择的编程语言—都是一个更好的选择,至少在控制批处理和从错误中恢复方面。@dlatikay由于一个调用\u ID可能与所有9个连接条件相匹配,其中Seq=1仅将其中一个匹配提交到输出表。我测试了分而治之的方法,但当我隔离到一条记录并将其单独插入到批处理之外时,它会很好地加载到表中。我确实尝试运行并手动识别,但第一次失败后的下一次失败仅发生在5k行之后,考虑到4m的处理时间,这可能需要大量的手动划分和征服@JeroenMostert由于没有由于记录挂起而引发的错误,我不确定SSIS或其他工具中的错误处理是否有用。也就是说,我将在明天和明天探索这个选项feedback@dlatikay为CRM_Accounts表添加了创建表脚本。没有使用忽略Dup键或其他约束。@dlatikay因为它实际上并没有插入该行,所以它进入并停止该行感觉像是一个表锁,但正如您所看到的,我设置了锁超时。它不是以0插入的形式传递该批,它只是在该批处停止,并带有一条它不喜欢的记录,而不是继续插入,就好像卡在select上一样