2012-02-21 189 views
2

我一直在寻找网络的一些答案。但我得到的只是简单的答案。SQL约束检查或触发器?

我在我的数据库中的几列应该有一个约束他们的最大值,但如果另一列设置为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] 

下列值在该表是由一个外部程序,其中值a是最初5000提供行2,但该行的值被设置为FALSE,因此将限制值到3750并将1250添加到ValueB

现在的想法是,如果设置为true,则可以绕过检查。 ,但是如果它被设置为false,并且该值大于3750it,则应将ValueA降低回3750,并将余数放在ValueB中。

这是可能的做一个约束检查表达式,还是更谨慎的使用之前更新触发器?

回答

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) 
); 

然后,您可以使用上面的查询将数据从临时表复制到基表,同时不违反任何约束,但是在知道如果您的查询错误时该过程将失败!

+0

谢谢,无法为真正的错误位提供更好的名称,它确实是一个包含T或F的char字段。感谢您的洞察力。我将其标记为我的答案,因为它包含一个示例。 – Raskaroth 2012-02-24 08:55:21

1

我的看法,这听起来像'复杂'的业务逻辑。

复杂,我的意思是一些如果检查,和一些不同的行为基于规则。

在这种情况下,我会做一个触发器检查。

+0

谢谢你的开关响应,我正在倾向一个触发器,我自己只是不确定是否会因为我读了这么多关于它们的负面消息而不好用。 – Raskaroth 2012-02-21 19:05:04

+0

这种类型的使用非常棒 - 在掩盖巨大的程序性行为会降低性能时,人们会遇到麻烦。 – Randy 2012-02-21 19:08:00

+0

谢谢,那么我有我需要的答案! – Raskaroth 2012-02-21 19:10:47

1

你需要一个触发是因为限制无法设置基于条件的另一列的值(如你在这里做)