Загрузка данных
USE [myNewVasya];
SET NOCOUNT ON;
DECLARE @subscriber sysname =
N'WIN-5ODCFIGQRP3\SQL2016SQL';
DECLARE @destination sysname = N'replTransVas';
DECLARE @publication sysname = N'V3Trans';
DECLARE @jobName sysname =
N'WIN-5ODCFIGQRP3\SQL20-myNewVasya-V3Trans-WIN-5ODCFIGQRP3\SQL20-3';
DECLARE @program nvarchar(128) =
N'WIN-5ODCFIGQRP3_myNewVasya_V3Trans';
DECLARE @pubId int, @subscriberId int;
DECLARE @jobId uniqueidentifier;
DECLARE @deadline datetime2;
DECLARE @rc int;
IF CONVERT(sysname, SERVERPROPERTY('ServerName')) <> @subscriber
BEGIN
;THROW 50001, N'Неверный экземпляр SQL Server.', 1;
END;
IF @@TRANCOUNT <> 0
BEGIN
;THROW 50002, N'Запустите блок вне открытой транзакции.', 1;
END;
SELECT @pubId = pubid
FROM dbo.syspublications
WHERE name = @publication
AND immediate_sync = 0
AND allow_anonymous = 0;
SELECT @subscriberId = server_id
FROM sys.servers
WHERE name = @subscriber;
SELECT @jobId = job_id
FROM msdb.dbo.sysjobs
WHERE name = @jobName;
IF @pubId IS NULL OR @subscriberId IS NULL OR @jobId IS NULL
BEGIN
;THROW 50003, N'Настройки публикации, подписчика или задания отличаются от ожидаемых.', 1;
END;
-- Подтверждаем соответствие двух статей исходным таблицам.
IF
(
SELECT COUNT(*)
FROM dbo.sysarticles
WHERE pubid = @pubId
AND
(
(artid = 142 AND name = N'sb_answer'
AND objid = OBJECT_ID(N'dbo.sb_answer'))
OR
(artid = 143 AND name = N'sb_answerData'
AND objid = OBJECT_ID(N'dbo.sb_answerData'))
)
) <> 2
BEGIN
;THROW 50004, N'Статьи отличаются от показанных на снимке.', 1;
END;
-- Сохраняем состав и состояние остальных подписок публикации.
DECLARE @otherSubscriptions TABLE
(
artid int,
srvid int,
dest_db sysname,
subscription_type int,
status int
);
INSERT INTO @otherSubscriptions
SELECT s.artid, s.srvid, s.dest_db,
s.subscription_type, s.status
FROM dbo.syssubscriptions AS s
JOIN dbo.sysarticles AS a ON a.artid = s.artid
WHERE a.pubid = @pubId
AND NOT
(
a.artid IN (142, 143)
AND s.srvid = @subscriberId
AND s.dest_db = @destination
);
IF NOT EXISTS
(
SELECT 1
FROM @otherSubscriptions
WHERE srvid = @subscriberId
AND dest_db = @destination
)
BEGIN
;THROW 50005, N'Не найдены остальные статьи нужной подписки.', 1;
END;
-- 1. Штатная остановка агента.
IF EXISTS
(
SELECT 1
FROM msdb.dbo.sysjobactivity
WHERE job_id = @jobId
AND session_id =
(SELECT MAX(session_id) FROM msdb.dbo.syssessions)
AND start_execution_date IS NOT NULL
AND stop_execution_date IS NULL
)
BEGIN
EXEC @rc = msdb.dbo.sp_stop_job @job_id = @jobId;
IF @rc <> 0
BEGIN
;THROW 50006, N'Не удалось запросить остановку агента.', 1;
END;
END;
-- 2. Ждем остановки задания и завершения SQL-сессий.
SET @deadline = DATEADD(SECOND, 60, SYSDATETIME());
WHILE
EXISTS
(
SELECT 1
FROM msdb.dbo.sysjobactivity
WHERE job_id = @jobId
AND session_id =
(SELECT MAX(session_id) FROM msdb.dbo.syssessions)
AND start_execution_date IS NOT NULL
AND stop_execution_date IS NULL
)
OR EXISTS
(
SELECT 1
FROM sys.dm_exec_sessions
WHERE program_name IN (@program, @jobName)
)
BEGIN
IF SYSDATETIME() >= @deadline
BEGIN
SELECT
N'WAITING_FOR_STOP' AS result,
N'Изменение подписок еще не выполнялось. Повторите блок позже.'
AS next_action;
SELECT
s.session_id,
s.program_name,
r.command,
r.wait_type,
r.blocking_session_id,
r.percent_complete
FROM sys.dm_exec_sessions AS s
LEFT JOIN sys.dm_exec_requests AS r
ON r.session_id = s.session_id
WHERE s.program_name IN (@program, @jobName);
RETURN;
END;
WAITFOR DELAY '00:00:02';
END;
BEGIN TRY
-- 3. Исключаем только sb_answer из конкретной подписки.
IF EXISTS
(
SELECT 1
FROM dbo.syssubscriptions
WHERE artid = 142
AND srvid = @subscriberId
AND dest_db = @destination
)
BEGIN
EXEC @rc = sys.sp_dropsubscription
@publication = @publication,
@article = N'sb_answer',
@subscriber = @subscriber,
@destination_db = @destination;
IF @rc <> 0
BEGIN
;THROW 50007, N'Не удалось исключить sb_answer.', 1;
END;
END;
-- 4. Исключаем только sb_answerData.
IF EXISTS
(
SELECT 1
FROM dbo.syssubscriptions
WHERE artid = 143
AND srvid = @subscriberId
AND dest_db = @destination
)
BEGIN
EXEC @rc = sys.sp_dropsubscription
@publication = @publication,
@article = N'sb_answerData',
@subscriber = @subscriber,
@destination_db = @destination;
IF @rc <> 0
BEGIN
;THROW 50008, N'Не удалось исключить sb_answerData.', 1;
END;
END;
-- 5. Обе целевые подписки должны отсутствовать.
IF EXISTS
(
SELECT 1
FROM dbo.syssubscriptions
WHERE artid IN (142, 143)
AND srvid = @subscriberId
AND dest_db = @destination
)
BEGIN
;THROW 50009, N'Подписка на одну из двух таблиц сохранилась.', 1;
END;
-- Остальные подписки должны сохраниться в прежнем состоянии.
IF EXISTS
(
SELECT artid, srvid, dest_db, subscription_type, status
FROM @otherSubscriptions
EXCEPT
SELECT s.artid, s.srvid, s.dest_db,
s.subscription_type, s.status
FROM dbo.syssubscriptions AS s
JOIN dbo.sysarticles AS a ON a.artid = s.artid
WHERE a.pubid = @pubId
)
BEGIN
;THROW 50010, N'Изменилось состояние другой подписки. Агент оставлен остановленным.', 1;
END;
-- 6. Запускаем доставку оставшихся статей.
EXEC @rc = msdb.dbo.sp_start_job @job_id = @jobId;
IF @rc <> 0
BEGIN
;THROW 50011, N'Статьи исключены, но запрос запуска агента не выполнен.', 1;
END;
SELECT
N'SUCCESS' AS result,
N'Исключены только sb_answer и sb_answerData из подписки replTransVas. Запуск агента запрошен.'
AS details,
SYSDATETIME() AS completed_at;
END TRY
BEGIN CATCH
SELECT
N'STOPPED_ON_ERROR' AS result,
ERROR_NUMBER() AS error_number,
ERROR_MESSAGE() AS error_message,
N'Изменения могли выполниться частично. Пришлите этот результат.'
AS next_action;
SELECT
a.name AS article_name,
s.dest_db,
s.status
FROM dbo.sysarticles AS a
JOIN dbo.syssubscriptions AS s ON s.artid = a.artid
WHERE a.pubid = @pubId
AND a.artid IN (142, 143)
AND s.srvid = @subscriberId
AND s.dest_db = @destination;
THROW;
END CATCH;