Как исправить ограничения внешнего ключа - PullRequest
0 голосов
/ 11 апреля 2019

Я создаю базу данных тестов с несколькими вариантами ответов, и при попытке создать таблицу CorrectAnswer я получаю следующую ошибку:

Сообщение 1785, Уровень 16, Состояние 0, Строка 15 Введение ограничения FOREIGN KEY 'FK__CorrectAn__Answe__5BE2A6F2' в таблицу 'CorrectAnswer' может привести к возникновению циклов или нескольких каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION, либо измените другие ограничения FOREIGN KEY. Сообщение 1750, уровень 16, состояние 1, строка 15 Не удалось создать ограничение или индекс. Смотрите предыдущие ошибки.

CREATE DATABASE PeriodicTableQuiz

CREATE TABLE Question(
QuestionID INT IDENTITY(1,1) PRIMARY KEY,
QuizQuestion VARCHAR(MAX) DEFAULT NULL
);

CREATE TABLE AnswerChoices(
AnswerID INT IDENTITY(1,1) PRIMARY KEY,
Answer VARCHAR(MAX) DEFAULT NULL,
QuestionID INT NOT NULL,
FOREIGN KEY(QuestionID) REFERENCES Question(QuestionID) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE CorrectAnswer(
CorrectAnswerID INT IDENTITY(1,1) PRIMARY KEY,
QuestionID INT NOT NULL,
FOREIGN KEY(QuestionID) REFERENCES Question(QuestionID) ON DELETE CASCADE ON UPDATE CASCADE,
AnswerID INT NOT NULL,
FOREIGN KEY(AnswerID) REFERENCES AnswerChoices(AnswerID) ON DELETE CASCADE ON UPDATE CASCADE
);

Я хочу вставить вопросы в таблицу вопросов, а ответы - в таблицу ответов. CorrectAnswer должен иметь QuestionID и AnswerID, ссылающихся на таблицы Question и AnswerChoices соответственно.

Ответы [ 2 ]

0 голосов
/ 11 апреля 2019

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

  • , удаление будет каскадно пересылаться непосредственно на AnswerChoices
  • , удаление будет каскадно пересылаться прямо в CorrectAnswer, и потому что CorrectAnswer и AnswerChoices имеют требуемый один-ко-многимОтношение с включенным каскадным удалением затем будет каскадно переходить из AnswerChoices в CorrectAnswer

Итак, у вас есть два пути каскадного удаления из Вопроса в CorrectAnswer - что вызывает исключение.

Вы должны либо сделатьопция QuestionId необязательна хотя бы в одной из таблиц.

Я предлагаю следующее:

CREATE DATABASE PeriodicTableQuiz

CREATE TABLE Question(
QuestionID INT IDENTITY(1,1) PRIMARY KEY,
QuizQuestion VARCHAR(MAX) DEFAULT NULL
);

CREATE TABLE Answer(
AnswerID INT IDENTITY(1,1) PRIMARY KEY,
Answer VARCHAR(MAX) DEFAULT NULL,
);

CREATE TABLE CorrectAnswer(
CorrectAnswerID INT IDENTITY(1,1) PRIMARY KEY,
QuestionID INT NOT NULL,
FOREIGN KEY(QuestionID) REFERENCES Question(QuestionID) ON DELETE CASCADE ON UPDATE CASCADE,
AnswerID INT NOT NULL,
FOREIGN KEY(AnswerID) REFERENCES AnswerChoices(AnswerID) ON DELETE CASCADE ON UPDATE CASCADE
);

Теперь у CorrectAnswer есть отношение один ко многим.Удаление вопроса удалит правильные строки ответа.Ответ теперь может быть связан с различными вопросами.

Опять же, от ваших требований зависит, является ли ответ дочерним или зависимым от вопроса.

0 голосов
/ 11 апреля 2019

Хотя это правда, что вам просто не нужен столбец QuestionID в CorrectAnswer, поскольку он является избыточным, и следующая схема решит текущую проблему:

CREATE TABLE dbo.CorrectAnswer(
CorrectAnswerID INT IDENTITY(1,1) PRIMARY KEY,
AnswerID INT NOT NULL,
FOREIGN KEY(AnswerID) REFERENCES dbo.AnswerChoices(AnswerID) 
  ON DELETE CASCADE ON UPDATE CASCADE
);

Я предлагаю этот дизайн вместо:

CREATE TABLE dbo.Questions
(
  QuestionID INT IDENTITY(1,1) PRIMARY KEY,
  Question VARCHAR(MAX) DEFAULT NULL
);

CREATE TABLE dbo.Answers
(
  AnswerID INT IDENTITY(1,1) PRIMARY KEY,
  Answer VARCHAR(MAX) DEFAULT NULL,
  QuestionID INT NOT NULL,
  IsCorrectAnswer bit NOT NULL,
  CONSTRAINT FK_Question FOREIGN KEY(QuestionID) 
    REFERENCES dbo.Questions(QuestionID) 
    ON DELETE CASCADE ON UPDATE CASCADE
);

Ограничение не может обеспечить правильность только одной строки для каждого вопроса, но вы можете применить это через триггер (изменение области действия для этого вопроса). Выполнение по крайней мере одной строки может быть немного сложнее (очень похоже на обеспечение того, что строка должна существовать в CorrectAnswer в исходном проекте, потому что, когда вы можете это сделать?), Просто потому, что это будет означать, что у вас есть сначала вставить правильный ответ.

Возможно, вам также нужны некоторые метаданные для определения порядка выбора, появляющегося в тесте, особенно если вы намереваетесь вставить правильные / неправильные ответы в некотором предсказуемом порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...