Ant*_*kov 13 sql-server sql-server-2005 auto-increment
假设该表有两列:
ParentEntityId int foreign key
Number int
Run Code Online (Sandbox Code Playgroud)
ParentEntityId 是另一个表的外键.
Number是一种本地身份,即它在单身内是独一无二的ParentEntityId.
通过这两列上的唯一键可轻松实现唯一性.
如何在插入Number的上下文中自动递增ParentEntityId?
附录1
为了澄清这个问题,这里有一个摘要.
ParentEntity有多个ChildEntity,每个都ChiildEntity应该Number在其上下文中具有唯一的增量ParentEntity.
附录2
对待ParentEntity一个客户.
治疗ChildEntity作为一种秩序.
因此,每个客户的订单应编号为1,2,3等.
好吧,这种类型的列没有本机支持,但您可以使用触发器实现它:
CREATE TRIGGER tr_MyTable_Number
ON MyTable
INSTEAD OF INSERT
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN;
WITH MaxNumbers_CTE AS
(
SELECT ParentEntityID, MAX(Number) AS Number
FROM MyTable
WHERE ParentEntityID IN (SELECT ParentEntityID FROM inserted)
)
INSERT MyTable (ParentEntityID, Number)
SELECT
i.ParentEntityID,
ROW_NUMBER() OVER
(
PARTITION BY i.ParentEntityID
ORDER BY (SELECT 1)
) + ISNULL(m.Number, 0) AS Number
FROM inserted i
LEFT JOIN MaxNumbers_CTE m
ON m.ParentEntityID = i.ParentEntityID
COMMIT
Run Code Online (Sandbox Code Playgroud)
没有测试,但我很确定它会工作.如果你有一个主键,你也可以将它作为AFTER触发器实现(我不喜欢使用INSTEAD OF触发器,当你需要在6个月后修改它们时,它们更难理解).
只是为了解释这里发生了什么:
SERIALIZABLE是最严格的隔离模式; 它保证一次只有一个数据库事务可以执行这些语句,这是我们需要的,以保证这个"序列"的完整性.请注意,这会不可逆转地促进整个事务,因此您不希望在长时间运行的事务中使用它.
CTE获取已用于每个父ID的最高数字;
ROW_NUMBERPARTITION BY从数字1开始为每个父ID()生成一个唯一的序列; 如果有一个获得新序列,我们将其添加到先前的最大值.
我可能还应该提一下,如果你一次只需要插入一个新的子实体,你最好只是通过存储过程汇集这些操作而不是使用触发器 - 你肯定会从中获得更好的性能.这就是hierarchyidSQL '08中当前使用列的方式.