このような構造をテーブルに格納する方法の1つは、各エンティティの追加フィールドを定義することです。これにより、何らかの方法で祖先が決定されます。 したがって、常に祖先を知ることができ、単純な列挙により、階層ツリー全体を復元できます。 これは非常に一般的な方法であり、テーブルでツリー階層を表示する必要があるすべての場所で使用されます。
ただし、MS SQL DBMSの開発者は、MS SQL 2008の新しいバージョンで、ツリー階層を実装するための新しいタイプのデータストレージ階層 IDを提供しています。
はじめに
階層IDタイプはデータベースのシステムタイプであり、そのサイズはツリーの構造(深さ)とノードの子孫の平均数に応じて異なります。 MSDNには次の計算が示されています。100,000人の6レベルの階層を持つツリーの場合、hierarchyidは38ビットを取り、データベースは40ビットまたは5バイトに丸めます。 hierarchyidが占有できる最大サイズは892バイトです。
テーブル作成
まず、特定の会社の従業員の階層を格納する非常に単純なテーブルを作成します。
CREATE TABLE Table_1(
hierarchyid NOT NULLを非表示にしました
userId int NOT NULL 、
userName nvarchar(50) NOT NULL 、
CONSTRAINT PK_Table_1 プライマリ キーが クラスター化されました
(
[非表示] ASC
)) *このソースコードは、 ソースコードハイライターで強調表示されました。
テーブルには、hierarchyid、従業員ID、および彼の名前が含まれます。 次に、このテーブルで次の階層の担当者を再作成しようとします。
1イワノフ 2ペトロフ 7スミルノフ 8パプキン 3シドロフ 4ワセリン 5クルグロフ 6マス
階層を作成する
まず、hierrachiaのルートを作成します。
Table_1に挿入
値 (hierarchyid :: GetRoot()、1、 'Ivanov' ) *このソースコードは、 ソースコードハイライターで強調表示されました。
hierarchyid :: GetRoot()に注意してください-これは、常に階層ルートの識別子を返す静的メソッドです。
次に、子孫をルートレコードに追加します。
Id階層IDを 宣言します
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= hierarchyid :: GetRoot()
Table_1に挿入
値 (hierarchyid :: GetRoot()。GetDescendant(@id、 null )、2、 'Petrov' );
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= hierarchyid :: GetRoot()
Table_1に挿入
値 (hierarchyid :: GetRoot()。GetDescendant(@id、 null )、3、 'Sidorov' );
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= hierarchyid :: GetRoot()
Table_1に挿入
値 (hierarchyid :: GetRoot()。GetDescendant(@id、 null )、4、 'Vasechkin' );
*このソースコードは、 ソースコードハイライターで強調表示されました。
このコードでは、次のコードセクションが注目に値します。
- hid.GetAncestor(1)= hierarchyid :: GetRoot()-祖先(直接)がルートであるすべてのレコードを選択します。
- hierarchyid :: GetRoot()。GetDescendant(@id、null)-ツリールートの直接の子孫の最初のフリーな階層IDを選択します。 以下にパラメータの説明をします。
表に残りのすべてのエントリを記入して、図を完成させます。
@phId hierarchyidを宣言する
select @phId =( SELECT hid FROM Table_1 WHERE userId = 2);
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= @phId
Table_1に挿入
値 (@ phId.GetDescendant(@id、 null )、7、 'Smirnov' );
select @phId =( SELECT hid FROM Table_1 WHERE userId = 4);
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= @phId
Table_1に挿入
値 (@ phId.GetDescendant(@id、 null )、5、 'Kruglov' );
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= @phId
Table_1に挿入
値 (@ phId.GetDescendant(@id、 null )、6、 'Squares' );
select @phId =( SELECT hid FROM Table_1 WHERE userId = 7);
Id = MAX (非表示)を選択します
Table_1 から
ここで、 hid.GetAncestor(1)= @phId
Table_1に挿入
値 (@ phId.GetDescendant(@id、 null )、8、 'Pupkin' );
*このソースコードは、 ソースコードハイライターで強調表示されました。
記事内のすべてのコードは1つのスクリプトで実行する必要があることに注意してください。
このコードをすべて実行すると、次の図が表示されます
select hid.ToString()、hid.GetLevel()、* from Table_1 *このソースコードは、 ソースコードハイライターで強調表示されました。
/ 0 0x 1イワノフ / 1/1 0x58 2ペトロフ / 1/1/2 0x5AC0 7スミルノフ / 1/1/1/3 0x5AD6 8パプキン / 2/1 0x68 3シドロフ / 3/1 0x78 4ワセリン / 3/1/2 0x7AC0 5ラウンド / 3/2/2 0x7B40 6正方形 WIN-Z6U4ALRNDSU(WIN-Z6U4ALRNDSU \ Administrator):(8行が影響を受けます)
明らかに、選択されたデータは階層の構造を正確にコピーし、正しくソートされたデータを取得するために、parentIdを持つフィールドを介して一般に受け入れられている方法で階層が実装される場合に必要ないくつかのトリックに頼る必要はありませんでした。
ヘルパー関数
階層IDを使用する場合、MS SQL 2008にはいくつかの機能があります。 ここで、それぞれの目的を簡単に説明します。完全な説明については、ドキュメントを参照することをお勧めします。
- GetAncestor-祖先の階層IDを返します。祖先のレベルを指定できます。たとえば、1は直接の祖先を選択します。
- GetDescendant-子孫の階層IDを返します。出力で取得する必要がある特定の子孫を制御できる2つのパラメーターを取ります。
- GetLevel-階層IDレベルを返します。
- GetRoot-ルートレベルを返します。
- IsDescendant-パラメーターを介して渡された階層IDが子孫であるかどうかを確認します。
- 解析-階層IDの文字列表現を適切な階層IDに変換します。
- Reparent-現在の祖先を変更できます。
- ToString-階層IDを文字列表現に変換します。
おわりに
MS SQL 2008は、ツリー階層であるデータを保存する新しい方法を提供します。 これらの目的のために、階層要素への「パス」を含む階層IDタイプが導入されています。 データベースプログラマを支援するために、階層の表示の整理、データの移動、要素へのアクセス、新しい階層要素の追加を可能にする一連の補助機能が提供されます。
私の意見では、提案されたオプションは、parentIdフィールド(祖先)を介して階層データを保存する標準的な方法の優れた代替手段です。 hierarchyidを使用すると、最小限のコードを記述して階層構造を作成できます。