这是场景:
配置表:
+--------+-----------+-------+
| Prefix | Separator | Seed |
+--------+-----------+-------+
| A | # | 10000 |
+--------+-----------+-------+
交易表:
+----+----------+------+
| Id | SerialNo | Col3 |
+----+----------+------+
| 1 | A#10000 | |
| 2 | A#10001 | |
+----+----------+------+
事务表有一个SerialNo列,该列具有基于配置表生成的序列号。配置表确定前缀分隔符和序列号的种子值。
在上面的示例中,序列号将从 A#10000 开始并递增 1。 但是,如果几个月后有人更新配置表以具有
+--------+-----------+-------+
| Prefix | Separator | Seed |
+--------+-----------+-------+
| B | # | 10000 |
+--------+-----------+-------+
然后事务表应该看起来像这样:
+----+----------+------+
| Id | SerialNo | Col3 |
+----+----------+------+
| 1 | A#13000 | |
| 2 | B#10001 | |
+----+----------+------+
但是,在发生业务表的任何给定时间点都不能有重复的序列号。
如果有人将前缀设置回A
并将种子设置为10000
则不应A#10000
下一个序列号,因为它已经存在。应该是A#13001
可以简单地编写一个带有MAX()
的选择查询,然后CONCAT()
它可能会导致并发问题。不想有重复的序列号。此外,希望它尽可能对性能友好。
我可以想到的另一个解决方案是我创建一个Windows服务,该服务将继续运行并监视表。插入的记录以 null 作为序列号,Windows 服务将更新序列号。这样就不会有并发问题,但我不确定这有多可靠。会有延迟。
在任何给定时间点,配置表中将只有一个条目。
您可以在SQL Server中非常轻松地解决种子值问题。当有人将种子值更新回 10000 时,您需要通过存储过程执行此操作。然后,存储过程确定实际的下一个可用值应该是多少,因为显然 10000 可能是错误的值。然后,存储过程使用正确的"new_reseed_value"执行DBCC CHECKIDENT
。然后,当插入新记录时,服务器将再次正确处理这些值。
请查看此链接以了解DBCC CHECKIDENT
命令的用法。SQL Server DBCC CHECKIDENT