Transact SQL: как создать двусторонние ограничения внешнего ключа?

#sql #sql-server #tsql #foreign-keys

#sql #sql-сервер #tsql #внешние ключи

Вопрос:

Допустим, у меня есть две таблицы: A и B

A имеет один столбец, который является первичным ключом B , т. Е. Внешним ключом, и B имеет один столбец, который является первичным ключом A , т. Е. Внешним ключом.

Итак, я бы сделал

 CREATE TABLE A(
 idA INT PRIMARY KEY,
 idB INT FOREIGN KEY REFERENCES B(idB)
);

CREATE TABLE B(
 idB INT PRIMARY KEY,
 idA INT FOREIGN KEY REFERENCES A(idA)
);

 

и ожидал бы, что это сработает; однако среда sql server Management Studio выдает мне следующую ошибку:
Foreign key references invalid table for table B
Если я поменяю их порядок местами, вместо этого в таблице появится ошибка A .

Как мне преодолеть эту проблему, учитывая, что у меня есть двусторонние отношения, то A есть ссылки B и B ссылки A .

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

1. Попробуйте сначала создать таблицы, а затем добавить FK после создания таблиц (поскольку вы пытаетесь создать ключ в таблице, которая еще не существует при создании таблицы A

2. У меня есть назначение, для которого требуется один скрипт со всей информацией о таблице создания. Разве нет способа сделать это?

3. Вы не можете ссылаться на таблицу, которую вы еще не создали (или Patterson пакет). SQL является последовательным, поэтому вторая таблица не будет существовать при выполнении первого оператора. Создайте оба, затем используйте ALTER TABLE инструкцию для добавления обоих ограничений с именем, отличным от имени по умолчанию.

Ответ №1:

Вы должны выполнить первое ограничение с помощью отдельного ALTER TABLE , поскольку справочная таблица еще не определена. В этом случае SQL не имеет понятия «прямой ссылки».

 CREATE TABLE A (
 idA INT PRIMARY KEY,
 idB INT
);

CREATE TABLE B (
 idB INT PRIMARY KEY,
 idA INT FOREIGN KEY REFERENCES A(idA)

);

ALTER TABLE A
    ADD CONSTRAINT FK_A_B FOREIGN KEY (idB) REFERENCES B(idB);
 

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

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

Вот скрипка db<> .

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

1. Если позволите, что это такое FK_B_A .

2. @DuarteArribas . , , Это имя ограничения. Вы обнаружите, что встроенные имена довольно непостижимы.

3. Если это ответ на вопрос, @DuarteArribas, вы должны принять это как решение.

Ответ №2:

Итак, я вижу, что люди собираются ответить на этот вопрос, не задавая очевидного вопроса:

Почему циклическая ссылка?

Возможно, мне не хватает какого-то блестящего дизайна, но идея, что вы размещаете PK на одном столе, а затем делаете обратное, кажется ДЕЙСТВИТЕЛЬНО плохим дизайном. Я открыт для обучения, но это звучит как катастрофа.

В общем:

  • При использовании метода «один ко многим» одна таблица является родительской или подстановочной, а другая имеет FK для этой таблицы
  • При использовании «один к одному» вы обычно вводите идентификатор (подкласс) в заблуждение, поэтому в каждой таблице может быть только один. Или вы перепроектируете и создаете единую таблицу.
  • Вы можете ограничить с помощью других средств, но у вас все еще есть циклическая концепция в вашей схеме

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

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

1. Задания, к сожалению / досадно / глупо / и т.д., Часто устанавливают нереалистичные и произвольные требования. Я бы не удивился, если бы это был один из них.

2. @Larnu — Моя большая проблема заключается в том, что когда кто-то спрашивает: «Как мне врезаться в мою машину на скорости 90 миль в час без ремня безопасности и не умереть», и кто-то на самом деле отвечает на вопрос, а не спрашивает: «Чего ты пытаешься достичь?» Когда говорят «Я хочу произвести впечатление на свою девушку», правильный ответ — «купить ей цветы», а не «набить себе подушки»