简单地说,这是我的问题,我一直在尝试在 StackOverflow 中搜索答案,但找不到满意的答案。
我有一个包含列的 InvoiceHeader 表(简化):
InvoiceID : Int - PK Identity(1,1)
InvoiceDate : date
CustomerID : Int - FK to Customer table
等等...
我会经常向用户显示有关 Invoice 的信息。 当我向用户显示发票编号时,我需要为 InvoiceID 添加前缀和零填充。
例如:
InvoiceID : 1
Invoice Number : INV0000001
我的问题是,我应该在 InvoiceHeader
表中创建一个全新 PERSISTED COMPUTED 列来保存格式化的发票号码,如下所示:
InvoiceNumber AS 'INV' + RIGHT('000000'+cast(InvoiceID as varchar(7)),7)
或者我应该选择 InvoiceID
并在运行时从我的应用程序将其处理为 INV0000001
吗?
我的困境:
- 如果我添加一个新的 PERSISTED COMPUTED 列(即 InvoiceNumber),那么我可以在 InvoiceNumber 处创建非聚集索引,这将在 WHERE 子句中使用 InvoiceNumber 进行查询时有所帮助。但这仍然需要覆盖索引或包含索引来获取其他列的值。另一个优点是我不必每次需要显示它时都将其“格式化”为 INV0000001。
- 如果我在应用程序的 SELECT QUERY 中将 InvoiceID 格式化为 INV0000001,这将是太多“苦差事”,每次我想显示 InvoiceNumber 时都必须对其进行格式化。但我不需要另一列,它基本上与 InvoiceID 具有相同的值,并带有一些前缀和零填充。
- 发票号码将被用户用于搜索,例如:给我找到一张号码为“1234”+“%”的发票。如果对 InvoiceID(整数列)执行此操作,它将进行隐式转换,是否会使查询变慢?查询计划还会使用 PK 索引吗?
编辑: 考虑到在很多地方我每次需要时都必须手动格式化发票编号(如果我不使用计算列),我现在几乎确信要使用Esperento57的解决方案:
创建 2 个新列:
InvoiceID : int identity (PK)
Prefix : char(3) --> INV, etc
InvoiceNumber : Prefix + RIGHT('000000'+cast(InvoiceID as varchar(7)),7)
但我不会让 PK 包含前缀,因为 InvoiceID 是身份
,因此它本身是唯一的。
我还在考虑 @Matt 关于关注点分离的观点,因为它是有道理的。
最佳答案
我对您的专栏的建议:
InvoiceID:整数不为空,自动增量(序列不是必需的,SQL Server 可以完成这项工作)
前缀:PREFIXTABLE 上的 varchar(10) 不为 null FK
InvoiceID 和 Prefix 为主键
InvoiceNumber:计算并保留的列 = Prefix + RIGHT('0000000'+ InvoiceID,7)
在 InvoiceNumber 上添加索引
根据我的建议,您可以:
- 如有必要,请更改前缀
- 您对前缀很诚实
- 您拥有完整的 key 并保留真正的主 key
- 您不必重新计算完整的 key
- 在进行数据恢复时,您可以将序列跳转到您的 key 或仅选择其他前缀
- 您可以在 PREFIX 表中添加说明以解释您的前缀(以供 future 的开发人员举例)
关于SQL Server - 前缀和零填充 ID 列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44868052/