Могу ли я иметь внешний ключ, ссылающийся на столбец в представлении в SQL Server? - PullRequest
76 голосов
/ 15 января 2009

В SQL Server 2008 и

TableA(A_ID, A_Data)
TableB(B_ID, B_Data)
ViewC(A_or_B_ID, A_or_B_Data)

можно ли определить TableZ(A_or_B_ID, Z_Data) так, чтобы столбец Z.A_or_B_ID был ограничен значениями, найденными в ViewC? Можно ли это сделать с внешним ключом против вида?

Ответы [ 7 ]

95 голосов
/ 15 января 2009

Нельзя ссылаться на представление во внешнем ключе.

23 голосов
/ 10 марта 2013

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

15 голосов
/ 15 января 2009

Если вам действительно нужно A_or_B_ID в TableZ, у вас есть два похожих варианта:

1) Добавьте в таблицу z столбцы A_ID и B_ID, которые можно обнулять, сделать A_or_B_ID вычисляемый столбец, используя ISNULL для этих двух столбцов, и добавить ограничение CHECK, чтобы только один из A_ID или B_ID не равно нулю

2) Добавьте столбец TableName в таблицу z, ограниченный, чтобы содержать либо A, либо B. Теперь создайте A_ID и B_ID как вычисляемые столбцы, которые являются ненулевыми, когда их соответствующая таблица названа (используя выражение CASE ). Заставь их сохраниться тоже

В обоих случаях теперь у вас есть столбцы A_ID и B_ID, которые могут иметь соответствующие иностранные ключи к базовым таблицам. Разница в том, какие столбцы вычисляются. Вас также не нужно TableName в варианте 2 выше, если домены столбцов 2 ID не перекрытие - до тех пор, пока ваше выражение регистра может определить, какой домен A_or_B_ID падает в

(Спасибо за комментарий для исправления моего форматирования)

8 голосов
/ 15 января 2009

Извините, вы не можете использовать FK для представления в SQL Server.

4 голосов
/ 28 июля 2012

Есть еще один вариант. Обрабатывайте TableA и TableB как подклассы новой таблицы с именем TablePrime. Отрегулируйте значения идентификаторов TableB, чтобы они не совпадали со значениями идентификаторов TableA. Сделайте ID в TablePrime PK и вставьте все TableA и TableB (скорректированные) идентификаторы в TablePrime. Сделайте так, чтобы TableA и TableB имели связи FK на своих PK с одним и тем же идентификатором в TablePrime.

Теперь у вас есть шаблон супертипа / подтипа, и вы можете наложить ограничения на TablePrime (когда вы хотите -A-or-B ) или одну из отдельных таблиц (когда вы хотите только ) A или только B ).

Если вам нужна дополнительная информация, пожалуйста, спросите. Существуют варианты, которые позволят вам убедиться, что A и B являются взаимоисключающими, или, может быть, то, с чем вы работаете, может быть одновременно одновременно. Лучше формализовать это в ФК, если это возможно.

1 голос
/ 13 августа 2018

К сожалению, В строгом смысле этого слова нет, вы не можете устанавливать внешние ключи на представления. Вот почему:

InnoDB - единственный встроенный механизм хранения для MySQL, который имеет внешние ключи. Любая таблица InnoDB будет зарегистрирована в information_schema.tables с engine = 'InnoDB'.

Представления, будучи зарегистрированными в information_schema.tables, имеют механизм хранения NULL. В MySQL нет механизмов, позволяющих иметь внешние ключи в любой таблице с неопределенным механизмом хранения.

Спасибо!

1 голос
/ 29 декабря 2015

Проще добавить ограничение, которое ссылается на пользовательскую функцию, которая выполняет проверку за вас, fCheckIfValueExists (columnValue), которая возвращает true, если значение существует, и false, если его нет.

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

Недостатком является то, что оптимизатор не может использовать все свои трюки с внешним ключом.

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