Что вызывает ошибку несоответствия внешнего ключа? - PullRequest
11 голосов
/ 06 марта 2011

У меня есть база данных sqlite, структурированная следующим образом:

CREATE TABLE IF NOT EXISTS Patient 
( PatientId INTEGER PRIMARY KEY AUTOINCREMENT );

CREATE TABLE IF NOT EXISTS Event 
( 
PatientId INTEGER REFERENCES Patient( PatientId ),
DateTime TEXT,
EventTypeCode TEXT,
PRIMARY KEY( PatientId, DateTime, EventTypeCode )
);

CREATE TABLE IF NOT EXISTS Reading 
( 
PatientId INTEGER REFERENCES Patient( PatientId ),
DateTime TEXT REFERENCES Event (DateTime),
EventTypeCode TEXT REFERENCES Event (EventTypeCode),
Value REAL,
PRIMARY KEY( PatientId, DateTime, EventTypeCode )
);

Я вставляю пациента с Id # 1

, затем запускаю:

INSERT INTO Event (PatientId, DateTime, EventTypeCode) VALUES (1, '2011-01-23 19:26:59', 'R')

, который работает

затем я запускаю:

INSERT INTO Reading (PatientId, DateTime, EventTypeCode, Value) VALUES (1, '2011-01-23 19:26:59', 'R', 7.9)

и это дает мне несоответствие внешнего ключа.Идентификатор пациента во всех случаях равен 1, а дата и время совпадают во втором и третьем запросах.Я не понимаю, в чем заключается несоответствие, но я немного новичок в определении внешних ключей и не знаю, что делаю неправильно.

1 Ответ

35 голосов
/ 06 марта 2011

Я не знаком с SQLite, но немного Google'ing обнаружил это .Документация гласит:

Если схема базы данных содержит ошибки внешнего ключа, для определения которых требуется более одного определения таблицы, то эти ошибки не обнаруживаются при создании таблиц.Вместо этого такие ошибки не позволяют приложению подготовить операторы SQL, которые изменяют содержимое дочерних или родительских таблиц способами, использующими внешние ключи.Ошибки, сообщаемые при изменении содержимого, представляют собой «ошибки DML», а ошибки, сообщаемые при изменении схемы, - «Ошибки DDL».Таким образом, другими словами, неправильно настроенные ограничения внешнего ключа, которые требуют рассмотрения как дочернего, так и родительского, являются ошибками DML. Сообщение об ошибке на английском языке для ошибок DML внешнего ключа обычно представляет собой «несоответствие внешнего ключа» , но также может быть «нет такой таблицы», если родительская таблица не существует.Ошибки DML внешнего ключа могут сообщаться, если:

  • Родительская таблица не существует или
  • Столбцы родительского ключа, названные в ограничении внешнего ключа, не существуют, или
  • Столбцы родительского ключа, названные в ограничении внешнего ключа, не являются первичным ключом родительской таблицы и не подчиняются уникальному ограничению с использованием последовательности сортировки, указанной в CREATE TABLE, или
  • Дочерняя таблица ссылается на первичный ключ родительского элемента без указания столбцов первичного ключа, а количество столбцов первичного ключа в родительском элементе не соответствует количеству столбцов дочернего ключа.

Я подозреваю, что вы можете столкнуться с # 3 в этом списке.

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

  1. Reading.PatientId ссылался на Event.PatientId, чтобы на полный составной ключ из Event ссылались Reading, либо
  2. Добавить EventId автоинкремент, первичный ключ к таблице Event и использование его в качестве внешнего ключа в таблице Reading (чтобы у вас было только EventId и Value в Reading, и вы можете получить PatientId, DateTime, EventTypeCode из Event).

Я бы предложил # 2, чтобы вы могли избежать избыточности PatientId, DateTime и EventTypeCode в Event и Reading.

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