我刚遇到一个有点旧的数据库(和前端),它有一种有趣的方式来处理唯一 ID 方面的问题。
我有一个表,其中只有一列和一行存储一个整数(当前为 31448)。这个数字在Invoices
表上用作“InvoiceNo”,该Invoices
表也有一个唯一的 auto-inc id(当前为 2847)
它看起来有点像这样:
CREATE TABLE InvoiceNumber(
LatestId [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE Invoices(
InvoiceId [int] IDENTITY(1,1) NOT NULL,
InvoiceNo [int] NOT NULL,
Amount [decimal](18, 2) NULL
) ON [PRIMARY]
GO
除了实际上不是强制关系的 InvoiceNo 之外,两个表之间没有实际关系。
然后,当用户添加新发票时,前端执行以下操作:
public static void CreateInvoice(Invoice newInvoice)
{
try
{
using (var ctx = new DataContext)
{
var lastInvoice = (from lastNumber in ctx.SingleRowTable
select lastNumber).Single;
var newInvoiceNo = lastInvoice.InvoiceNumber +1; // Int
lastInvoice.InvoiceNumber = newInvoiceNo;
newInvoice.InvoiceNo = newInvoiceNo;
ctx.Invoices.InsertOnSubmit(newInvoice);
ctx.SubmitChanges;
}
}
catch (Exception x)
{
// Sleep now in the fire
}
}
因此,基本上,当创建新发票时,前端会请求 InvoiceNo(单行)表中的号码并加一 (+1) 该号码,然后成为新的发票号码以及最近使用的发票号码。
数据库中的其他表 (InvoiceItems) 引用 InvoiceId 而不是 InvoiceNo。
我想问题是:为什么有人会使用这种方法?它是反模式或设计错误还是有任何真正的实现?
我的想法是,出于某种原因,需要保留“真实世界”发票编号,因此他们决定运行额外的“唯一 ID”将是处理它的最佳方式。我想也许开发人员无法承受发票数量增加一千。(?) 也许。
我曾经使用过一个程序,该程序使用类似的系统为发票生成唯一 ID。它确实起源于一个不同的数据库系统,一个没有自动递增 ID 的系统。
你的系统有一点不同,我非常喜欢这种不同。该表有一个唯一的、自动递增的
invoice
ID——它有一个单独的、面向客户的(我假设)发票号。我经历了合并两个结构相同的数据库的过程。自动递增的 ID 值重叠,因此我们必须在合并过程中重置其中一组。我们的
invoice
表使用唯一的、自动递增的 ID 作为面向客户的发票编号。因此,我们在功能上丢失了系统中的那些发票号码。虽然拥有相同(面向客户)发票编号的两张发票可能会出现问题,但如果面向客户的值与主键不同,至少我们会有该选项。
该解决方案是生成唯一密钥的“正常”解决方案。当数据库没有序列或自动递增选项时使用它。您还可以使用它来独立于数据库。