Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL约束检查还是触发器?_Sql_Sql Server 2005_Triggers_Constraints - Fatal编程技术网

SQL约束检查还是触发器?

SQL约束检查还是触发器?,sql,sql-server-2005,triggers,constraints,Sql,Sql Server 2005,Triggers,Constraints,我一直在网上寻找答案。但我得到的只是简单的答案 我的数据库中有一些列应该对它们的最大值有一个约束,但如果另一列设置为false,则没有约束 我在表中有以下值 ROW ValueA TRUE/FALSE ValueB 0 3750 TRUE 0 1 5000 TRUE 0 2 5000 FALSE

我一直在网上寻找答案。但我得到的只是简单的答案

我的数据库中有一些列应该对它们的最大值有一个约束,但如果另一列设置为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]
在此表中,第2行由外部程序提供,其中ValueA最初为5000,但该行的值设置为FALSE,因此将该值限制为3750,并将1250添加到ValueB

现在的想法是,如果设置为true,它可以绕过检查。 但是,如果该行的值设置为false,并且该值大于3750,则应将ValueA减回到3750,并将剩余值放入ValueB中


这可能与约束检查表达式有关,还是更谨慎地使用更新前触发器?

我认为,这听起来像是“复杂”的业务逻辑

所谓复杂,我指的是一些if检查,以及一些基于规则的不同行为


在本例中,我将在触发器中进行检查。

您需要一个触发器,因为约束无法根据条件设置另一列的值(正如您在这里所做的那样)

我建议您有两个表:一个用于保存外部程序原始数据的暂存表,另一个用于应用业务规则的表。第二个表可能只是一个
视图
,它通过应用规则来查询数据,例如(我使用CTE用示例数据模拟暂存表;另外,SQL Server没有真正的布尔类型,所以我使用
字符(1)模拟它)
列中的名称将我的头部插入,因此我将其更改为
某些标志
!):


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

谢谢你的switft回复,我自己也倾向于使用触发器,只是不确定使用触发器是否不好,因为我读到了很多关于触发器的负面信息。这种类型的使用非常好-人们在埋葬会降低性能的巨大程序行为时会遇到麻烦。谢谢,那么我就有了我需要的答案!当然,不要忘记编写(和测试)触发器,以便它能够处理多个记录插入/更新。SQL Server不会在触发器中循环遍历批处理中的每条记录。。。这里可能也有一个潜在的规范化问题。谢谢,我想不出一个更好的名称来表示真-假位,它确实是一个包含t或F的字符字段。谢谢您的见解。我将此标记为我的答案,因为它包含一个示例。
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
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 )
);