【问题标题】:MSSQL Can a column auto-increment only under certain circumstancesMSSQL 只有在某些情况下才能使列自动递增
【发布时间】:2017-06-02 00:53:29
【问题描述】:

我有一个包含 4 列 ID、c1、c2 和 LOT 的表。 ID 是主键。对于 c1 为 5 时的每条记录,我想为 LOT 自动生成一个数字,该数字对于 c2 的每个不同值都是从 1 开始的序列。

所以如果 c1 不是 5,LOT 保持为空。但是如果 c1 是 5,那么对于 c2=1 的每条记录,我想用从 1 开始的自动递增序列填充 LOT。 例如:

ID  c1  c2  LOT
1   3   
2   5   1   1
3   5   1   2
4   5   1   3
5   4

然后对不同的 c2 值执行相同的操作。所以如果 c2 是 2,再有一堆从 1 开始的自增手数:

ID  c1  c2  LOT
6   3   
7   5   2   1
8   5   1   4
9   5   2   2
10  5   2   3

我们使用的是 MSSQL 2014 Enterprise Ed。表分区是否有用,还是我需要为 C2 的每个不同值创建特殊表?

【问题讨论】:

  • 抱歉,我在该链接中没有看到对触发器的引用。
  • 对不起,我之前发布了错误的链接。请参阅stackoverflow.com/q/24335341/1072229 进行类似讨论。
  • 谢谢。这看起来很相关。我还发现了这一点:侧边栏中的stackoverflow.com/questions/2205036/… 也使用触发器解决了这个问题,该触发器在下面解释了我的担忧(关于唯一性)

标签: sql-server conditional auto-increment


【解决方案1】:

感谢大家提出使用触发器的建议(全部赞成)。事实证明(正如我在上面的评论中提到的)侧栏上出现的一篇文章 (SQL Server unique auto-increment column in the context of another column) 显示了正确的 INSTEAD OF INSERT 触发器的详细构造。作者提到它是“未测试”,确实存在一个小错误(WITH 子句中缺少 GROUP BY ParentEntityID),但任何复制代码的人都会得到一个明显需要修复的错误。可能不适合在这里更正该帖子,但另一个问题是 6 岁。

【讨论】:

    【解决方案2】:

    您可以使用该逻辑在查询或视图中生成 LOT:

    SELECT ID, C1, C2,
        CASE
            WHEN C1<>5 OR C2 IS NULL THEN NULL
            ELSE COUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        END AS LOT
     FROM D
     ORDER BY ID
    

    给定一个使用 (ID, C1, C2) 生成的表:

    CREATE TABLE D (ID INT PRIMARY KEY IDENTITY, C1 INT, C2 INT)
    INSERT D VALUES (3,NULL),
                    (5,1),
                    (5,1),
                    (5,1),
                    (4,NULL),
                    (3,NULL),
                    (5,2),
                    (5,1),
                    (5,2),
                    (5,2)
    

    查询产生上述输出:

    ID  C1  C2  LOT
    1   3   
    2   5   1   1
    3   5   1   2
    4   5   1   3
    5   4   
    6   3   
    7   5   2   1
    8   5   1   4
    9   5   2   2
    10  5   2   3
    

    用于生成LOTCOUNT(*) OVER (PARTITION BY C1, C2 ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 的语句仅计算当前行之前和包括当前行的行数,其中 C1 和 C2 等于当前行。例如,对于第 4 行,元组 (c1,c2)=(5,1) 在该行之前和包括该行(第 2、3 和 4 行)的 3 条记录中观察到,因此 LOT=3。

    【讨论】:

      【解决方案3】:

      使用身份功能无法做到这一点,但是,请考虑使用Instead of trigger 来手动管理所需的值。

      【讨论】:

      • 我想我不明白如何保证触发器生成唯一的完整序列。如何解决多个同时插入的问题?
      • 我不知道你会如何解决同时插入的问题,但我认为没有任何方法可以保证不使用引擎的身份
      • 实际上,在我在下面的“我自己的”答案中提到的帖子中,触发代码使用 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE,作者说它保证了完整的唯一序列(但存在一些潜在的性能问题。)
      【解决方案4】:

      没有身份字段,您可以使用触发器。

      【讨论】:

        猜你喜欢
        • 2016-05-02
        • 1970-01-01
        • 1970-01-01
        • 2021-01-02
        • 2014-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多