Подтвердить что ты не робот

Доступны ли циркулярные ссылки в базе данных?

Когда в базе данных допустимы циркулярные ссылки?

Теоретическая и практическая, любая помощь приветствуется.

4b9b3361

Ответ 1

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

Например, если у вас есть таблица пользователя и транзакции, пользователь может иметь указатель на свою последнюю транзакцию. Сначала необходимо вставить транзакцию, а затем обновить last_transaction_id до правильного значения. Хотя обе эти записи существуют, вы не можете их стереть, потому что user.last_transaction_id указывает на transaction.id и transaction.user_id указывает на user.id. Это означает, что пользователь без транзакций имеет значение null last_transaction_id. Это также означает, что вы должны удалить это поле, прежде чем сможете удалить транзакцию.

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

Ответ 2

Рассмотрим города и штаты. Каждый город существует в государстве. в каждом штате есть столица.

CREATE TABLE city (
  city  VARCHAR(32),
  state VARCHAR(32) NOT NULL,
  PRIMARY KEY (city),
  FOREIGN KEY (state) REFERENCES state (state)
);

CREATE TABLE state (
  state VARCHAR(32),
  capital_city VARCHAR(32),
  PRIMARY KEY (state),
  FOREIGN KEY (capital_city) REFERENCES city (city)
);

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

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

--Create state record
INSERT INTO state (state, capital_city) VALUES ('Florida', NULL);

--Create various city records
INSERT INTO city (city, state) VALUES ('Miami', 'Florida');
INSERT INTO city (city, state) VALUES ('Tallahassee', 'Florida');
INSERT INTO city (city, state) VALUES ('Orlando', 'Florida');

--Set one of the cities as the capital
UPDATE state SET capital_city = 'Tallahassee' WHERE state = 'Florida';

Ответ 3

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

Ответ 4

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

Если у вас есть отношения вроде:

create table foo_master (
       foo_master_id int not null primary key
      ,current_foo_id int
)


create table foo_detail (
       foo_detail_id int not null primary key
       foo_master_id int not null
)

alter table foo_master
  add constraint fk_foo_current_detail
      foreign key (current_foo_id)
      references foo_detail

alter table foo_detail
  add constraint fk_foo_master
      foreign key (foo_master_id)
      references foo_master

Тогда удаление записи может вызвать такую ​​проблему с курицей и агг из-за круговых зависимостей.

Лучшая схема для этого выглядит так:

create table foo_master (
       foo_master_id int not null primary key
)


create table foo_detail (
       foo_detail_id int not null primary key
       foo_master_id int not null
       is_current char (1)
)

alter table foo_detail
  add constraint fk_foo_master
      foreign key (foo_master_id)
      references foo_master

Это означает, что отношение не является циклическим, и текущая запись foo_detail все еще может быть идентифицирована.

Ответ 5

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

Ответ 6

Я видел круговые ссылки, сделанные по соображениям производительности. Это выглядит уродливым, но производительность может быть незначительной.

Пример: некоторые доски объявлений (я думаю, phpBB делает это) имеют lastpostid в таблице категорий, которая является ярлыком к последнему сообщению в потоке.

Это создает круг, в котором последнее сообщение имеет FK в таблице категорий, а таблица категорий имеет FK до последнего сообщения.

Как я уже сказал, мне это не очень нравится, но я это видел.

Ответ 7

редко я сталкиваюсь с соотношением 1:1, которое необходимо и налагает круговые отношения

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

Ответ 8

Я думаю, это не проблема, если вы используете базу данных только для записи. Если вы планируете использовать часть RUD CRUD, вы, вероятно, столкнетесь с (обычно избегаемыми) сложными проблемами при работе с ними.