【问题标题】:Conditional column in SQL Server based in another columnSQL Server 中的条件列基于另一列
【发布时间】:2019-10-30 13:22:30
【问题描述】:

我正在寻找一种解决方案,以便在我的表上基于另一列有一个版本列。

我的表格中有一个“文档编号”列。每次插入具有相同文档号的新行时,我都想增加列版本。

我知道我可以通过后端。但是,这意味着我必须先阅读表格然后插入。我的想法是优化性能并将其留给 SQL Server。

有可能吗?

pk    DocNo  Version
---------------------
1     ABC     0
2     CBD     0
3     ABC     1
4     FGH     0
5     ABC     2

【问题讨论】:

  • 您是在寻找 SQL 查询、触发器还是存储过程?
  • 一种选择是使用row_number() 在您的选择查询中生成版本。或者编写一个存储过程来执行插入。或者使用触发器更新版本
  • @Angelo,我正在寻找想法。我不想执行插入数据的过程。我认为触发器可能是个好主意。

标签: sql sql-server optimization


【解决方案1】:

假设您可以参数化您的查询(如在存储过程中),并且您的主键设置为 IDENTITY,您可以使用以下内容:

    INSERT INTO TableA (DocNo, Version)
    (SELECT TOP 1 'XYZ',ISNULL(MAX(Version)+1,0) 
      FROM TableA WHERE DocNo = 'XYZ')

我使用'XYZ' 来放置参数,例如:

    INSERT INTO TableA (DocNo, Version)
    (SELECT TOP 1 @DocNo,ISNULL(MAX(Version)+1,0) 
      FROM TableA WHERE DocNo = @DocNo)

【讨论】:

    【解决方案2】:

    存储过程解决方案

    CREATE PROCEDURE tableUpsert(@DocNo varchar(100))
    AS
      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
      BEGIN TRAN
        IF EXISTS(SELECT * FROM dbo.YourTable WITH (UPDLOCK) WHERE DocNo = @DocNo)
          UPDATE dbo.YourTable
          SET Version = Version + 1
          WHERE DocNo = @DocNo;
        ELSE
          INSERT dbo.YourTable(DocNo, Version)
          VALUES(@DocNo, 1);
      COMMIT
    

    代码是不言自明的。如果记录存在,则通过增加 VersionNumber 列进行更新,如果不存在,则插入默认 VersionNumber 为 1 的新记录。注意使用 UPDLOCK 以确保当前只有您的特定进程在更新记录。

    【讨论】:

      【解决方案3】:

      您可以使用insert trigger。在触发器中,通过获取相同 DocNo 的最后一个 version 并加 1 来更新 Version

      update  t
      set     Version = isnull(v.Version, 0) + 1
      from    inserted i
              inner join mytable t    on  i.pk = t.pk
              outer apply
              (
                  select  Version = max(Version)
                  from    mytable x
                  where   x.DocNo = i.DocNo
              ) v
      

      【讨论】:

        【解决方案4】:

        您的版本号隐含在您的数据中。使用PK通过

        来判断

        SELECT DocNo, ROW_NUMBER() over (PARTITION BY DocNo ORDER BY pk) as version order by DocNo 当您检索数据(或将其放入视图中)时

        依赖 IDENTITY 可能会给您带来差距

        依赖 MAX(x)+1 可能并不总是有效,具体取决于您的并发模型。

        锁定表/列将引入并发问题(在您的情况下这可能不重要或微不足道)。

        【讨论】:

          猜你喜欢
          • 2013-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-04
          • 1970-01-01
          • 1970-01-01
          • 2021-07-17
          • 1970-01-01
          相关资源
          最近更新 更多