MSSQL 只能在特定情况下列自动递增
MSSQL Can a column auto-increment only under certain circumstances
我有一个 table,其中包含 4 列 ID、c1、c2 和 LOT。 ID 是主键。对于 c1 为 5 时的每条记录,我想为 LOT 自动生成一个数字,对于 c2 的每个不同值,这将是一个从 1 开始的序列。
因此,如果 c1 不是 5,则 LOT 保持为空。但是,如果 c1 是 5,那么对于 c2=1 的每条记录,我想用从 1 开始的自动递增序列填充 LOT。
例如:
ID c1 c2 LOT
1 3
2 5 1 1
3 5 1 2
4 5 1 3
5 4
然后对 c2 的不同值执行相同的操作。因此,如果 c2 为 2,则有另一组从 1 开始的自动递增 LOT 数字:
ID c1 c2 LOT
6 3
7 5 2 1
8 5 1 4
9 5 2 2
10 5 2 3
我们使用的是 MSSQL 2014 企业版。 table 分区是否有用,或者我是否需要为 C2 的每个不同值创建特殊的 table?
不使用标识字段,您可以使用触发器。
无法使用身份功能执行此操作,但是,请考虑使用 Instead of trigger 手动管理所需的值。
您可以使用逻辑在查询或视图中生成 LOT:
SELECT ID, C1, C2,
CASE
WHEN C1<>5 OR C2 IS NULL THEN NULL
ELSE COUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
END AS LOT
FROM D
ORDER BY ID
给定 table 使用 (ID, C1, C2) 生成:
CREATE TABLE D (ID INT PRIMARY KEY IDENTITY, C1 INT, C2 INT)
INSERT D VALUES (3,NULL),
(5,1),
(5,1),
(5,1),
(4,NULL),
(3,NULL),
(5,2),
(5,1),
(5,2),
(5,2)
查询产生上面指示的输出:
ID C1 C2 LOT
1 3
2 5 1 1
3 5 1 2
4 5 1 3
5 4
6 3
7 5 2 1
8 5 1 4
9 5 2 2
10 5 2 3
用于生成LOT
、COUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
的语句只是统计当前行之前和包括当前行的行数,其中C1和C2等于当前行。例如,对于第 4 行,元组 (c1,c2)=(5,1) 在该行之前和包括该行(第 2、3 和 4 行)的 3 条记录中被观察到,因此 LOT=3.
感谢大家对使用触发器的建议(全部up-voted)。事实证明(正如我在上面的评论中提到的)一篇关于 side-bar (SQL Server unique auto-increment column in the context of another column) 的文章显示了正确的 INSTEAD OF INSERT 触发器的详细构造。作者提到它是 "Not tested",并且确实存在一个小错误(WITH 子句中缺少 GROUP BY ParentEntityID)但是任何复制代码的人都会得到一个明显需要修复的错误。在这里纠正 post 可能不符合犹太洁食标准,但另一个问题已有 6 年历史了。
我有一个 table,其中包含 4 列 ID、c1、c2 和 LOT。 ID 是主键。对于 c1 为 5 时的每条记录,我想为 LOT 自动生成一个数字,对于 c2 的每个不同值,这将是一个从 1 开始的序列。
因此,如果 c1 不是 5,则 LOT 保持为空。但是,如果 c1 是 5,那么对于 c2=1 的每条记录,我想用从 1 开始的自动递增序列填充 LOT。 例如:
ID c1 c2 LOT
1 3
2 5 1 1
3 5 1 2
4 5 1 3
5 4
然后对 c2 的不同值执行相同的操作。因此,如果 c2 为 2,则有另一组从 1 开始的自动递增 LOT 数字:
ID c1 c2 LOT
6 3
7 5 2 1
8 5 1 4
9 5 2 2
10 5 2 3
我们使用的是 MSSQL 2014 企业版。 table 分区是否有用,或者我是否需要为 C2 的每个不同值创建特殊的 table?
不使用标识字段,您可以使用触发器。
无法使用身份功能执行此操作,但是,请考虑使用 Instead of trigger 手动管理所需的值。
您可以使用逻辑在查询或视图中生成 LOT:
SELECT ID, C1, C2,
CASE
WHEN C1<>5 OR C2 IS NULL THEN NULL
ELSE COUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
END AS LOT
FROM D
ORDER BY ID
给定 table 使用 (ID, C1, C2) 生成:
CREATE TABLE D (ID INT PRIMARY KEY IDENTITY, C1 INT, C2 INT)
INSERT D VALUES (3,NULL),
(5,1),
(5,1),
(5,1),
(4,NULL),
(3,NULL),
(5,2),
(5,1),
(5,2),
(5,2)
查询产生上面指示的输出:
ID C1 C2 LOT
1 3
2 5 1 1
3 5 1 2
4 5 1 3
5 4
6 3
7 5 2 1
8 5 1 4
9 5 2 2
10 5 2 3
用于生成LOT
、COUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
的语句只是统计当前行之前和包括当前行的行数,其中C1和C2等于当前行。例如,对于第 4 行,元组 (c1,c2)=(5,1) 在该行之前和包括该行(第 2、3 和 4 行)的 3 条记录中被观察到,因此 LOT=3.
感谢大家对使用触发器的建议(全部up-voted)。事实证明(正如我在上面的评论中提到的)一篇关于 side-bar (SQL Server unique auto-increment column in the context of another column) 的文章显示了正确的 INSTEAD OF INSERT 触发器的详细构造。作者提到它是 "Not tested",并且确实存在一个小错误(WITH 子句中缺少 GROUP BY ParentEntityID)但是任何复制代码的人都会得到一个明显需要修复的错误。在这里纠正 post 可能不符合犹太洁食标准,但另一个问题已有 6 年历史了。