所以我的数据库中有一个名为 的自引用表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.
将函数更改为仅返回 NVARCHAR 而不是实际的 HIERARCHYID 时,路径看起来都很好,从/
根目录开始,然后是/2/
等等。简单地选择HIERARCHYID::Parse('path')
也可以正常工作。实际上,我通过将路径作为字符串一直保留到 INSERT 到函数结果中,并在那里解析路径,从而使函数正常工作。但是,当我尝试将重新生成的数据插入到相同模式的表中时,我得到了同样的错误。
所以问题是,这是一个错误,还是有人知道使用 HIERARCHYIDs<->Path 字符串可能导致这种情况的任何(新的?)陷阱?我不明白整个二进制字符串的想法来自哪里。
这是 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