Обработка исключений в скриптах

zhenya17

Добрый день.Задача: Почистить все таблицы, имеющие определённое поле по некоторому условию (пусть в нашем примере условием служит то, что значение нужного поля >99). База на MSSQL 2000.Выдержка из скрипта:
SET @cc = CURSOR FOR
	select distinct so.[name] tableName
	from syscolumns col
	join sysobjects so on so.id = col.id
	where upper(col.[name]) = 'НАЗВАНИЕ_ПОЛЯ' and so.xtype = 'U'
	order by so.[name]
OPEN @cc
FETCH NEXT FROM @cc INTO @table
WHILE @@FETCH_STATUS = <b>0</b>
BEGIN
	Execute('delete from ' + @table + ' where isnull(НАЗВАНИЕ_ПОЛЯ,0)>99')
	if @@rowcount><b>0</b> print 'Удалены записи из таблицы ' + @table
	FETCH NEXT FROM @cc INTO @table
END
На некотором шаге происходит ошибка и скрипт обрубается:Server: Msg 30002, Level 16, State , Procedure tD_hrtb_doc_id_hr_doc_hrtb_docparam, Line 18Нельзя удалять запись из таблицы <Название_таблицы>, так как существуют связанные с ней данные в таблице <Название_связанной_таблицы>.Вопрос такой: можно ли в sql-скрипте как-то обработать исключения? Мне важно, чтобы скрипт не прекращался на ошибке, а продолжал чистить остальные таблицы. Понятно, что я могу в скрипте вручную прописать названия таких таблиц, на которых спотыкается скрипт, но очень не хотелось бы этим заниматься, т.к. в структуре базы более 1000 таблиц.Пыталась найти ответ в BOL, но там ни try, ни catch, ни exception нет. Дальше моя фантазия закончилась :)
10 ответов

zhenya17

zhenya17,проверяйте ещё наличие FK, ссылающихся на таблицу.И не пытайтесь удалять из таблицы, на которую такие ссылки есть.


zhenya17

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


zhenya17

Разве что сразу сделать скрипт в 2 прохода: сначала чистить таблицы без FK, а потом - с FK... Или в запросе для курсора поставить сортировку по признаку есть/нет FK, а потом уже по имени...И всё-таки обработки ошибок в T-SQL нет?


zhenya17

iap, мне этот вариант не подходит.Дело в том, что если бы скрипт доработал до конца, то большинство связанных таблиц у меня уже было бы очищено. Потом бы я запустила скрипт повторно и дочистились бы те таблицы, на которых появляется ошибка при первой прогонке скрипта.
А сразу написать скрипт, который начнет удалять данные с самого "дна", не судьба ?


zhenya17

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


zhenya17

Glory, судьба, конечно. Скорее всего, так и поступлю... просто сразу это в голову не пришло. Но хочется параллельно и свой кругозор расширить, узнав, есть ли возможность обрабатывать ошибки
Обработка ошибок сильно зависит от версии сервера. Которую вы не сообщили.Или вы пишите универсальный скрипт для всех версий ?


zhenya17

iap, мне этот вариант не подходит.Дело в том, что если бы скрипт доработал до конца, то большинство связанных таблиц у меня уже было бы очищено. Потом бы я запустила скрипт повторно и дочистились бы те таблицы, на которых появляется ошибка при первой прогонке скрипта.
Почему же подходит?Просто надо правильно задать порядок удаления, исходя из существующих FK.Фактически. пролучится обход дерева, узлы которого представляют собой таблицы, а ветвями служат связи по FK.И не просто установить наличие FK, а в команде DELETE предусмотреть проверку, не существуютли записи, ссылающиеся на удаляемые. Типа
DELETE P WHERE NOT EXISTS(SELECT * FROM F WHERE F.ID_P=P.ID)


zhenya17

iap, спасибо за помощь. Примерно так и делаю.Что касается обработки исключений, то нашла следующее (http://www.interface.ru/home.asp?artId=4425):Новые возможности T-SQL в MS SQL Server 2005 (исходники):В связи с интеграцией SQL Server с платформой .NET, языки которой поддерживают гибкий механизм обработки исключений, разработчики SQL Server включили в T-SQL давно желанную SQL-программистами возможность обработки исключений.
BEGIN TRY
 -- "Опасный" запрос
END TRY
BEGIN CATCH
 -- Обработка ошибки
END CATCH
Стало быть, в mssql2000 этого нет.


zhenya17

В 2000 нет TRY CATCH , но например можно после каждого DML оператора осуществлять проверку
if @@error<><b>0</b>


zhenya17

... только перед этим надо сохранить код ошибки в переменной, иначе после проверкиif @@error<>0@@error сбросится в 0 и мы никогда уже не узнаем что за ошибка была.