Как условно создать хранимую процедуру в SQL Server? - PullRequest
21 голосов
/ 11 сентября 2008

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

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.

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

Ответы [ 10 ]

21 голосов
/ 11 сентября 2008

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

Оберните его в EXEC (), вот так:

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

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

7 голосов
/ 15 апреля 2016

SET NOEXEC 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 SET PARSEONLY {ON | OFF}

5 голосов
/ 11 сентября 2008

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

3 голосов
/ 11 сентября 2008

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

2 голосов
/ 08 декабря 2008

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

1 голос
/ 04 апреля 2018

Мое решение состоит в том, чтобы проверить, существует ли proc, если да, то отбросьте его, а затем создайте proc (такой же ответ, как у @robsoft, но с примером ...)

IF EXISTS(SELECT * FROM sysobjects WHERE Name = 'PROC_NAME' AND xtype='P') 
BEGIN
    DROP PROCEDURE PROC_NAME
END
GO
CREATE PROCEDURE PROC_NAME
    @value  int
AS
BEGIN
    UPDATE  SomeTable
    SET     SomeColumn = 1
    WHERE   Value = @value
END
GO
1 голос
/ 21 февраля 2012

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

1 голос
/ 11 сентября 2008

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

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

0 голосов
/ 14 января 2009

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

0 голосов
/ 14 января 2009
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...