在MS-SQL服务器中,我有一个名为(发票)的表,其中包含4列
[InvoiceID] [int] IDENTITY(1,1) NOT NULL (Primary Key)
[OrgID] [int] NULL
[CompanyID] [int] NULL
[InvoiceNo] [int] NULL
在此表中,每个组织(OrgID列)和子公司(CompanyID列)必须具有其InvoiceNo的顺序。类似于以下内容:
InvoiceID OrgID CompanyID InvoiceNo
-------------------- --------------- --------------- -----------
1 1 101 1
2 1 101 2
3 1 101 3
4 2 201 1
5 2 201 2
6 2 201 3
7 2 202 1
8 2 202 2
9 2 202 3
我尝试了许多想法,使插入新行时,基于OrgID和CompanyID的InvoiceNo列增加一:
select row_number() over(partition by OrgID, CompanyID order
by ID) + 1
。该系统被数十名用户大量使用,当同一组织和公司中的两个不同用户插入发票时,InvoiceNo重复且两个不同的发票采用相同的编号,因为在将select语句作为插入存储过程的一部分执行时,行仍未提交。
我创建了一个非聚集索引以避免重复,但是在发生上述情况时会引发异常。因此它隐藏了问题,但无法解决。
我了解了有关计算列的信息,这对我的问题是一个很好的解决方案,但是是否可以按计算列公式中的列进行分区?如果没有,您建议如何解决InvoiceNo重复项?
请注意,数据库中的许多表(大约50个表)都具有OrgID和CompanyID列,并且它们都必须具有基于OrgID和基于CompanyID的序列。
非常感谢。
答案 0 :(得分:1)
您不能在计算列中放置窗口函数(例如ROW_NUMBER),但是有一个很好的解决方法。创建一个带有窗口函数的标量值函数,然后可以在计算列中使用该标量函数。
map
然后:
CREATE FUNCTION dbo.fnGetInvoiceNo(@InvoiceID INT)
RETURNS int
AS
BEGIN
DECLARE @InvoiceNo INT
;WITH cte AS
(
SELECT InvoiceID, ROW_NUMBER() OVER (PARTITION BY OrgID, CompanyID ORDER BY InvoiceID) rn
FROM dbo.Invoices
)
SELECT @InvoiceNo = rn
FROM cte
WHERE cte.InvoiceID = @InvoiceID
RETURN @InvoiceNo
END
GO
ALTER TABLE dbo.Invoices ADD InvoiceNo AS dbo.fnGetInvoiceNo(InvoiceID)
GO
返回:
SELECT * FROM dbo.Invoices