という名前のデータベースにこの自己参照テーブルがNodes
あり、組織のツリー構造を格納するために使用されます。
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[ParentId] [int] NULL,
(+ other metadata columns)
そこから、HIERARCHYID を使用して、アクセス レベルなどに基づいてクエリを管理しています。私はこのためのテーブル値関数を作成しましtvf_OrgNodes
た。かなり前に、SQL Server 2008 から 2014 年までテストおよび作業を行いましたが、それ以来変更されていません。ただし、パス nvarchars ("/2/10/8/") から HIERARCHYID を解析すると、次のエラーが発生し、Google で 4 つのヒット (!) しか一致しないため、何かが変更されました。
Msg 6522, Level 16, State 2, Line 26
A .NET Framework error occurred during execution of user-defined routine or aggregate "hierarchyid":
Microsoft.SqlServer.Types.HierarchyIdException: 24000: SqlHierarchyId operation failed because HierarchyId object was constructed from an invalid binary string.
実際の HIERARCHYID の代わりに NVARCHAR のみを返すように関数を変更すると/
、ルートから始まり、その後に続くパスなど、すべてのパスが正常に見えます/2/
。単に選択するだけHIERARCHYID::Parse('path')
でも正常に動作します。INSERT が関数の結果になるまでパスを文字列のままにして、そこでパスを解析することで、実際に関数を機能させました。しかし、残念ながら、結果のデータを同じスキーマのテーブルに挿入しようとすると、同じエラーが発生します。
質問は、これはバグですか、それとも、HIERARCHYID<->パス文字列を操作する際にこれを引き起こす可能性のある (新しい?) 落とし穴を知っている人はいますか? バイナリ文字列全体のアイデアがどこから来たのかわかりません。
これは TVF のコードです。
CREATE FUNCTION [dbo].[tvf_OrgNodes] ()
RETURNS @OrgNodes TABLE (
OrgNode HIERARCHYID,
NodeId INT,
OrgLevel INT,
ParentNodeId INT
) AS
BEGIN
WITH orgTree(OrgNode, NodeId, OrgLevel, ParentNodeId) AS (
-- Anchor expression = root node
SELECT
CAST(HIERARCHYID::GetRoot() AS varchar(180))
, n.Id
, 0
, NULL
FROM Nodes n
WHERE ParentId IS NULL -- Top level
UNION ALL
-- Recursive expression = organization tree
SELECT
CAST(orgTree.OrgNode + CAST(n.Id AS VARCHAR(180)) + N'/' AS VARCHAR(180))
, n.Id
, orgTree.OrgLevel + 1
, n.ParentId
FROM Nodes AS n
JOIN orgTree
ON n.ParentId = orgTree.NodeId
)
INSERT INTO @OrgNodes
SELECT
HIERARCHYID::Parse(OrgNode),
NodeId,
OrgLevel,
ParentNodeId
FROM orgTree;
RETURN;
END
最近、lolz 用に .NET 4.53 aka 4.6 をインストールした可能性があります。ただし、reg を除いてどこにもその証拠は見つかりません: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319\SKUs.NETFramework,Version=v4.5.3