Как протестировать SQLCMD в сценарии SQL без выполнения сценария

#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 в противном случае. Извините за мой английский