ПРИМЕЧАНИЕ ДЛЯ ЧИТАТЕЛЕЙ: Пожалуйста, прочитайте весь вопрос, включая пример кода (т.е. не только заголовок). Этот вопрос не о том, как лучше прокрутить базы данных, и не о том, почему [tempdb] получает эту ошибку. OP уже пытается избежать выполнения ALTER
операторов во всех системных базах данных (ну, в 4 видимых) и спрашивает, почему оператор IF, который должен пропускать [tempdb], по-видимому, не пропускает его.
Почему следующий скрипт выдает ошибку, связанную с tempdb?
Причина в том, что IF
оператор влияет только на то, что происходит, когда код фактически выполняется, но SQL Server все еще должен анализировать и компилировать пакет перед его выполнением. Ошибки синтаксического анализа связаны с синтаксисом, например, с обеспечением правильности формирования операторов SQL и правильного объявления переменных:
-- parse the following by hitting Control-F5 or clicking the check mark in SSMS
SELECT @Bob;
получает следующую ошибку:
Msg 137, Level 15, State 2, Line 2
Must declare the scalar variable "@Bob".
И следующее:
-- parse the following by hitting Control-F5 or clicking the check mark in SSMS
CREATE TABLE b
получает следующую ошибку:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'b'.
Если пакет успешно анализируется, он компилируется, и в это время проверяются такие вещи, как разрешения, и выполняются некоторые другие проверки.
-- parse the following by hitting Control-F5 or clicking the check mark in SSMS
IF (1 = 0)
BEGIN
ALTER AUTHORIZATION ON DATABASE::[tempdb] TO [sa];
ALTER DATABASE [tempdb] SET RECOVERY SIMPLE;
END;
Вышеуказанный SQL сформирован правильно, поэтому пакет успешно анализируется. Теперь попробуйте выполнить вышеупомянутый SQL, нажав F5 или Control-E или ! Кнопка Выполнить и т. Д.
На этот раз вы получите следующую ошибку:
Msg 5058, Level 16, State 1, Line 4
Option 'RECOVERY' cannot be set in database 'tempdb'.
хотя он IF (1 = 0)
гарантирует, что код никогда не будет запущен. Это означает, что вы столкнулись с ошибкой компиляции. Вы можете обойти эти типы ошибок, перемещая нарушающий код в подпроцесс посредством EXEC
вызова.
Выполните следующее, и оно будет успешно завершено, так как то, что находится внутри EXEC()
, не анализируется и не компилируется, пока этот оператор не будет выполнен во время выполнения.
IF (1 = 0)
BEGIN
EXEC('
ALTER AUTHORIZATION ON DATABASE::[tempdb] TO [sa];
ALTER DATABASE [tempdb] SET RECOVERY SIMPLE;
');
END;
Подводя итог: во-
первых, учтите, что sp_MSForEachDB
циклически проходит через базы данных и выполняет ваш переданный SQL после замены на ?
имя текущей базы данных. Таким образом, когда курсор внутри sp_MSForEachDB
получает [tempdb]
, он фактически делает следующее:
IF ( (select database_id from sys.databases where name = ''tempdb'') > 4)
BEGIN
ALTER AUTHORIZATION ON DATABASE::tempdb TO [sa];
ALTER DATABASE [tempdb] SET RECOVERY SIMPLE;
END
Во-вторых, SQL Server выполняет несколько шагов при выполнении пакета запроса:
- Анализировать
- Compile
- Фактическое исполнение
Важно понимать, что это отдельные этапы, которые могут вызвать ошибки перед переходом к следующему этапу (и, следовательно, отменить дальнейшую обработку перед переходом к следующему этапу). В данном случае ошибка происходит в Шаге 2 - Компиляция - как доказано во втором и последнем примере выше (первый, с которого нужно начинать IF (1 = 0)
). Функция IF (1 = 0)
предотвращает BEGIN...END
запуск кода внутри блока, но ошибка все равно возникает. Следовательно, ошибка не происходит из-за фактической попытки выполнить два ALTER
оператора.
Причина того, что перенос ALTER
операторов внутри EXEC()
функции работает, заключается в том, что SQL Server не будет анализировать и компилировать то, что находится внутри, до тех EXEC()
пор, пока он не EXEC()
будет запущен. В этот момент IF ( (select database_id from sys.databases where name = ''?'') > 4)
оператор будет иметь возможность работать , так как партия не будет терпеть неудачу во время компиляции и сделает его исполнение, и IF
оператор будет пропускать [tempdb]
и «Option„RECOVERY“не может быть установлена в базе данных" данных TempDb»ошибка не произойдет.
IF
оператор, ни любые другие операторы SQL (включая дваALTER
) не выполняются в этот момент.IF
Заявление не позволяет ID TempDb, чтобы быть направлены на то , что находится внутриBEGIN
/END
блока, и код даже не запустивALTER
заявления на данный момент. Ошибка генерируется SQL Server, поскольку он проверяет SQL перед его выполнением. Я добавил сводный раздел до конца.Прежде всего, нет необходимости использовать
ms_foreachdb
его недокументированный, и вы можете зацикливаться на нем, используя простой курсор. Что касается ошибки, вы пытаетесь изменить модель восстановления всей базы данных,including tempdb
но вы не можете изменить модель восстановления базы данных tempdb, а также не можете выполнить какую-либо операцию резервного копирования, поэтому вы получили это сообщение об ошибке. Это не разрешено Microsoft. Пожалуйста, прочитайте больше об операциях, которые вы можете выполнять на базе данных tempdb.источник
ALTER
заявления просто быть проверены , не выполняются. Я предоставляю подробности в моем ответе .Помимо того, что вы не можете изменить параметр восстановления для базы данных tempdb, вам не нужен цикл для того, что вы делаете:
Запустите в SSMS, нажав CTRL+T
источник