我一直在网上寻找答案。但我得到的只是简单的答案。
我的数据库中有几列应该对其最大值有约束,但如果另一列设置为false则不会
例如。我在表格中有以下值
ROW ValueA TRUE/FALSE ValueB
0 3750 TRUE 0
1 5000 TRUE 0
2 5000 FALSE 0 [INITIAL VALUES PROVIDED]
2 3750 FALSE 1250 [ACTUAL VALUES ACCEPTED]
在此表中,Row2由外部程序提供,其中ValueA最初为5000,但该行的值设置为FALSE,因此它将值限制为3750并将值1250添加到ValueB
现在的想法是,如果设置为true,它可以绕过检查。 但如果该行设置为false且值大于3750it,则应将ValueA减少回3750并将余数放入ValueB。
这是否可以使用Constraint Check表达式,或者在此使用Before Update触发器更为谨慎?
答案 0 :(得分:1)
我认为,这听起来像'复杂'的商业逻辑。
复杂,我的意思是一些检查,以及一些基于规则的不同行为。
在这种情况下,我会在触发器中进行检查。
答案 1 :(得分:1)
你需要一个触发器,因为约束不能根据条件设置另一列的值(就像你在这里一样)
答案 2 :(得分:1)
我建议你有两个表:一个用于保存外部程序的原始数据的临时表和一个应用了业务规则的第二个表。第二个表可以是VIEW
,它通过应用规则来查询数据,例如(我正在使用CTE来模拟带有示例数据的登台表;同样,SQL Server没有真正的布尔类型,因此我使用CHAR(1)
列模拟它并且名称正在我的头脑中所以我将它改为some_flag
!):
WITH Staging
AS
(
SELECT *
FROM (
VALUES (0, 3750, 'T'),
(1, 5000, 'T'),
(2, 5000, 'F')
) AS T (ROW, ValueA, some_flag)
)
SELECT ROW, ValueA, some_flag,
0 AS ValueB
FROM Staging
WHERE ( ValueA <= 3750 OR some_flag = 'T' )
UNION
SELECT ROW, 3750 AS ValueA, some_flag,
( ValueA - 3750 ) AS ValueB
FROM Staging
WHERE ValueA > 3750 AND some_flag = 'F';
如果您希望第二个表是基表,那么以下约束(使用传统逻辑)似乎适用:
IF some_flag = 'F' THEN ValueA <= 3750
IF some_flag = 'T' THEN ValueB = 0
IF some_flag = 'F' AND ValueA < 3750 THEN ValueB = 0
在SQL中作为CHECK
约束(我已经猜到了一些'常识'业务规则):
CREATE TABLE MyTable
(
ROW INTEGER NOT NULL UNIQUE,
ValueA INTEGER NOT NULL CHECK ( ValueA > 0 ),
some_flag CHAR(1) NOT NULL CHECK ( some_flag IN ( 'T', 'F' ) ),
ValueB INTEGER NOT NULL CHECK ( ValueB >= 0 ),
CHECK ( some_flag <> 'F' OR ValueA <= 3750 ),
CHECK ( some_flag <> 'T' OR ValueB = 0 ),
CHECK ( some_flag <> 'F' OR ValueA >= 3750 OR ValueB = 0 )
);
然后,您可以使用上述查询将数据从登台表复制到基表,同时不违反任何约束,但知道如果查询错误,则程序将失败!