hierarchyid (Transact-SQL)

hierarchyid データ型は可変長のシステム データ型です。hierarchyid は、階層内の位置を表すために使用します。hierarchyid 型の列が自動的にツリーを表すことはありません。行と行の間に必要なリレーションシップが反映されるよう、hierarchyid 値を生成して割り当てるのは、アプリケーションの役割です。

hierarchyid データ型の値は、ツリー階層における位置を表します。hierarchyid の値には、以下の特性があります。

  • 非常にコンパクト

    n 個のノードを持つツリー内の、1 つのノードを表すために必要な平均ビット数は、平均ファンアウト (ノードあたりの子の平均数) によって決まります。ファンアウトが小さい場合 (0-7)、サイズは約 6*logAn ビットです (A は平均ファンアウト)。平均ファンアウトが 6 レベルで、100,000 人から成る組織階層の場合、1 つのノードには約 38 ビットが必要です。格納時には、これが 40 ビット (5 バイト) に切り上げられます。

  • 深さ優先順で比較

    ab の 2 つの hierarchyid 値がある場合、a<b は、ツリーの深さ優先検査において a が b の前に来ることを意味します。hierarchyid データ型のインデックスは深さ優先順であり、深さ優先検査で近接するノードどうしは、相互に近接して格納されます。たとえば、あるレコードの子は、そのレコードに隣接して格納されます。詳細については、「hierarchyid データ型の使用 (データベース エンジン)」を参照してください。

  • 任意の挿入および削除のサポート

    GetDescendant メソッドを使用すると、指定したノードの右側や左側、または任意の 2 つの兄弟間に、いつでも兄弟を生成できます。階層に対して任意の数のノードを挿入または削除しても、比較の特性は維持されます。ほとんどの挿入や削除では、コンパクトさも維持されます。ただし、2 ノード間に挿入した場合は、hierarchyid 値のコンパクトさがやや失われます。

  • hierarchyid 型で使用されるエンコーディングは 892 バイトに制限されます。したがって、表現のレベルが多すぎて 892 バイトに収まらないノードについては、hierarchyid 型で表すことができません。

hierarchyid 型は、CLR クライアントで SqlHierarchyId データ型として利用できます。

説明

hierarchyid 型は、ツリーのルートからノードまでのパスをエンコードすることで、階層ツリーの 1 つのノードに関する情報を論理的にエンコードします。このようなパスは、ルートの後にアクセスされたすべての子の一連のノード ラベルとして論理的に表されます。この表現はスラッシュによって開始されます。ルートのみを表すパスは、単一スラッシュで表されます。ルートの下のレベルの各ラベルは、ドットで区切られた一連の整数としてエンコードされます。子と子の比較は、ドットで区切られた一連の整数を辞書順で比較することにより行われます。各レベルの後ろには、スラッシュが続きます。したがって、スラッシュは親と子を区切ります。たとえば、次に示すのは、長さがそれぞれ 1、2、2、3、3 レベルの有効な hierarchyid パスです。

  • /

  • /1/

  • /0.3.-7/

  • /1/3/

  • /0.1/0.2/

ノードは、任意の位置に挿入できます。/1/2/ の後ろで、かつ /1/3/ の前に挿入されたノードは、/1/2.5/ として表されます。0 の前に挿入されたノードの論理表現は、負の値となります。たとえば、/1/1/ の前に位置するノードは、/1/-1/ として表されます。ノードに先頭のゼロを付けることはできません。たとえば、/1/1.1/ は有効ですが、/1/1.01/ は無効です。エラーを回避するには、GetDescendant メソッドを使用してノードを挿入します。

データ型の変換

hierarchyid データ型は、次のように他のデータ型に変換できます。

  • hierarchyid 値を nvarchar(4000) データ型として論理表現に変換するには、ToString() メソッドを使用します。

  • hierarchyid を varbinary に変換するには、Read () および Write () を使用します。

  • hierarchyid から XML への変換はサポートされていません。SOAP 経由で hierarchyid パラメータを送信するには、最初にパラメータを文字列としてキャストします。FOR XML 句を含むクエリは、最初に列を文字データ型に変換しないと、hierarchyid を持つテーブルで失敗します。

データベースのアップグレード

