我有一个业务需求,即发票表中的每条记录都有一个看起来像 YYYYNNNNNN 的 ID。
NNNNNN 部分需要在每年年初重新启动。所以 2016 年输入的第一行看起来像 2016000001,第二行看起来像 2016000002 等等。假设 2016 年的最后一条记录是 2016123456,下一行(2017 年)应该看起来像 2017000001
我不需要这个 id 作为主键,我也存储创建日期。这个想法是这个'显示ID'是独一无二的(所以我可以通过它查询)并且可以按年份进行分组。
不太可能删除任何记录;但是,我倾向于防御性地编写代码以防止类似的事情。
有什么方法可以创建这个 id 而不必在每次插入新行时查询今年的最大 id?
想法:
CreateNewInvoiceSP
,它获取MAX
那一年的值(令人讨厌)IDENTITY
orDEFAULT
声明中指定一些 UDF 或其他内容(??)PARTITION OVER + ROW()
(删除会出现问题)INSERT
(仍然需要运行一些MAX
查询:()所有这些都有些不理想。欢迎任何想法或变化!
gbn*_*gbn 17
您的领域有 2 个元素
它们不需要存储为一个字段
例子:
YEAR(GETDATE())
然后创建一个连接它们的计算列(使用适当的格式)。序列可以在年份变化时重置。
SQLfiddle 中的示例代码:*(SQLfiddle 并不总是有效)
-- Create a sequence
CREATE SEQUENCE CountBy1
START WITH 1
INCREMENT BY 1 ;
-- Create a table
CREATE TABLE Orders
(Yearly int NOT NULL DEFAULT (YEAR(GETDATE())),
OrderID int NOT NULL DEFAULT (NEXT VALUE FOR CountBy1),
Name varchar(20) NOT NULL,
Qty int NOT NULL,
-- computed column
BusinessOrderID AS RIGHT('000' + CAST(Yearly AS VARCHAR(4)), 4)
+ RIGHT('00000' + CAST(OrderID AS VARCHAR(6)), 6),
PRIMARY KEY (Yearly, OrderID)
) ;
-- Insert two records for 2015
INSERT INTO Orders (Yearly, Name, Qty)
VALUES
(2015, 'Tire', 7),
(2015, 'Seat', 8) ;
-- Restart the sequence (Add this also to an annual recurring 'Server Agent' Job)
ALTER SEQUENCE CountBy1
RESTART WITH 1 ;
-- Insert three records, this year.
INSERT INTO Orders (Name, Qty)
VALUES
('Tire', 2),
('Seat', 1),
('Brake', 1) ;
Run Code Online (Sandbox Code Playgroud)
您是否考虑过使用种子 = 2016000000 创建身份字段?
create table Table1 (
id bigint identity(2016000000,1),
field1 varchar(20)...
)
Run Code Online (Sandbox Code Playgroud)
这个种子应该每年自动增加,例如在 2017/1/1 晚上你需要安排
DBCC CHECKIDENT (Table1, RESEED, 2017000000)
Run Code Online (Sandbox Code Playgroud)
但是我已经看到了设计的问题,例如:如果你有百万条记录怎么办?