9

列 を持つツリー テーブルがあり、にID依存する列値を生成したいと考えています。この目的のために、トリガーを使用します。階層列の値を生成するより良い方法はありますか?ParentIDHierarchyHierarchyParentID

ALTER TRIGGER [TR_MyTable_BeforInsert] ON [MyTable]
INSTEAD OF INSERT
AS BEGIN
SET NOCOUNT ON;
Declare @Name NVarChar(100),
        @ParentID Int

Declare DACategory Cursor For
Select  A.Name, A.ParentID
From    Inserted A
OPEN    DACategory
FETCH NEXT FROM DACategory INTO @Name, @ParentID
While @@FETCH_STATUS=0 Begin

    Insert Into MyTable (Name, ParentID, Hierarchy)
    Values (@Name, @ParentID, dbo.F_MyTableGetHID(NULL, @ParentID))

    FETCH NEXT FROM DACategory INTO @Name, @ParentID
End
Close   DACategory
Deallocate DACategory
END

関数 :

ALTER FUNCTION [F_MyTableGetHID]
(
    @ID int,
    @ParentID int
)
RETURNS HierarchyID

AS BEGIN
    Declare @RootHID HierarchyID, 
            @LastHID HierarchyID

    IF (@ParentID IS NULL)Begin
        Set @RootHID = HierarchyID::GetRoot()
        Select @LastHID = Max(Hierarchy) From MyTable Where ParentID IS NULL
    End Else Begin
        Select @RootHID = Hierarchy From MyTable Where ID = @ParentID
        select @LastHID = Max(Hierarchy) From MyTable where ParentID = @ParentID
    End
    return @RootHID.GetDescendant(@LastHID, NULL)
END

このテーブルを更新するには、ParentID変更時に階層列を再度設定するトリガーもあります。

この問題のベストプラクティスは何ですか?

EDIT 1 :可能であればトリガーを使用しないソリューションを探します。

4

5 に答える 5

3

両方の質問に答えるには、別のアプローチがあります。データベースに不必要なオーバーヘッドが追加されるため、通常、最後の選択肢になるまでトリガーの使用を避けます。

トリガーとストアド プロシージャの比較

  • テーブルのリレーションシップ、制約、インデックス、データベース内のストアド プロシージャを表示するのは簡単ですが、トリガーは表示するのが困難です。
  • トリガーは、クライアント アプリケーション アプリケーションからは見えずに実行されます。これらは表示されないか、デバッグ コードで追跡できます。
  • トリガーのことは忘れがちです。ドキュメントがないと、新しい開発者がトリガーの存在を理解するのが難しくなります。
  • データベース フィールドが更新されるたびにトリガーが実行され、システムのオーバーヘッドになります。システムの実行が遅くなります。

これが、私がストアド プロシージャを好む理由です。エージェント経由でジョブ ファイルを作成できます (例: 30 分ごと、またはその他の時間ごとに実行)。そのジョブ ファイルに挿入するためのロジックを使用できます。このようにして、のデータはtree tableほぼリアルタイムになります。

エージェントを作成するための参照:
http://msdn.microsoft.com/en-us/library/ms191128(v=sql.90).aspx
http://msdn.microsoft.com/en-us/library/ms181153 (v=sql.105).aspx

于 2012-08-04T08:20:23.570 に答える
1

あなたはベストプラクティスを求めました。

ベスト プラクティスは、隣接リスト モデル (お持ちのもの) を使用せず、代わりにネストされたセット モデルに切り替えることです。

コード化して理解するのが難しいため、それほど普及していませんが、はるかに柔軟です。

于 2012-08-03T10:15:07.047 に答える
1

このコンテキストでは、カーソルなしでトリガーを使用する必要があります

ALTER TRIGGER [TR_MyTable_BeforInsert] ON [MyTable]
INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    Insert Into MyTable (Name, ParentID, Hierarchy)
    Select Name, ParentID, dbo.F_MyTableGetHID(NULL, ParentID)
    From inserted
END
于 2012-08-04T18:50:41.793 に答える
1

親への外部キーを指定して、hierarchyid 値を計算する関数を作成できます。次に、この関数を列のデフォルト値計算機として呼び出すことができます。ユーザーがこの列に挿入できないようにすると、デフォルト値が常に適用されます。

このソリューションは、親子関係が更新できない場合にのみ機能します。

于 2012-08-06T05:12:11.313 に答える
0

カーソルはいらない

ただ使う

Insert Into MyTable (Name, ParentID, Hierarchy) 
 select Name, ParentID, dbo.F_MyTableGetHID(NULL, ParentID)   
  from inserted

機能を説明できますか-それが何をしているのかはわかりません。ただし、クエリに変換できるため、上記と組み合わせることができるように見えます-ベストプラクティスは、リレーショナルデータベースで常に集合論を行うことです

于 2012-08-05T22:16:26.647 に答える