SQL Serverのビューの列を参照する外部キーを使用できますか?


84

SQL Server2008では

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_IDViewC

回答:


108

外部キーでビューを参照することはできません。


36
これはSQLサーバーの制限ですか、それとも不合理なことですか?
アーロンアノダイド2012年

1
@Brian私も、これがSQL Serverの制限なのか、それとも不合理なものなのかを知りたいと思っています。この時点で、FKサポートを取得するためだけにトリガーを使用してビューをエミュレートしようとしているからです(MySqlを使用していますが) )。
そり2012年

4
-これは、これらのフォローアップの質問に良い答えですstackoverflow.com/questions/3833150/...
クリスHalcrow

それがこれらの質問に対する良い答えであるかどうかはわかりません...それは別のDBMSに関するものであり、ビューはスキーマの詳細とユーザーの利便性を隠すために設計されたと言っています。まず、わかりました...しかし、これは、初期設計を超えた確かなユースケースを見つける最初のことではありません。第二に、FKがなぜそうしないのかわかりません。ビューは、テーブルから引き出す必要がない任意のクエリにすることができ、結合された定数の束にすることができます...その場合、外部キーはかなり賢明なようです。理由があれば、もっと深いものが欲しいと思います。
ジョージマウアー

27

古いSQLServerエディションでは、外部キーはトリガーを介してのみ可能でした。挿入された値が関連するテーブルの1つにも表示されるかどうかをチェックする挿入トリガーを作成することにより、カスタム外部キーを模倣できます。


3
StackOverflowへようこそ。回避策を提供しているので、あなたの回答に価値がありますが、正解は受け入れられたものであり、質問は4年以上前のものであるため、投票はしていませんが、このコメントなしで残したくありませんでした。
jachguate 2013年

16

A_or_B_IDTableZが本当に必要な場合は、次の2つの同様のオプションがあります。

1)null許容列A_IDB_ID列をテーブルzにA_or_B_ID追加し、これら2つの列にISNULLを使用して計算列を作成し、一方のみがA_IDまたはB_IDnullでないます。

2)AまたはBのいずれかが今作成含むように制約、表zにテーブル名の列を追加A_IDし、B_ID適切なテーブルに名前が付けられている場合にのみnull以外の列を、計算列として(CASE式を使用)。それらも持続させる

どちらの場合も、ベーステーブルへの適切な外部キーを持つことができる列がA_IDありB_IDます。違いは、列の計算方法です。また、2つのID列のドメインが重複しない場合は、上記のオプション2のTableNameは必要ありません。ただし、ケース式でどのドメインを判別できるかを判断できます。A_or_B_ID が該当する

(私のフォーマットを修正してくれたコメントに感謝します)


:バックティックでアンダースコアで入れ言葉 A_or_B_ID
ビルKarwin

私はレガシーシステムにいくつかの機能を追加することに取り組んでいます。これは古いものと新しいものを一緒にパッチするための素晴らしい方法です。ありがとうございました!
David Gunderson 2017年


4

別のオプションがあります。TableAとTableBをTablePrimeと呼ばれる新しいテーブルのサブクラスとして扱います。TableBのID値を調整して、TableAのID値と一致しないようにします。TablePrimeのIDをPKにし、TableAとTableBの(調整済み)IDをすべてTablePrimeに挿入します。TableAとTableBが、TablePrimeの同じIDに対してPKでFK関係を持つようにします。

これでスーパータイプ/サブタイプパターンが作成され、TablePrime(-Aまたは-Bが必要な場合)または個々のテーブルの1つ(AのみまたはBのみが必要な場合)に制約を加えることができます。

詳細が必要な場合はお問い合わせください。AとBが相互に排他的であることを確認できるバリエーションがあります。または、作業しているものが同時に両方である可能性があります。可能であれば、FKでそれを形式化するのが最善です。


2

チェックを行うユーザー定義関数を参照する制約を追加する方が簡単です。fCheckIfValueExists(columnValue)は、値が存在する場合はtrueを返し、存在しない場合はfalseを返します。

利点は、複数の列を受け取り、それらを使用して計算を実行し、nullを受け入れ、主キーに正確に対応しない値を受け入れたり、結合の結果と比較したりできることです。

欠点は、オプティマイザがすべての外部キートリックを使用できないことです。


1
欠点は、オプティマイザーがすべての外部キートリックを使用できないことです... ...そして、関数は挿入/更新するすべての行に対して実行されます(セットにはあまり良くありません)。
jimbobmcgee 2017年

0

申し訳ありませんが、厳密な意味では、ビューに外部キーを設定することはできません。理由は次のとおりです。

InnoDBは、外部キーを備えたMySQLの唯一の組み込みストレージエンジンです。すべてのInnoDBテーブルは、engine = 'InnoDB'でinformation_schema.tablesに登録されます。

ビューは、information_schema.tablesに登録されていますが、NULLストレージエンジンを備えています。MySQLには、未定義のストレージエンジンを持つテーブルに外部キーを持つメカニズムはありません。

ありがとう!


この質問はSQLサーバーに関するものです
George Mauer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.