在一行中创建表的实例?

时间:2019-06-03 17:26:06

标签: sql sql-server asp.net-mvc tsql

当用户在用户界面中更新表时,我很难弄清楚如何创建表的快照(或实例)。

问题是:

我有一个“修订”的用户界面。在用户界面中,有一个“修订类型”的下拉列表。修订类型也有其自己的UI,用户可以在此处检查/取消选中可用修订类型的列表。当用户取消选中“修订类型”时,该类型将从所有修订的下拉列表中删除。客户要求对修订类型的更改仅影响新修订,而不影响更改之前存在的修订。

因此,如果先前已检查“新建,草稿,已关闭”的修订类型值,而未选中“草稿”,则我仍需要在UI中为现有修订显示所有三个值,然后仅在新修订中显示“新”和“已关闭”。但是,然后他们可以返回并重新打开“草稿”,并再次显示该草稿,但仅适用于在重新打开草稿后创建的修订。

对我来说,这意味着我需要为“修订类型历史记录”创建一个表。 “修订类型”表具有一个AmendmentTypeID列,其中所有ID均显示为行。我会将其显示为列,并以“生效日期”(更改值的日期)定义行。然后,我将修正案链接到AmendmentTypeHistoryID,并通过查找AmendmentTypeIDs获取要显示的值。

例如

dbo.AmendmentType

AmendmentTypeID          Name         CreationDate       IsActive
      1                  New            6/2/2019            1
      2                  Draft          6/2/2019            1
      3                  Closed         6/2/2019            1

dbo.AmendmentTypeHistory

AmendmentTypeHistoryID     EffectiveDate     AmendmentTypeID     AmendmentTypeID     AmendmentTypeID
            1             6/3/2019           1 (New)             2 (Draft)               3 (Closed)

然后您将其更改...

dbo.AmendmentType

AmendmentTypeID          Name         CreationDate       IsActive
      1                  New            6/2/2019            1
      3                  Closed         6/2/2019            1

dbo.AmendmentTypeHistory

AmendmentTypeHistoryID     EffectiveDate     AmendmentTypeID     AmendmentTypeID     AmendmentTypeID
            1             6/3/2019           1 (New)             2 (Draft)               3 (Closed)
            2             6/3/2019           1 (New)             3 (Closed)     NULL

总共有77种修正类型可能性。我不能硬编码它,所以我希望可以以某种方式动态地完成它。

有人知道我该怎么做吗?有没有更简便或更完善的方法来做我要做的事情?

2 个答案:

答案 0 :(得分:1)

在您发表评论后,我想我有一个解决方案。

像这样创建一个表AmendmentTypeVersions

ID | VERSION_NUMBER | AmendmentTypeId

并使用版本1插入所有有效的AmendmentType。

INSERT INTO AmendmentTypeVersions (VERSION_NUMBER ,  AmendmentTypeId)
    SELECT 1, AmendmentTypeID
    FROM AmendmentType
    WHERE isactive = 1

每次保存AmendmentType时,获取最大版本号并插入新版本的记录

DECLARE @LastVersion = (SELECT MAX(VERSION_NUMBER) FROM AmendmentTypeVersions)

INSERT INTO AmendmentTypeVersions (VERSION_NUMBER ,  AmendmentTypeId)
    SELECT @LastVersion + 1, AmendmentTypeID
    FROM AmendmentType
    WHERE isactive = 1

使用“ VERSION_NUMBER”添加到“修订”列并将其设置为1

现在您要做的就是这个:

  • 创建修订时,需要获取然后将修订VERSION_NUMBER设置为@lastVersion(在编辑操作上,您已经设置了修订VERSION_NUMBER)
  • 始终按修订的VERSION_NUMBER过滤修订类型(您必须按修订的VERSION_NUMBER将修订类型与AmendmentTypeVersions结合起来)

答案 1 :(得分:1)

这是一个非常困难和令人困惑的要求。如果IsActive的修订类型在您将其加载到下拉菜单与用户保存其条目之间有所不同,会发生什么情况?

忽略这一点,我建议使用一个表,该表将组合映射在有序的逗号分隔列表中。我的答案不符合规范形式的情况很少见,但是否则很难。

制作一个名为AmendmentTypeGroup的表:

create table AmendmentTypeGroup
(
AmendmentTypeGroupID int identity
,AmendmentTypes nvarchar(max) not null
,constraint PK_AmendmentTypeGroup primary key clustered(AmendmentTypeGroupID)
)

在“修正案”(而非修正案类型)表中添加一列:

alter table Amendmends add AmendmentTypeGroupID int null

每次在Amendments中插入一行时,请使用触发器或proc来确保首先将当时IsActive的所有AmendmentTypes的所有ID的一组插入到AmendmentTypeGroup中,以获取组ID,然后插入带有您插入的组值的修订行。如果已经有一个具有特定组合的组,只需获取其ID并使用它即可。

declare @amendmentCombination nvarchar(max)
declare @groupID int
select amendmentCombination=string_agg(convert(nvarchar(max),AmendmentTypeID),',') WITHIN GROUP ( ORDER BY AmendmentTypeID asc)
from AmendmentType
where IsActive = 1 -- will only work for sql server version 2017. Search XML path concatenation if you don't have it
select @groupID=AmendmentTypeGroupID
from AmendmentTypeGroup
where AmendmentTypes=@amendmentCombination
if @groupID is null
begin
    insert AmendmentTypeGroup(AmendmentTypes) select @amendmentCombination
    set @groupID=SCOPE_IDENTITY() -- last id entered
end

insert Amendments(..your_other_columns...,AmendmentTypeGroup)
    select ..your_other_columns...,@groupID

这样,对于每个修订行,您可以将其与AmendmentTypeGroup合并,以获取当时可用的AmendmentTypes的逗号分隔列表。您必须将其拆分为表格格式。

为使数据更健壮,您应该1)手动创建用于修订中已经存在的行的所有AmendmentTypeGroups,然后将其ID插入Amendment.AmendmentTypeGroup,以便随后可以2)在修订中创建FK .AmendmentTypeGroup引用AmendmentTypeGroup.AmendmentTypeGroupID 3)在AmendmentTypeGroup.AmendmentTypes上创建唯一约束

如您所见,这很困难。小心踩。