基于两列生成定制的唯一键(复合键)

时间:2019-02-01 07:15:35

标签: sql-server stored-procedures

我想在插入数据期间基于两列生成自定义的唯一密钥(复合密钥),并发处理的人数与那里尝试创建账单的用户一样多。

Billno应该以B01到B02,B03 ... N开头,直到付款类型和年份更改为止。

在完全插入后,这是期望的数据到表中。

BillId     PaymentType     Year      BillNo
1          Card            2018      B01
2          Card            2018      B02
3          Card            2019      B01
4          Cash            2018      C01
5          Cash            2018      C02
6          Cash            2018      C03
7          PayTM           2019      P01

注意:我已经通过更新和插入触发器来完成此操作,但是由于性能问题,正在寻找其他选择。

如果有人能解决问题,我表示感谢。

1 个答案:

答案 0 :(得分:0)

您可以使用ROW_NUMBER来生成编号,并使用DENSE_RANK来生成字母:

;WITH WindowFunctions AS
(
    SELECT
        T.*,
        RowNumber = ROW_NUMBER() OVER (
            PARTITION BY
                PaymentType,
                Year
            ORDER BY
                BillId),
        DenseRank = DENSE_RANK() OVER (ORDER BY PaymentType, Year)
    FROM
        YourTable AS T
)
SELECT
    T.*,
    BillNo = CHAR(64 + T.DenseRank) + RIGHT('0' + CONVERT(VARCHAR(10), T.RowNumber), 2)
FROM
    WindowFunctions AS T

请注意可能的字母数量,使用CHAR函数可能会降低效果。

结果:

BillID  PaymentType Year    RowNumber   DenseRank   BillNo
1       Card        2018    1           1           A01
2       Card        2018    2           1           A02
3       Card        2019    1           2           B01
4       Cash        2018    1           3           C01
5       Cash        2018    2           3           C02
6       Cash        2018    3           3           C03
7       PayTM       2019    1           4           D01

但是,仅当您考虑将整个集合放在同一SELECT上时,此方法才有效。一旦加载了表并设置了BillNo,您将无法生成下一个BillNo,除非您考虑将先前的记录与另一个SELECT一起使用,这会变得很棘手。 / p>

如果您确实需要1列键,建议您生成一个不依赖于其他/先前记录的ID,例如将PaymentTypeBillId混合在一起。