2008-09-10 5 views
20

Как часть моей стратегии интеграции, у меня есть несколько сценариев SQL, которые запускаются для обновления базы данных. Первое, что все эти сценарии сделать, это проверить, если они должны работать, например .:Как условно создать хранимую процедуру в SQL Server?

if @version <> @expects 
    begin 
     declare @error varchar(100); 
     set @error = 'Invalid version. Your version is ' + convert(varchar, @version) + '. This script expects version ' + convert(varchar, @expects) + '.'; 
     raiserror(@error, 10, 1); 
    end 
else 
    begin 
     ...sql statements here... 
    end 

Работает отлично! За исключением случаев, когда мне нужно добавить хранимую процедуру. Команда «create proc» должна быть единственной командой в группе команд sql. Ввод «create proc» в моей инструкции IF вызывает эту ошибку:

 
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. 

Ouch! Как поместить команду CREATE PROC в мой скрипт и выполнить ее только в том случае, если это необходимо?

ответ

20

Вот что я придумал:

Заверните его в EXEC(), например так:

if @version <> @expects 
    begin 
     ...snip... 
    end 
else 
    begin 
     exec('CREATE PROC MyProc AS SELECT ''Victory!'''); 
    end 

работает как шарм!

+2

Повторное создание procs каждый раз (условно снижается) является гораздо лучшим решением.Если вы используете exec, вы ничего не получаете и есть недостатки; ваш proc должен избегать строк, а любые номера строк в ошибках будут ссылаться на номер строки относительно команды exec. – Peter 2008-09-12 07:20:29

+0

+1 для того, чтобы справляться с условиями, отличными от существования (в моем случае @@ Version использует ли определенные procs или нет) – cmsjr 2009-06-24 17:16:28

+1

+1 - Я использовал это, чтобы настроить генератор CRUD для создания процедуры заглушки, если он еще не был существуют, а затем меняют его. Это позволяет мне изменить мои сохраненные procs, построить CRUD, но _preserve любые разрешения, назначенные против существующего procs_. – 2010-07-09 19:49:31

5

Но следите за одинарными кавычками в своей хранимой процедуре - они должны быть «экранированы», добавив второй. Первый ответ сделал это, но на всякий случай вы его пропустили. Ловушка для молодых игроков.

+0

Этот ответ должен быть комментарием. Почему бы вам не переместить его там? – Luiso 2015-12-16 15:32:14

3

Версии вашей базы данных - это путь, но ... Зачем условно создавать хранимые процедуры. Для представлений, хранимых процедур, функций, просто условно отбрасывать их и повторно создавать их каждый раз. Если вы условно создадите, то вы не будете очищать базы данных, у которых есть проблема или взлома, которые были добавлены еще 2 года назад другим разработчиком (вы или я этого никогда не сделаем), который был уверен, что он не забудет удалить одно время аварийное обновление.

1

Должен признаться, я бы обычно согласился с @Peter - я условно падал, а затем безоговорочно воссоздавал каждый раз. Я был пойман слишком много раз в прошлом, когда пытался угадать различия схем между базами данных, с или без контроля версий.

Сказав это, ваше собственное предложение @Josh довольно круто. Конечно, интересно. :-)

0

Проблема с удалением и созданием - вы теряете любые гранты безопасности, которые ранее были применены к отбрасываемому объекту.

0
IF NOT EXISTS(SELECT * FROM sys.procedures WHERE name = 'pr_MyStoredProc') 
BEGIN 

    CREATE PROCEDURE pr_MyStoredProc AS ..... 
    SET NOCOUNT ON 
END 

ALTER PROC pr_MyStoredProc 
AS 
SELECT * FROM tb_MyTable 
0

используйте команду «Exists» в T-SQL, чтобы узнать, существует ли сохраненный процесс proc. Если это так, используйте «Alter», иначе используйте «Create»

0

Это старый поток, но Jobo неверно: Create Procedure должен быть первым оператором в пакете. Поэтому вы не можете использовать Exists для проверки на существование, а затем используйте либо Create, либо Alter. Жалость.

4

SET поехес ON хороший способ, чтобы выключить какую-то часть кода

IF NOT EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SQL_CLR_Functions') 
    SET NOEXEC ON 
GO 
CREATE FUNCTION dbo.CLR_CharList_Split(@list nvarchar(MAX), @delim nchar(1) = N',') 
RETURNS TABLE (str nvarchar(4000)) AS EXTERNAL NAME SQL_CLR_Functions.[Granite.SQL.CLR.Functions].CLR_CharList_Split 
GO 
SET NOEXEC OFF 

Найдено здесь: https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch

P.S. Другой способ - SET PARSEONLY {ON | ВЫКЛ}.

Смежные вопросы