回答:
自己参照テーブルに問題はありません。
深い(無限?)ネストされた階層の一般的なデータベース設計パターンです。
hierarchyid
タイプを導入しました。
ネクロマンシング。
正解は、どのデータベースエンジンとどの管理ツールに依存するかです。
例
を見てみましょう。レポートテーブルが
あり、レポートには親(カテゴリなどのメニューポイント)
を含めることができ、その親自体に親(たとえば、利益センタ)を含めることができ
ます。
自己参照エンティティ/階層と同様に、標準的な再帰関係の最も単純な例。
結果のSQL-Serverテーブルは次のとおりです。
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_T_FMS_Reports_T_FMS_Reports') AND parent_object_id = OBJECT_ID(N'dbo.T_FMS_Reports'))
ALTER TABLE dbo.T_FMS_Reports DROP CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.T_FMS_Reports') AND type in (N'U'))
DROP TABLE dbo.T_FMS_Reports
GO
CREATE TABLE dbo.T_FMS_Reports
(
RE_UID uniqueidentifier NOT NULL
,RE_RE_UID uniqueidentifier NULL
,RE_Text nvarchar(255) NULL
,RE_Link nvarchar(400) NULL
,RE_Sort int NOT NULL
,RE_Status int NOT NULL
,PRIMARY KEY CLUSTERED ( RE_UID )
);
GO
ALTER TABLE dbo.T_FMS_Reports WITH CHECK ADD CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports FOREIGN KEY(RE_RE_UID)
REFERENCES dbo.T_FMS_Reports (RE_UID)
-- ON DELETE CASCADE -- here, MS-SQL has a problem
GO
ALTER TABLE dbo.T_FMS_Reports CHECK CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
ただし、問題が発生し
ます。すべてのサブメニューポイントでメニューポイントを削除する必要がある場合、delete-cascadeを設定できません。MicrosoftSQL-Serverは再帰的なカスケード削除をサポートしないためです(一方で、PostGreSQLはグラフは循環的ではありません]。MySQLは再帰CTEをサポートしていないため、この種のテーブル構造はまったく好きではありません)。
そのため、削除の整合性/機能を爆破し、独自のコードまたはストアドプロシージャ(RDBMSがストアドプロシージャをサポートしている場合)にそのような機能を実装することを必須にします。
これは、(非自己参照)外部キー関係に従ってすべてのテーブルに対して削除ステートメントを実行することも、単純な選択を行うこともできないため、あらゆる種類の全自動動的データインポート/エクスポートを爆破することは間違いありません*そして、任意の順序ですべての行に挿入を作成します。
たとえば、SSMSを使用してINSERTスクリプトを作成すると、SSMSは外部キーを取得しないため、依存関係の親を挿入する前に、依存関係を持つエントリを挿入する挿入ステートメントを実際に作成します。 、外部キーが配置されているため。
ただし、適切なツールを使用した適切なデータベース管理システム(PostgreSQLなど)では、これは問題になりません。RDBMS(私はあなた、Microsoft、Oracle =?)、および/またはそのツールベルトに多くのお金を払っているからといって、それが適切にプログラムされているわけではありません。また、OpenSource(MySQLなど)を使用しても、このようなすばらしい特徴に耐性がありません。
古いことわざにもあるように、悪魔は細部に宿っています。
さて、このような問題を回避できなかったわけではありませんが、システムが複雑になる場合(200以上のテーブルなど)は、お勧めしません。
さらに、(ディルバートによって描かれた)通常の商用設定では、その時間は与えられません。
はるかに優れたアプローチは、より困難ですが、クロージャーテーブルです。
これには、MySQLでも機能するという追加のボーナスがあります。
一度クロージャー機能を実装すると、ほとんど時間をかけずに追加の場所で機能するようになります。
リレーションシップが実際に階層的であり、ネットワークリレーションシップではない場合(たとえば、部品表はネットワークリレーションシップであり、階層関係ではない場合)、それは良い考えです。
照会に時間がかかる場合があります。処理を高速化するために、クロージャーテーブルを使用できます。
http://karwin.blogspot.ca/2010/03/rendering-trees-with-closure-tables.html