2009-04-06 4 views
7

У меня есть ситуации, когда я хочу, чтобы проверить определенный столбец (например, номер версии), а затем применить кучу DDL измененийбегущие условные DDL заявления на SQL сервере

беда в том, я не могу сделать это с в блок IF BEGIN END, поскольку для операторов DDL требуется разделитель GO между ними, и TSQL не позволит этого.

мне интересно, если есть какой-нибудь способ, чтобы выполнить эту

ответ

0

GO признан клиентских программ, а не на сервере. Вы можете иметь CREATE в своих хранимых процедурах или специальных запросах без GO.

1

Несколько заявлений «IF»? Затем вы можете проверить успешность последующих заявлений DDL

Динамический SQL? EXEC ('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?

Как уже упоминалось, GO является клиентским разделителем пакетов для разбивки одного текстового блока SQL на партии, которые отправляются на SQL Server.

+0

динамический SQL станет грязным очень скоро, так как у меня есть динамический SQL внутри самих –

+0

OK процедур, несколько IF заявления затем ... – gbn

6

Вам не нужно использовать полный блок. Условие будет выполнять следующий оператор целиком, если вы не используете BEGIN/END - включая один оператор DDL. Это эквивалентно поведению , если в Pascal, C и т. Д. Конечно, это означает, что вам придется повторно проверять свое состояние снова и снова. Это также означает, что использование переменных для управления поведением сценария в значительной степени не может быть и речи.

[Edit: CREATE PROCEDURE не работает в приведенном ниже примере, поэтому я изменил его на что-то другое, и переехал CREATE PROCEDURE для более широкого обсуждения ниже]

If ((SELECT Version FROM table WHERE...) <= 15) 
CREATE TABLE dbo.MNP (
.... 
) 
GO 

If ((SELECT Version FROM table WHERE...) <= 15) 
ALTER TABLE dbo.T1 
ALTER COLUMN Field1 AS CHAR(15) 
GO 

... 

Или что-то подобное, в зависимости от вашего состояния.

К сожалению, CREATE/ALTER PROCEDURE и CREATE/ALTER VIEW имеют особые требования, из-за которых сложнее работать. Они в значительной степени обязаны быть единственной вещью в заявлении, поэтому вы не можете комбинировать их с IF вообще.

Для многих сценариев, когда вы хотите «обновить» свои объекты, вы можете работать как условная капля, за которым следует создать:

IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc'))) 
DROP PROCEDURE dbo.abc 
GO 

CREATE PROCEDURE dbo.abc 
AS 
    ... 
GO 

Если вы действительно нужны условная логика, чтобы решить, что делать , тогда единственный способ, которым я знаю, - использовать EXECUTE для запуска операторов DDL в виде строки.

If ((SELECT Version FROM table WHERE...) <= 15) 
EXECUTE 'CREATE PROC dbo.abc 
AS 
    .... 
') 

Но это очень больно. Вы должны избегать кавычек в теле процедуры, и ее действительно трудно прочитать.

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

Извините; нет простого «правильного» способа, который работает на все. Это просто то, что TSQL поддерживает очень плохо. Тем не менее, вышеприведенное должно быть хорошим началом.

+0

Если ((SELECT Version FROM таблицы WHERE ...) <= 15) CREATE PROCEDURE dbo.abc AS этот синтаксис не работает. Это говорит о некорректном синтаксисе рядом с ключевым словом «ПРОЦЕДУРА» –

+1

Вы верны! Сожалею. Видеть? Я сказал вам, что это беспорядочно (учит меня отвечать на вопрос в 2 часа ночи). T-SQL требует, чтобы CREATE PROC был ТОЛЬКО заявлением в «партии» (между GO). Я исправил образец выше и предоставил вам более подробную информацию о проблеме. Удачи. –

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