如何在同一记录上插入自动生成的标识值作为hierarchyid字段的一部分

时间:2015-01-28 00:33:58

标签: sql-server tsql hierarchical-data hierarchyid

我试图找到一种方法将记录插入到一​​个表中,该表使用新生成的Identity值作为其层次结构ID的一部分。以下sql演示了我想要做的事情,以及我设法最接近的事情。哪个是使用插入,然后在事务内部进行更新。我在提出初始层次结构ID方面遇到了麻烦,因为该字段存在唯一约束,我担心如果同时将2个元素添加到同一个父节点,则可能会抛出错误。 / p>

DECLARE @hierarchy_elements TABLE (
     id int IDENTITY (1, 1) NOT NULL ,
     element_path hierarchyid NOT NULL
)

-- Cheating here, but I need some data to append to.
INSERT INTO @hierarchy_elements(element_path)
SELECT ('/1/')
UNION ALL SELECT ('/1/2/')

-- See that we have a couple elements in the table.
SELECT id, element_path.ToString() as [path] from @hierarchy_elements

-- arbitrarily pick a parent to append to
DECLARE @parentElementId int = 2

-- grab that parent's path.
DECLARE @parentElementPath hierarchyid 
SELECT @parentElementPath = element_path FROM @hierarchy_elements WHERE id = @parentElementId

-- This is what I want to do.  Use the current id as the last part of the hierarchyid
INSERT INTO @hierarchy_elements (element_path)
VALUES(@parentElementPath.ToString() + CAST(scope_identity() AS VARCHAR(20)) + '/')

-- This works, but kind of sucks.
BEGIN TRANSACTION 

-- Insert under the parent with a known invalid id.
INSERT INTO @hierarchy_elements (element_path)
VALUES(@parentElementPath.ToString() + '-1/')

-- now update setting the last element in the hierarchyid to the id just generated.
UPDATE @hierarchy_elements 
SET element_path = @parentElementPath.ToString() + CAST(SCOPE_IDENTITY() AS VARCHAR(20)) + '/'
WHERE id = SCOPE_IDENTITY()

COMMIT TRANSACTION

-- See that id 3 would fail the unique constraint check, but id 4 is correct.
SELECT id, element_path.ToString() as [path] from @hierarchy_elements

如果可能,我想使用单个语句插入,它将在hierarchyid字段中包含新的Identity值。

1 个答案:

答案 0 :(得分:1)

解决问题的一般想法:

分别生成行的ID,记住它,然后在ID列中插入生成的ID,并使用相同的记忆值来组成element_path

如果您使用SQL Server 2012及更高版本,则它具有SEQUENCE功能。如果您使用的是2008及以下版本,则可以使用单独的专用表格,其中包含一个IDENTITY列,用于生成ID。

因此主表的结构会有所不同(id不再是IDENTITY):

DECLARE @hierarchy_elements TABLE (
     id int NOT NULL ,
     element_path hierarchyid NOT NULL
)

你会有一个单独的对象(SEQUENCE或帮助者表)来根据需要生成唯一的ID。

您将有一个额外明确的步骤来生成ID,但您只能在主表中只有一个INSERT,而不需要UPDATE

第二个变种

您可以使用AFTER INSERT TRIGGER来隐藏"隐藏"显式UPDATE语句。此变体非常接近您的原始方法。您仍然需要在element_path中插入内容。那"东西"将使用IDENTITY新生成的ID在触发器中进行调整。