使用如下所示的示例表:
CREATE TABLE MyTable (id INT IDENTITY(1,1), someCol NVARCHAR(20), codeCol NVARCHAR(20))
有一个 id 列、一些随机值列和存储代码的第三列。
您的触发器可能如下所示:
CREATE TRIGGER tgInsertMyTable ON myTable
AFTER INSERT
AS
BEGIN
DECLARE @code NVARCHAR(20)
SELECT @code = 'ABC-' + CAST(YEAR(GETDATE()) AS NVARCHAR(4)) + '-'
DECLARE @max NVARCHAR(20)
SELECT @max = codeCol FROM dbo.myTable mts WHERE mts.codeCol LIKE @code + '%'
;WITH CTE_UPD AS
(
SELECT REPLICATE('0', 5-LEN(CAST(COALESCE(CAST(RIGHT(@max,5) AS INT),0) + ROW_NUMBER() OVER (ORDER BY ins.ID) AS NVARCHAR(5)))) + CAST(COALESCE(CAST(RIGHT(@max,5) AS INT),0) + ROW_NUMBER() OVER (ORDER BY ins.ID) AS NVARCHAR(5)) AS nextNo, id
FROM INSERTED ins
)
UPDATE mt
SET mt.CodeCol = @code + nextNo
FROM dbo.MyTable mt
INNER JOIN CTE_UPD ins ON ins.ID = mt.ID
END
我知道它在某些地方看起来很复杂,所以我会尝试解释一下,但是
首先 - 这是一个可以正常工作的演示:
SQLFiddle DEMO
所以,首先我在@code 变量中设置了所需的代码前缀——这是没有增量的部分。
第二 - 我在表中的现有行中搜索具有相同前缀的最大值 - 并将其存储在变量 @max
第三部分是 CTE - 它用于查找下一个增量值。
- 从最大值中只去除最后 5 个字符(RIGHT 函数)
- 将它们转换为 int (CAST) - 从零开始剥离它
- 如果 @max 为 NULL - 现在它被声明为 0 (COALESCE)
- 将插入的 ROW_NUMBER 添加到其中 - 这很重要 - 您不能只使用 +1,因为您可能会同时添加多于 1 行(就像在演示中一样)。这就是首先需要 CTE 的全部原因。
- 转换回 nvarchar
- REPLICATE 用于返回 5-LEN 数量的起始零(新 LEN 计算为在数字变为 10、100、1000 时添加更少的零)
最后,只需将 CTE 加入表并使用@code + 计算值进行更新
我不确定是否有更简单的解决方案,但这个可行 - 我认为涵盖了所有场景。