0

我有一个包含 2 个表(sql server 2008)的数据库:

贷款委员会

身份证号码

佣金小数

佣金等级

身份证号码

最小佣金小数

最大佣金小数

我想在 2 个表之间建立关系。显而易见的方法是将 CommissionTierId 添加到 LenderCommission 表中,但随后会修复此问题。如果层级的佣金结构发生变化,所有 LenderCommissions 都需要重新评估。

我不是专家,但我猜不可能在和Commission之间建立关系。但是,有什么方法可以使这种关系更加流畅吗?MinCommissionMaxCommission

4

2 回答 2

1

我不太确定你想要做什么——我已经整理了一个演示,展示了你可能希望事情起作用的一种方式。我们实际上创建了一个包含更多列的表,然后使用几个触发器将其隐藏在视图后面,以确保一切正常。

表格:

create table dbo.CommissionTier (
    ID int not null,
    MinCommission decimal not null,
    MaxCommission decimal not null,
    constraint PK_CommissionTier PRIMARY KEY (ID),
    constraint UQ_CommissionTier_RangeValidation UNIQUE (ID,MinCommission,MaxCommission) --This is to support our FK below
)
go
create table dbo._LenderCommission (
    ID int not null,
    Commission decimal not null,
    CommissionTier int not null,
    _MinCommission decimal not null,
    _MaxCommission decimal not null,
    constraint PK__LenderCommission PRIMARY KEY (ID),
    constraint CK__LenderCommission_InRange CHECK (
        _MinCommission < Commission and --Inclusive or exclusive bound? <= or <
        Commission < _MaxCommission --Ditto?
    ),
    constraint FK__LenderCommission_Tier
       FOREIGN KEY (CommissionTier)
       references dbo.CommissionTier (ID), --This FK isn't actually needed
    constraint FK__LenderCommission_Tier_Range
       FOREIGN KEY (CommissionTier,_MinCommission,_MaxCommission)
       references dbo.CommissionTier(ID,MinCommission,MaxCommission) on update cascade
)

视图(从现在起您将其视为原始表):

create view dbo.LenderCommission
with schemabinding
as
    select
        ID,
        Commission,
        CommissionTier
    from
        dbo._LenderCommission
go

您可能不需要这个,但是当视图伪装成表时,我倾向于始终放置索引,并为其赋予与原始主键相同的名称:

create unique clustered index PK_LenderCommission on dbo.LenderCommission(ID)

现在有几个触发器可以进行一些必要的房屋清洁:

create trigger dbo.T_LenderCommission_I
on dbo.LenderCommission
instead of insert
as
    set nocount on

    insert into dbo._LenderCommission (ID,Commission,CommissionTier,_MinCommission,_MaxCommission)
    select i.ID,i.Commission,i.CommissionTier,ct.MinCommission,ct.MaxCommission
    from
        inserted i
            inner join
        dbo.CommissionTier ct
            on
                i.CommissionTier = ct.ID
go
create trigger dbo.T_LenderCommission_U
on dbo.LenderCommission
instead of update
as
    set nocount on

    update lc
    set
        Commission = i.Commission,
        CommissionTier = i.CommissionTier,
        _MinCommission = ct.MinCommission,
        _MaxCommission = ct.MaxCommission
    from
        dbo._LenderCommission lc
            inner join
        inserted i
            on
                lc.ID = i.ID
            inner join
        dbo.CommissionTier ct
            on
                i.CommissionTier = ct.ID

现在我们填充它们:

insert into CommissionTier(ID,MinCommission,MaxCommission) values
(1,0,1000),
(2,1000,2000),
(3,2000,3000)
go
insert into LenderCommission(ID,Commission,CommissionTier) values
(1,500,1),
(2,750,1),
(3,1500,2)

现在出现一些错误:

--This produces an error:
insert into LenderCommission(ID,Commission,CommissionTier) values
(4,500,2)
go
--This produces an error:
update LenderCommission set Commission = 2500 where ID=2
go
--This *doesn't* produce an error because the new value matches the new tier
update LenderCommission set Commission = 2500,CommissionTier = 3 where ID=2
go
--This is okay, we're adjusting one of the tiers
update CommissionTier set MaxCommission = 1550 where ID = 2
go
--This produces an error, because the cascading foreign key updated the values:
update LenderCommission set Commission = 1600 where ID = 3

作为上述的替代方案CK__LenderCommission_InRange,您可以创建一个计算列来执行相同的检查并采用合适的值,而不是使用 :

CommissionOutOfRange AS
  CASE WHEN Commission < MinCommission THEN -1
  CASE WHEN Commission > MaxCommission THEN 1
  ELSE 0 END

现在您可以快速在表格中搜索超出范围的值(但没有什么能阻止它们被创建

于 2013-05-17T13:48:49.743 回答
1

我不完全理解你的目标。表之间似乎已经存在逻辑关系;据推测,佣金可能介于最小值和最大值之间。你可以这样加入:

select <whatever>
from LenderCommission lc join
     CommissionTier ct
     on lc.commission between ct.MinCommission and ct.MaxCommission;

你想做什么?

一种可能性是您希望通过将其转换为等值连接而不是“中间”连接来提高此连接的效率。拥有身份证肯定会做到这一点。如果 CommissionTier 表只有几十行,那么这种效率水平可能并不重要。

也许您正试图在表之间强制执行约束,因此只能使用佣金层添加新佣金。如果是这样,您可以通过触发器进行检查。

真正将这种关系转换为单个外键会很复杂。您需要考虑以下事项:

  • 防止重叠的佣金等级。
  • 当佣金等级发生变化时更改外键关系(即修改eaderCommission.
  • 维护佣金等级的历史数据,如果您需要在不同的时间点查看“它是什么”。

这些都是可能的,但可能比您预期的要复杂得多。

于 2013-05-17T13:12:47.927 回答