Как попытаться удалить записи без прерывания по ошибке - PullRequest
3 голосов
/ 31 октября 2011

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

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

Как мне написать скрипт, который пытается удалить каждую запись в таблице и не завершать оператор при первой ошибке?

С уважением,

непристойные

EDIT:

Причина, по которой я хотел бы сделать что-то подобное, заключается в том, что бизнес-пользователи добавили много повторяющихся данных (например: найдите кого-то и нажмите «Добавить как новое» вместо «Выбрать»). Теперь у нас может быть 10 человек, которые имеют только имя и не имеют отношения к другим таблицам. Я надеюсь, что это устраняет любую путаницу.

Ответы [ 4 ]

3 голосов
/ 01 ноября 2011

Я играл с разными идеями. Вот самый прямой путь. Тем не менее, это довольно дорого. Опять же, это попытка удалить неиспользованные дубликаты данных. 1000 записей заняли 8 минут. Кто-нибудь может придумать более эффективный способ сделать это?

DECLARE @DeletedID Int

DECLARE ItemsToDelete SCROLL CurSor For
SELECT ID FROM ParentTable

Open ItemsToDelete

FETCH NEXT FROM ItemsToDelete INTO @DeletedID
     While @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        --ATTEMPT TO DELETE
        DELETE FROM ParentTable WHERE ID = @DeletedID;
    END TRY 

    BEGIN CATCH
        --DO NOTHING
    END CATCH

        --FETCH NEXT ROW
    FETCH NEXT FROM ItemsToDelete INTO @DeletedID
END


Close ItemsToDelete

Deallocate ItemsToDelete
1 голос
/ 01 ноября 2011

Ну, каждый оператор в SQL рассматривается как транзакция, поэтому, если вы попытаетесь удалить несколько записей и столкнетесь с ошибкой с учетом правил целостности, каждое внесенное вами изменение будет откатываться.Что вы можете сделать, это написать запрос, который сначала удалит данные из ссылочной таблицы (таблица, которая имеет значение из внешнего ключа (в вашем случае это таблица T_child), а затем удалите данные из таблицы T_parent.

Всего:Сначала проверьте в таблице T_child записи, которые вы хотите удалить, а затем удалите записи из таблицы T_parent, чтобы избежать сбоя транзакции.

Надеюсь, это поможет.

(Исправьте меня, если я ошибаюсь)

1 голос
/ 01 ноября 2011

Здесь есть несколько вариантов.В вашем вопросе есть некоторая двусмысленность, поэтому я хочу сначала повторить ваш вариант использования (и я отвечу на ваш вопрос, как я его понимаю).

Вариант использования

База данных состоит из нескольких таблиц T_Parent, T_Child1, T_Child2, T_Child3.Полный набор данных будет иметь записи во всех 4 таблицах.Учитывая бизнес-требования, мы часто получаем частичные данные, которые необходимо удалить позднее.Например, T_parent и T_Child2 могут получать данные, но не TC1 и TC3.

Мне нужно иметь возможность проверить частичные данные и, если они найдены, удалить все частичные данные (в моем примере это T_Parent и T_Child 2, но это могут быть TP и TC3 или другие комбинации).


@ ribald - Правильно ли мое понимание?

  • Прокомментируйте мое понимание, и я напишу ответ.Если комментарии не длинные или недостаточно четкие, просто отредактируйте свой вопрос.
  • вы сказали «каскад» в терминах удаления (что означает очень специфическую вещь в SQL-сервере), но в вашем последующем описании это звучитбольше похоже на то, что вы хотите удалить все частичные данные.
  • «Каскадирование» - это то, что доступно, но на самом деле это не то, что вы включаете и выключаете в зависимости от условий некоторых данных.
  • когда вы говорили «набор данных», вы не имели в виду ADO.NET Dataset, вы только что имели в виду тестовые данные.
  • Я полагаю, вы не ищете хороший способ тестирования, вы просто хотите убедиться, что у вас есть целостность данных.
1 голос
/ 01 ноября 2011

Возьмем это с точки зрения соли: на самом деле я не администратор баз данных и никогда не работал с SQL Server.Тем не менее:

Здесь вы на самом деле сталкиваетесь с двумя разными правилами:

  1. Ссылочные ограничения
  2. Специфичные для бизнеса (я предполагаю) 'delete-allow'rules.

Звучит так, как когда были установлены ссылочные ограничения (в дочерних таблицах), они были созданы с опцией RESTRICT или NO ACTION.Это означает, что попытка удаления из родительской таблицы приведет к ошибке при наличии дочерних строк.Но выгода заключается в том, что вы хотите, чтобы в конкретной таблице разрешалось удалять и распространять их (опция CASCADE).Таким образом, для только тех таблиц, для которых удаление должно распространяться, измените ссылочное ограничение для использования CASCADE.В противном случае предотвратите удаление с (уже существующей) ошибкой.

Что касается работы с возникающими исключениями ... вот несколько способов справиться с ними:

  1. Предсказать их.Напишите свое удаление таким образом, чтобы не удаляло что-либо, если ключ указан в наборе дочерних таблиц.Очевидно, что это невозможно поддерживать в долгосрочной перспективе или для таблицы с большими ссылками.
  2. Поймать исключение.Я сомневаюсь, что их можно поймать «в скрипте» (особенно если запускается один файл типа .txt), поэтому вам, вероятно, придется по крайней мере написать хранимую процедуру или запустить язык более высокого уровня.Вторая проблема здесь заключается в том, что вы не можете «пропустить» ошибку и «продолжить» удаление (о чем я знаю) - SQL будет держать с ошибками каждый раз (... onчто составляет случайный ряд).Вам нужно было бы перебрать весь файл весь , по строке (или, возможно, набор строк, динамически), чтобы обеспечить удаление записи.Для небольшого файла (относительно) это может работать.
  3. Создать (набор) динамических операторов, использующих таблицы и поиски информационной схемы для исключения идентификаторов, включенных в «не удаляемые»Таблицы.Интересная концепция, но потенциально сложная / дорогая.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...