Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
iii2
Member

Откуда:
Сообщений: 202
Проблема следующая:
Хочу включить и сделать доверенными констрейнты на куче таблиц (и в куче баз, но это не существенно).
Действую примитивно, через динамический sql:

-- в целевых таблицах включим констрейнты 
Set @sql=(select 'ALTER TABLE ' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' WITH CHECK CHECK CONSTRAINT all; ' 
			from sys.tables T 
			inner join sys.schemas s on T.[schema_id] = s.[schema_id]
			where T.name like '[_]%'
			For xml path(''));

Exec sp_sqlexec @sql;

Можно ли сделать как то, чтобы выражение продолжалось после ошибки на каком то этапе, в каком то куске сгенерированного кода, или для этого придётся морочиться с курсором и TRY / Catch?

Я таким образом не только констрейнты включаю, и мне достаточно, чтобы в Messages красная строчка появилась, не более. Без затей, т.с.
3 ноя 17, 16:22    [20925414]     Ответить | Цитировать Сообщить модератору
 Re: Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
iii2
Member

Откуда:
Сообщений: 202
Чего то я угнал, коллеги.

-- в целевых таблицах включим констрейнты 
Set @sql=(select ' BEGIN TRY ALTER TABLE ' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' WITH CHECK CHECK CONSTRAINT all; Print ' 
			+ '''' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' checked'''
			+ ' END TRY BEGIN CATCH Print ERROR_MESSAGE () END CATCH; ' 
			from sys.tables T 
			inner join sys.schemas s on T.[schema_id] = s.[schema_id]
			where T.name like '[_]%'
			For xml path(''));

Exec sp_sqlexec @sql;


Вопрос снят :-)
3 ноя 17, 16:31    [20925451]     Ответить | Цитировать Сообщить модератору
 Re: Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1172
iii2,

лучше верните нам Машу :)
3 ноя 17, 16:38    [20925485]     Ответить | Цитировать Сообщить модератору
 Re: Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
iii2
Чего то я угнал, коллеги.

-- в целевых таблицах включим констрейнты 
Set @sql=(select ' BEGIN TRY ALTER TABLE ' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' WITH CHECK CHECK CONSTRAINT all; Print ' 
			+ '''' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' checked'''
			+ ' END TRY BEGIN CATCH Print ERROR_MESSAGE () END CATCH; ' 
			from sys.tables T 
			inner join sys.schemas s on T.[schema_id] = s.[schema_id]
			where T.name like '[_]%'
			For xml path(''));

Exec sp_sqlexec @sql;


Вопрос снят :-)

Вопрос cнят, но не совсем. Используйте TYPE, чтобы знаки > не преобразовывались в ерунду, и STUFF :)
declare @sql nvarchar(MAX)
Set @sql=(stuff(
(select 
N'BEGIN TRANSACTION;BEGIN TRY ALTER TABLE ' + Quotename(s.[name]) + '.' + Quotename(T.name) + ' WITH CHECK CHECK CONSTRAINT all END TRY BEGIN CATCH IF @@TRANCOUNT>0 ROLLBACK TRANSACTION;END CATCH;IF @@TRANCOUNT>0 COMMIT TRANSACTION;' 
			from sys.tables T 
			inner join sys.schemas s on T.[schema_id] = s.[schema_id]
			where T.name like '%_test%'
			--For xml path('')
			for XML PATH('')
, TYPE).value('.', 'NVARCHAR(MAX)') , 
             1, 0, '') 
);
--Exec sp_sqlexec @sql;
print @sql

+

Поддерживаю - верните Машу :)
3 ноя 17, 17:26    [20925664]     Ответить | Цитировать Сообщить модератору
 Re: Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
iii2
Member

Откуда:
Сообщений: 202
Andy_OLAP, гм...
Нет, не согласен. Точнее - формально, оно, конечно, правильно, а фактически на разовую задачу такие изыски не нужны.
1. В xml будут экранированы символы ' " < >. Но наличие их в именах объектов - жесть жестяная. У нас нет такого.
2. Alter table - вполне себе атомарная операция. Зачем ее обрамлять транзакцией? Мне как раз и нужно, включить все констрейнты, а потом те, которые получится - сделать доверенными. Поэтому я вначале запускаю конструкцию без With check, а потом с check. Кстати, WITH CHECK CHECK CONSTRAINT all, вроде как откатывается в случае, если не удается верифицировать какой то один констрейнт, так что, наверное, их лучше поименно включить.
3. Stuff зачем использовать? Начинать выражение с ; - вполне себе хорошая практика. Во-первых, по новым веяниям вообще ; становится обязательным символом. Во вторых - привыкнешь и точно не забудешь перед with поставить :-) В чем проблема то?

А Маша тут постоянно пишет. Только, вроде, не регистрируется. По крайней мере задачки с sql-ex - точно какое то время назад спрашивала. Только создание она хитрое, знает, что народ не любит в этом вопросе подсказывать, поэтому перефразирует. Ловил пару раз :-)
4 ноя 17, 20:04    [20927536]     Ответить | Цитировать Сообщить модератору
 Re: Существует ли способ заставить dynamic sql выражение не прерываться после ошибки?  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
iii2
Но наличие их в именах объектов - жесть жестяная. У нас нет такого.

Так и у нас нет такого. Петр Сергеевич, я же не для Вас это написал, Вы ведь понимаете, а чтобы те, кто читают, поняли, что без TYPE - это на скорую руку, а в целом dynamic sql + xml path позволяют делать интересные штуки :)
4 ноя 17, 23:20    [20927899]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить