根据表格中的其他2列自动递增数字列

时间:2019-07-17 22:01:39

标签: sql-server

在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列增加一:

  1. 在触发器中使用select row_number() over(partition by OrgID, CompanyID order by ID) + 1
  2. 使用上面的直接选择作为InvoiceNo列中的值 插入语句或将其放在函数中,然后在插入中调用。
  3. 使用插入创建视图和内部联接。

该系统被数十名用户大量使用,当同一组织和公司中的两个不同用户插入发票时,InvoiceNo重复且两个不同的发票采用相同的编号,因为在将select语句作为插入存储过程的一部分执行时,行仍未提交。

我创建了一个非聚集索引以避免重复,但是在发生上述情况时会引发异常。因此它隐藏了问题,但无法解决。

我了解了有关计算列的信息,这对我的问题是一个很好的解决方案,但是是否可以按计算列公式中的列进行分区?如果没有,您建议如何解决InvoiceNo重复项?

请注意,数据库中的许多表(大约50个表)都具有OrgID和CompanyID列,并且它们都必须具有基于OrgID和基于CompanyID的序列。

非常感谢。

1 个答案:

答案 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