如何将自动生成的标识值作为 hierarchyid 字段的一部分插入同一记录
How to Insert auto-generated identity value as part of a hierarchyid field on the same record
我正在尝试找到一种方法来将记录插入到 table 中,该 table 使用新生成的身份值作为其层次结构 ID 的一部分。以下 sql 展示了我正在尝试做的事情,以及我已经设法做到的最接近的事情。这是在事务内部使用插入后跟更新。我在想出初始层次结构 ID 时遇到了麻烦,因为该字段有唯一约束,而且我担心如果同时将 2 个元素添加到同一父级,可能会引发错误。
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 字段中包含新的身份值。
解决问题的大致思路:
分别生成该行的ID,将其记住某处,然后将生成的ID按原样插入ID列,并使用相同的记忆值组成element_path
。
如果您使用 SQL Server 2012 及更高版本,它具有 SEQUENCE
功能。如果您使用的是 2008 及以下版本,您可以有一个单独的专用 table 和一个 IDENTITY
列来生成 ID。
所以你的 main table 的结构会有所不同(id 不再是 IDENTITY
):
DECLARE @hierarchy_elements TABLE (
id int NOT NULL ,
element_path hierarchyid NOT NULL
)
并且您将有一个单独的对象(SEQUENCE
或助手 table)来根据需要生成唯一 ID。
您将需要一个额外的显式步骤来生成 ID,但您只能将一个 INSERT
放入主 table 而无需 UPDATE
。
第二种变体
您可以使用 AFTER INSERT TRIGGER
到 "hide" 显式 UPDATE
语句。此变体非常接近您的原始方法。您仍然需要在 element_path
中插入一些内容。 "something" 将使用 IDENTITY
新生成的 ID 在触发器中进行调整。
我正在尝试找到一种方法来将记录插入到 table 中,该 table 使用新生成的身份值作为其层次结构 ID 的一部分。以下 sql 展示了我正在尝试做的事情,以及我已经设法做到的最接近的事情。这是在事务内部使用插入后跟更新。我在想出初始层次结构 ID 时遇到了麻烦,因为该字段有唯一约束,而且我担心如果同时将 2 个元素添加到同一父级,可能会引发错误。
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 字段中包含新的身份值。
解决问题的大致思路:
分别生成该行的ID,将其记住某处,然后将生成的ID按原样插入ID列,并使用相同的记忆值组成element_path
。
如果您使用 SQL Server 2012 及更高版本,它具有 SEQUENCE
功能。如果您使用的是 2008 及以下版本,您可以有一个单独的专用 table 和一个 IDENTITY
列来生成 ID。
所以你的 main table 的结构会有所不同(id 不再是 IDENTITY
):
DECLARE @hierarchy_elements TABLE (
id int NOT NULL ,
element_path hierarchyid NOT NULL
)
并且您将有一个单独的对象(SEQUENCE
或助手 table)来根据需要生成唯一 ID。
您将需要一个额外的显式步骤来生成 ID,但您只能将一个 INSERT
放入主 table 而无需 UPDATE
。
第二种变体
您可以使用 AFTER INSERT TRIGGER
到 "hide" 显式 UPDATE
语句。此变体非常接近您的原始方法。您仍然需要在 element_path
中插入一些内容。 "something" 将使用 IDENTITY
新生成的 ID 在触发器中进行调整。