#sql-server #powershell #sqlcmd
#sql-сервер #powershell #sqlcmd
Вопрос:
У меня есть большое хранилище SQL-скриптов в синтаксисе SQLCMD. Для каждого скрипта определено 0 или более $(SomeParam)
. У нас есть утилита, которая выполняет скрипты и передает значения для $(params)
, что, по сути, позволяет нам настраивать и автоматизировать сборки для широкого спектра моделей данных.
Иногда наш процесс сборки завершается с ошибкой, потому что в скрипте $(param)
указано значение, которое не настроено в нашей утилите. т. е. у нас нет значения для этого $(param)
набора
Я хотел бы выполнить тестовый запуск этих скриптов перед их выполнением. Тестовый запуск должен гарантировать, что все необходимое $(params)
было предоставлено скрипту. Сам SQL не должен выполняться — я просто хочу знать, доступен ли он для компиляции. Возможно ли этого достичь с помощью sqlcmd?
Рассмотренные альтернативы
Я рассмотрел одну альтернативу использования скрипта Powershell для поиска совпадений для всех $(param)
в файле (с использованием регулярных выражений) и перекрестной проверки этого по нашему списку параметров в утилите. Я бы предпочел сохранить всю функциональность либо в командной строке sqlcmd, либо в самих SQL-скриптах, если это возможно.
Комментарии:
1. Может быть заданием для
SET NOEXEC ON
.2. не могли бы вы предоставить дополнительный параметр по умолчанию, чтобы указать, что он выполняется в тестовом режиме. затем используйте этот флаг, чтобы выполнять содержащийся код только тогда, когда он не находится в тестовом режиме? это довольно грязное решение, которое я использовал раньше для проверки сценария без его запуска.
3. @JeroenMostert — Я думаю, что это, вероятно, лучший подход. Если вы можете немного расширить ответ, я пометю его как правильный.
Ответ №1:
SET NOEXEC ON
переводит SQL Server в режим, в котором инструкции анализируются и компилируются, но не выполняются, за исключением команды SET NOEXEC OFF
, которая возвращает все в исходное состояние. Итак, если инструкции в конечном итоге синтаксически недопустимы из-за отсутствия параметров, SET NOEXEC ON
перехватит это.
Существует важное ограничение на SET NOEXEC ON
. В документации ошибочно указано, что «этот параметр полезен для того, чтобы SQL Server проверял синтаксис и имена объектов в коде Transact-SQL при выполнении», но, на самом деле, при SET NOEXEC ON
SQL Server вообще не будет разрешать имена для большинства объектов. Следующий скрипт выполнит синтаксический анализ без ошибок:
SET NOEXEC ON;
GO
CREATE TABLE Foo(ID INT PRIMARY KEY);
GO
INSERT Fooo(ID) VALUES (5); -- Oops, typo
Это не означает, что имена вообще не разрешаются. Следующий сценарий все равно завершится неудачей:
SET NOEXEC OFF;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SET NOEXEC ON;
GO
SELECT dbo.Foo(); -- No error here, even though Foo can't be invoked this way
SELECT * FROM dbo.Foo(5); -- Error here: too many arguments specified
Можно сказать, что это справедливо, но:
SET NOEXEC ON;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SELECT * FROM dbo.Foo(5); -- No error, because Foo doesn't exist
Это SET NOEXEC ON
не может служить ни способом гарантировать, что сценарий полностью корректен, ни способом определить, что сценарий определенно недействителен. Пока вы знаете о его ограничениях, он все еще может быть полезен.
Существует еще один параметр, который действительно работает последовательно в отношении имен объектов: SET PARSEONLY ON
. Это не только не выполняет инструкции, но даже не компилирует их. Приведенный выше пример, который выдает ошибку с NOEXEC
, не выдаст ошибки с PARSEONLY
. Также выполняется следующее:
CREATE TYPE MyInt FROM INT;
GO
CREATE TABLE A(ID MyInt);
-- Error under NOEXEC since MyInt does not exist, no error under PARSEONLY
Итак, если все, что вы хотите проверить, это синтаксическую корректность, PARSEONLY
лучше, чем NOEXEC
.
Ответ №2:
Вы можете создать копию скрипта, автоматически инкапсулировать выполнение скрипта в транзакцию и ввести ошибку в конце скрипта. Он всегда выдает ошибку. Если ошибка вызвана ВАШЕЙ введенной ошибкой, значит, скрипт сработал идеально, или выведите ошибку param в противном случае. Извините за мой английский