Решение найдет свое применение в тех случаях, когда есть необходимость отменять зависшие экземпляры процессов.
Ссылка на решение
Вся основная логика лежит на хранимых процедурах: tsp_DeleteSysProcessDataById, tsp_DeleteSysProcessDataByStartDate, tsp_UpdateSysProcessLogById, tsp_UpdateSysProcessLogByStartDate
В общих словах про процедуры
tsp_DeleteSysProcessDataById – удаляет информацию по процессу из таблиц SysActivityPrcEl, SysEntityCommonPrcEl, SysProcessIntermediateEvent, SysProcessData
tsp_DeleteSysProcessDataByStartDate – читает процессы, в логе фильтрует по дате, и запускает DeleteSysProcessDataById
tsp_UpdateSysProcessLogById – обновляет информацию по процессу из таблиц SysProcessLog, SysProcessElementLog,
tsp_UpdateSysProcessLogByStartDate – читает процессы, в логе фильтрует по дате, и запускает UpdateSysProcessLogById
Бизнес-процесс который позволяет выбрать процесс, указать период, отменить процессы и выдать результат (к-ство отменных процессов)
Ниже отдельно SQL скрипты самих процедур
Скрипт на удаление:
SET QUOTED_IDENTIFIER ON GO IF NOT OBJECT_ID('[dbo].[tsp_DeleteSysProcessDataById]') IS NULL BEGIN DROP PROCEDURE [dbo].[tsp_DeleteSysProcessDataById] END GO CREATE PROCEDURE [dbo].[tsp_DeleteSysProcessDataById] @SysProcessDataId uniqueidentifier AS BEGIN SET NOCOUNT ON DECLARE @sysProcessDataRecordsToDelete TABLE (Id uniqueidentifier) DECLARE @sysProcessElementDataRecordsToDelete TABLE (Id uniqueidentifier ) INSERT INTO @sysProcessDataRecordsToDelete ([Id]) SELECT Id from SysProcessData WHERE ParentId = @SysProcessDataId OPTION (OPTIMIZE FOR (@SysProcessDataId UNKNOWN)) DECLARE @COUNT bigint = (SELECT COUNT_BIG(*) FROM @sysProcessDataRecordsToDelete) WHILE (@COUNT) != 0 BEGIN DECLARE @parentId uniqueidentifier = (SELECT TOP 1 Id from @sysProcessDataRecordsToDelete) DELETE FROM @sysProcessDataRecordsToDelete WHERE Id = @parentId; EXEC [dbo].[tsp_DeleteSysProcessDataById] @parentId SET @COUNT = @COUNT - 1 END INSERT INTO @sysProcessElementDataRecordsToDelete ([Id]) SELECT Id FROM SysProcessElementData WHERE SysProcessId = @SysProcessDataId SET @COUNT = (SELECT COUNT_BIG(*) FROM @sysProcessElementDataRecordsToDelete) DELETE FROM SysActivityPrcEl WHERE ProcessElementId IN (SELECT Id FROM @sysProcessElementDataRecordsToDelete) DELETE FROM SysEntityCommonPrcEl WHERE ProcessElementId IN (SELECT Id FROM @sysProcessElementDataRecordsToDelete) DELETE FROM SysProcessIntermediateEvent WHERE SysProcessElementId IN (SELECT Id FROM @sysProcessElementDataRecordsToDelete) DELETE FROM SysProcessData WHERE Id = @SysProcessDataId OPTION (OPTIMIZE FOR (@SysProcessDataId UNKNOWN)) END GO SET QUOTED_IDENTIFIER ON GO IF NOT OBJECT_ID('[dbo].[tsp_DeleteSysProcessDataByStartDate]') IS NULL BEGIN DROP PROCEDURE [dbo].[tsp_DeleteSysProcessDataByStartDate] END GO CREATE PROCEDURE [dbo].[tsp_DeleteSysProcessDataByStartDate] @ProcessName nvarchar(MAX), @StartDate datetime, @EndDate datetime AS BEGIN SET NOCOUNT ON IF NOT OBJECT_ID('#SysProcessDataId') IS NULL BEGIN DROP TABLE #SysProcessDataId END CREATE TABLE #SysProcessDataId (Id uniqueidentifier) INSERT INTO #SysProcessDataId ([Id]) SELECT DISTINCT SysProcessData.Id FROM SysProcessLog JOIN SysProcessData on SysProcessLog.SysSchemaId = SysProcessData.SysSchemaId WHERE SysProcessData.ParentId IS NULL AND CONVERT(date, SysProcessLog.StartDate) >= CONVERT(date, @StartDate) and CONVERT(date, SysProcessLog.StartDate) <= CONVERT(date, @EndDate) AND SysProcessLog.Name = @ProcessName AND SysProcessLog.StatusId = 'ED2AE277-B6E2-DF11-971B-001D60E938C6' DECLARE SysProcessDataIdCursor CURSOR STATIC LOCAL FOR SELECT Id FROM #SysProcessDataId DECLARE @COUNT int = (SELECT COUNT_BIG(*) FROM #SysProcessDataId) IF (@COUNT > 50000) SET @COUNT = 50000 DECLARE @processDataId uniqueidentifier OPEN SysProcessDataIdCursor WHILE (@COUNT > 0) BEGIN FETCH NEXT FROM SysProcessDataIdCursor INTO @processDataId IF @@FETCH_STATUS = -1 BREAK IF @@FETCH_STATUS = -2 CONTINUE EXEC [dbo].[tsp_DeleteSysProcessDataById] @processDataId SET @COUNT = @COUNT - 1 END CLOSE SysProcessDataIdCursor DEALLOCATE SysProcessDataIdCursor IF NOT OBJECT_ID('#SysProcessDataId') IS NULL BEGIN DROP TABLE #SysProcessDataId END END GO
Скрипт на обновление:
SET QUOTED_IDENTIFIER ON GO IF NOT OBJECT_ID('[dbo].[tsp_UpdateSysProcessLogById]') IS NULL BEGIN DROP PROCEDURE [dbo].[tsp_UpdateSysProcessLogById] END GO CREATE PROCEDURE [dbo].[tsp_UpdateSysProcessLogById] @SysProcessLogId uniqueidentifier AS BEGIN SET NOCOUNT ON DECLARE @sysProcessLogRecordsToDelete TABLE (Id uniqueidentifier) INSERT INTO @sysProcessLogRecordsToDelete ([Id]) SELECT Id FROM SysProcessLog WHERE ParentId = @SysProcessLogId OPTION (OPTIMIZE FOR (@SysProcessLogId UNKNOWN)) DECLARE @COUNT int = (SELECT COUNT(*) FROM @sysProcessLogRecordsToDelete) WHILE (@COUNT) != 0 BEGIN DECLARE @parentId uniqueidentifier = (SELECT TOP 1 Id from @sysProcessLogRecordsToDelete) Update SysProcessLog Set StatusId=( select id from SysProcessStatus where id = '1BE78F3E-234D-4D6A-869A-DC07253FD2F3' ) Where id =@parentId EXEC [dbo].[tsp_UpdateSysProcessLogById] @parentId SET @COUNT = @COUNT - 1 END Update SysProcessLog Set CompleteDate = GETUTCDATE(), StatusId=( select id from SysProcessStatus where id = '1BE78F3E-234D-4D6A-869A-DC07253FD2F3' ) Where id =@SysProcessLogId AND StatusId = 'ED2AE277-B6E2-DF11-971B-001D60E938C6' UPDATE SysProcessElementLog Set StatusId = (select Id from SysProcessStatus where Id = '1BE78F3E-234D-4D6A-869A-DC07253FD2F3'), CompleteDate = GETUTCDATE() where SysProcessId = @SysProcessLogId and StatusId= 'ED2AE277-B6E2-DF11-971B-001D60E938C6' END GO SET QUOTED_IDENTIFIER ON GO IF NOT OBJECT_ID('[dbo].[tsp_UpdateSysProcessLogByStartDate]') IS NULL BEGIN DROP PROCEDURE [dbo].[tsp_UpdateSysProcessLogByStartDate] END GO CREATE PROCEDURE [dbo].[tsp_UpdateSysProcessLogByStartDate] @ProcessName nvarchar(MAX), @StartDate datetime, @EndDate datetime AS BEGIN SET NOCOUNT ON IF NOT OBJECT_ID('#SysProcessLogId') IS NULL BEGIN DROP TABLE #SysProcessLogId END CREATE TABLE #SysProcessLogId (Id uniqueidentifier) INSERT INTO #SysProcessLogId ([Id]) SELECT Top 100000 SysProcessLog.Id FROM SysProcessLog WHERE SysProcessLog.ParentId IS NULL AND CONVERT(date, SysProcessLog.StartDate) >= CONVERT(date, @StartDate) AND CONVERT(date, SysProcessLog.StartDate) <= CONVERT(date, @EndDate) AND SysProcessLog.Name = @ProcessName CREATE TABLE #SysProcessExec (Id uniqueidentifier) INSERT INTO #SysProcessExec ([Id]) SELECT Top 100000 SysProcessLog.Id FROM SysProcessLog WHERE SysProcessLog.ParentId IS NULL AND CONVERT(date, SysProcessLog.StartDate) >= CONVERT(date, @StartDate) AND CONVERT(date, SysProcessLog.StartDate) <= CONVERT(date, @EndDate) AND SysProcessLog.Name = @ProcessName AND SysProcessLog.StatusId = 'ED2AE277-B6E2-DF11-971B-001D60E938C6' DECLARE SysProcessLogIdCursor CURSOR STATIC LOCAL FOR SELECT Id FROM #SysProcessLogId DECLARE @COUNT int = (SELECT COUNT_BIG(*) FROM #SysProcessLogId) DECLARE @processLogId uniqueidentifier OPEN SysProcessLogIdCursor WHILE (@COUNT > 0) BEGIN FETCH NEXT FROM SysProcessLogIdCursor INTO @processLogId IF @@FETCH_STATUS = -1 BREAK IF @@FETCH_STATUS = -2 CONTINUE EXEC [dbo].[tsp_UpdateSysProcessLogById] @processLogId SET @COUNT = @COUNT - 1 END CLOSE SysProcessLogIdCursor DEALLOCATE SysProcessLogIdCursor INSERT INTO MassCancellationProcessesLog (StartDate, EndDate, DisableProcessCount, Process) VALUES(CONVERT(date, @StartDate), CONVERT(date, @EndDate), (SELECT COUNT(*) FROM #SysProcessExec), @ProcessName) IF NOT OBJECT_ID('#SysProcessLogId') IS NULL BEGIN DROP TABLE #SysProcessLogId END IF NOT OBJECT_ID('#SysProcessExec') IS NULL BEGIN DROP TABLE #SysProcessExec END END GO