Измените строку, которая находится под ограничением внешнего ключа

#sqlite

Вопрос:

У меня есть таблица с целочисленными столбцами, как показано ниже. Назначение столбцов bexParentID и bexParentTypeID состоит в том, чтобы быть ограниченным внешним ключом для других строк в той же таблице, т. Е. (bexParentID,bexParentTypeID) Иметь составное ограничение FK для (bexID,bexTypeID) одной и той же таблицы.

Это сценарий создания:

 CREATE TABLE [main].[Boolean_Expressions](
  [bexID] INTEGER PRIMARY KEY NOT NULL, 
  [bexTypeID] INTEGER NOT NULL, 
  [bexParentID] INTEGER NOT NULL, 
  [bexParentTypeID] INTEGER NOT NULL, 
  FOREIGN KEY([bexParentID], [bexParentTypeID]) REFERENCES [Boolean_Expressions]([bexID], [bexTypeID]),
  UNIQUE([bexID], [bexTypeID]);
 

дизайн стола

Вот пример данных, которые могут появиться в этой таблице. данные

Как мне обновить тип строки (назовите ее A), в которой есть ограничения внешнего ключа из строк B, C, D…? Это нарушение-обновлять родительский тип строк B, C, D…, и это также нарушение-обновлять тип в первом.

Я могу думать только о том, чтобы «указать» B, C, D…. на другую строку, изменив их родительский идентификатор и родительский тип, чтобы указать на совершенно другую строку (назовите ее X), затем изменив тип A, затем «указав» B, C, D… обратно на A.

Ответ №1:

Добавьте ON UPDATE CASCADE к ограничению FK:

 FOREIGN KEY([bexParentID], [bexParentTypeID]) REFERENCES [Boolean_Expressions]([bexID], [bexTypeID]) ON UPDATE CASCADE
 

Эффект: достаточно обновить родительскую строку; все зависимые дочерние строки будут обновлены до одного и того же значения.

Комментарии:

1. Собирался предложить это, но я не могу вспомнить, как использовал составной индекс FK, поэтому не собирался предлагать без его тестирования.

2. Да, это работало с таблицей выше и другими таблицами, которые имели такое же ограничение FK для нее. Ваш ответ приведет меня к КАСКАДУ ОБНОВЛЕНИЙ, потому что раньше я не знал о предложениях FK.

Ответ №2:

Два варианта, которые могли бы быть проще.

а) Выключите внешние ключи до обновления, а затем включите их после обновления. Использование «PRAGMA foreign_keys = выключено» и «PRAGMA foreign_keys = включено»

  • = false (выкл.) или = true (вкл.) или = 0 (выкл.) или = 1 (вкл.) (любое значение, большее 0, включено)
  • примечание не может быть эффективно использовано (иначе это NOP) внутри транзакции.

напр.

 PRAGMA foreign_keys = off;
UPDATE ....;
PRAGMA foreign_keys = on;
 

или

б) Используйте отложенные внешние ключи, то есть включайте:-

 DEFERRABLE INITIALLY DEFERRED
 

В определении(определениях) внешнего ключа.

напр.

 bexParentID INTEGER NOT NULL REFERENCES mytable1(bexID) DEFERRABLE INITIALLY DEFERRED 
 

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

 BEGIN TRASNACTION;
UPDATE ....;
END TRANSACTION;
 

Комментарии:

1. Спасибо! отсрочка была тем, чего я добивался. Я пока не могу проголосовать, извините 🙂