Поскольку анализ команды USE осуществляется до фактического выполнения кода, можно предложить несколько вариантов, которые могут применяться для решения этой задачи, когда речь заходит о заключении, следует ли выполнять код (в зависимости от того, является ли целевая база данных основной репликой).

Задействуйте полностью динамический язык SQL. При одном упоминании об этой возможности я испытываю неловкость. Но как бы то ни было, идея состоит в том, что ВЕСЬ код заключается в оболочку и выполняется с помощью команд EXECUTE или sp_executesql — после решения вопроса о том, следует ли вообще выполнять этот код.

В сущности, это вполне возможно. Но поскольку данный вариант способен вызвать серьезные угрозы в плане безопасности, а также потому, что по мере усложнения заданий и операций управление процессами становится невероятно трудным, я не могу рассматривать это решение в качестве практически приемлемого.

Использование хранимых процедур для перенаправления. Это тоже не совсем надежный способ. На мой взгляд, он мало чем отличается от использования полностью динамического SQL — разве что этот вариант чуть лучше. Идея состоит в следующем. Вы можете создавать хранимые процедуры, скажем, в основной базе данных (тогда вам придется обеспечивать синхронизацию соответствующего кода на всех серверах вашей топологии AG). В этом случае шаги или логика вашего задания агента SQL Server смогут выполнять следующие операции: определять, является ли данный хост основным, после чего либо нормально завершать работу, либо продолжать обработку кода или операций, пытаясь выполнить что-то вроде EXEC master.dbo.DoJobLogic @ Params, @Etc, где тело этой хранимой процедуры dbo.DoJobLogic будет просто выполнять перенаправление с помощью кода вроде следующего: DELETE FROM

Опять-таки я не стал бы рекомендовать этот обходной маневр, но он возможен. Высока вероятность того, что вы сразу же столкнетесь с проблемами, даже при попытке выполнить операции INSERT, UPDATE, DELETE в таблицах, расположенных в другой базе данных (хотя здесь вы можете использовать SYNONMYMS— по-моему, это один из немногих случаев, где такой подход можно считать уместным). И вы, скорее всего, придете к выводу, что обслуживание (особенно с учетом всех перенаправлений) доставит вам немало хлопот. Поэтому я не стал бы рекомендовать и этот способ. Более того, я настоятельно рекомендую воздержаться от его использования (как и от применения динамического SQL).

Проверки с помощью добавления дополнительных шагов заданий. Этот вариант приемлем, но имеет свои недостатки (как будет показано ниже). Так или иначе, идея состоит в следующем. Если вам нужно выполнить задание агента SQL Server, состоящее всего из одного шага, вы добавляете новый шаг задания перед существующим шагом, чтобы этот новый шаг определял, выступает ли целевая база данных (для второго шага задания) в роли основной реплики на текущем сервере, а затем передавал управление второму шагу (если мы находимся на основном сервере) или завершал выполнение, если наш сервер не основной. Словом, процесс этот довольно запутанный, и я бы не хотел с ним связываться. Кроме того, для него характерны особенности, не соизмеримые с проблемами, типичными для подобных задач. Мы поговорим об этом подробнее чуть позже.

Отказаться от этого подхода и придумать что-нибудь другое. Вместо того чтобы, образно говоря, забивать в круглое отверстие квадратную затычку (то есть пытаться решить проблему с помощью оператора USE), мы можем взять на вооружение какой-нибудь другой подход. Иными словами, вместо того чтобы пытаться динамически определить, следует ли выполнять код после запуска системы, мы можем пойти по пути, описанному мной в одной из предыдущих статей, — просто синхронизировать задания по всем серверам и затем активировать или деактивировать их в зависимости от того, размешаются ли они на серверах, содержащих основную реплику. Да, здесь придется потрудиться. Зато этот метод не имеет ничего общего с теми сомнительными вариантами, которые предполагают «динамическое выявление целесообразности запуска кода в процессе исполнения».