【问题标题】:auto-increment an specific row自动增加特定行
【发布时间】:2017-04-19 14:22:07
【问题描述】:

我需要增加一个名为 Sequencia 的列,每个 Sequencia 依赖于 CedenteID、Ano 和 Periodo 来增加。这是我使用的:

select @Seq = isnull(Sequencia, 0) + 1
from T041_NossoNumero
where CedenteID = @CedenteID
and Ano = @Ano
and Periodo = @Periodo      

update T041_NossoNumero
set Sequencia = @Seq
where CedenteID = @CedenteID
and Ano = @Ano
and Periodo = @Periodo

但是,如果我同时执行这段代码,我可以拥有重复的 Sequencia。我想建议我应该做什么而不是使用更新 +1

我有什么:

  • CedenteID(PK/FK)
  • Ano(PK)
  • 周期(PK)
  |CedenteID|Ano   |Periodo|Sequencia|
  |         |      |       |         |
  |392      |2016  |1      |37382    |
  |392      |2016  |2      |17351    |

我需要什么,如果:

  • CedenteID = 392
  • Ano = 2016
  • 周期 = 2
 |CedenteID|Ano |Periodo|Sequencia|
 |         |    |       |         |
 |392      |2016|      1|    37382|
 |392      |2016|      2|    17352|

【问题讨论】:

  • 那张桌子上有标识列吗?
  • 那么,两个调用同时提交,只需要更新一次(+1,而不是+1+1)?如果是这样,您如何识别“同时”与“顺序”调用?

标签: sql sql-server increment


【解决方案1】:

通过设计“自动”增加一列的唯一方法是使用这样的标识。

CREATE TABLE dbo.Table_1
    (
    sequence int NOT NULL IDENTITY (1, 1)
    )  ON [PRIMARY]

但这对您不起作用,因为只有在所有其他字段都相同时您才需要递增。
这意味着必须在应用程序端完成递增。
确保使用单个事务来执行此操作,否则可能会出现同步问题。

【讨论】:

    【解决方案2】:

    通过使用事务,您可以确保在并发调用中不会出现重复,但这可能会导致您的系统出现性能问题。

    BEGIN TRY
        BEGIN TRANSACTION
    
        select @Seq = isnull(Sequencia, 0) + 1
        from T041_NossoNumero
        where CedenteID = @CedenteID
        and Ano = @Ano
        and Periodo = @Periodo      
    
        update T041_NossoNumero
        set Sequencia = @Seq
        where CedenteID = @CedenteID
        and Ano = @Ano
        and Periodo = @Periodo
    
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION
        THROW
    END CATCH
    

    【讨论】:

    • 我之前尝试过,当我在并发调用中执行它时允许相同的序列
    • 这条评论违反了交易的第一条规则。在此代码中,表 'T041_NossoNumero' 将被锁定,直到事务提交,这意味着不可能有重复的序列号,除非您在选择中使用 'NOLOCK' 关键字。
    【解决方案3】:

    我可能遗漏了一些东西,但你不能使用

    UPDATE T041_NossoNumero
     set Sequencia = isnull(Sequencia, 0) + 1
     where CedenteID = @CedenteID
      and Ano = @Ano
      and Periodo = @Periodo
    

    ?

    【讨论】:

    • 否,因为并发调用中有重复。
    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多