データベースを SQL Server 2008 にアップグレードすると、新しいアセンブリおよび hierarchyid データ型が自動的にインストールされます。アップグレード アドバイザのルールにより、競合する名前を持つユーザー型またはアセンブリが検出されます。アップグレード アドバイザは、次のいずれかの方法によって、競合するアセンブリの名前の変更を推奨します。2 つの方法とは、競合する型の名前を変更するか、または 2 つの部分から構成される名前をコード内で使用して既存のユーザー型を参照するかのどちらかです。

データベースのアップグレード時に競合する名前を持つユーザー アセンブリが検出されると、このアセンブリの名前が自動的に変更され、データベースが問題のあるモードになります。

アップグレード時に競合する名前を持つユーザー型が検出された場合、特別な処理は実行されません。アップグレード後は、古いユーザー型と新しいシステム型の両方が存在することになります。ユーザー型は、2 つの部分から構成される名前を介してのみ使用できます。

レプリケートされたテーブルでの hierarchyid 列の使用

hierarchyid 型の列は、任意のレプリケートされたテーブルで使用できます。アプリケーションの要件は、レプリケーション方法や (単方向または双方向)、使用される SQL Server のバージョンによって異なります。

単方向レプリケーション

単方向レプリケーションには、サブスクライバ側で変更が行われないスナップショット レプリケーション、トランザクション レプリケーション、およびマージ レプリケーションが含まれます。hierachyid 列が単方向レプリケーションとどのように連携するかは、サブスクライバが実行されている SQL Server のバージョンによって異なります。

  • SQL Server 2008 パブリッシャは、hierachyid 列を SQL Server 2008 サブスクライバにレプリケートできます。特別な注意は必要ありません。

  • SQL Server Compact 3.5 SP2 または前バージョンの SQL Server を実行しているサブスクライバにレプリケートするには、SQL Server 2008 パブリッシャは、hierarchyid 列を変換する必要があります。SQL Server Compact 3.5 SP2 および前バージョンの SQL Server では、hierarchyid 列がサポートされません。このどちらかのバージョンを使用している場合でも、サブスクライバにデータをレプリケートすることは可能です。そのためには、互換性のあるデータ型に列を変換できるように、スキーマ オプションまたはパブリケーションの互換性レベル (マージ レプリケーションの場合) を設定する必要があります。詳細については、「レプリケーション トポロジにおける複数バージョンの SQL Server の使用」を参照してください。

どちらのシナリオでも、列のフィルタ選択はサポートされています。これには、hierarchyid 列をフィルタで除外する処理が含まれます。行のフィルタ選択は、フィルタが hierarchyid 列を含まない限りサポートされます。

双方向レプリケーション

双方向レプリケーションには、サブスクライバ側で変更が行われる、更新サブスクリプションを使用したトランザクション レプリケーション、ピア ツー ピア トランザクション レプリケーション、およびマージ レプリケーションが含まれます。レプリケーションを実行するには、hierarchyid 列を持つテーブルを双方向レプリケーション用に構成する必要があります。以下の要件および考慮事項に注意してください。

  • パブリッシャおよびすべてのサブスクライバで SQL Server 2008 を実行している必要があります。

  • レプリケーションでは、データはバイトとしてレプリケートされます。階層の整合性を保証するための検証は行われません。

  • レプリケート元 (サブスクライバまたはパブリッシャ) で変更が加えられた階層は、レプリケート先にレプリケートするときに維持されません。

  • hierarchyid 列のハッシュ値は、生成元のデータベースに固有です。したがって、パブリッシャ側とサブスクライバ側とで同じ値が生成され、異なる行に適用される可能性があります。レプリケーションではこの条件のチェックは行われません。また、IDENTITY 列に対して用意されているような値を区切るための組み込みの手段は、hierarchyid 列に対しては用意されていません。アプリケーションでは、このような検出されない競合を避けるために、制約またはその他のメカニズムを使用する必要があります。

  • サブスクライバ側で挿入された行が孤立する場合があります。挿入された行の親の行がパブリッシャ側で削除されている可能性があります。その結果、サブスクライバの行がパブリッシャ側で挿入されたときに検出されない競合が発生します。

  • 列フィルタでは、NULL 値が許容されない hierarchyid 列を除外できません。パブリッシャ側の hierarchyid 列には既定値がないので、サブスクライバからの挿入は失敗します。

  • 行のフィルタ選択は、フィルタに hierarchyid 列が含まれない限りサポートされます。