根据另一个字段在字段中创建约束

时间:2011-08-04 12:19:09

标签: tsql sql-server-2008 triggers

我有一个带有三个字段的表T1:

id integer
Vocation integer : VOCATION = 1 or 2 or 3 or 4or 5
TYPE integer     : TYPE = 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8

类型取决于VOCATION。例如:

  • 如果VOCATION = 1,则TYPE应为= 2或3或4或6
  • 如果VOCATION = 2,TYPE应为= 4或5等

我使用sqlserver2008

我会在TYPE中创建一个约束,如果VOCATION的值为2,则强制约束的值为4或5,等等。

我希望触发器解决方案,所以我用sql创建一个触发器。它接受但表中没有效果

这是触发器代码(sql)

CREATE TRIGGER [dbo].[tg_T1]
ON [dbo].[T1]
after INSERT, UPDATE
AS

DECLARE @VOCATION int
DECLARE @TYPE int

BEGIN
   IF @VOCATION =1 
   SET @TYPE = 2
END

3 个答案:

答案 0 :(得分:1)

在触发器中,您不能仅将列作为变量引用。您需要使用INSERTED行集。这表示插入的数据并导致触发器触发。花一些时间阅读这篇MSDN文章:http://msdn.microsoft.com/en-us/library/aa258254(v=sql.80).aspx

对于代码,它看起来像这样:

CREATE TRIGGER [dbo].[tg_T1]
ON [dbo].[T1]
after INSERT, UPDATE
AS

BEGIN
   UPDATE T1
   SET TYPE = 
     CASE 
       WHEN VOCATION = 1 THEN 2
       WHEN VOCATION = 2 THEN 3
       ...
     END
   FROM T1
   INNER JOIN INSERTED I ON T1.YOUR_PRIMARY_KEY = I.YOUR_PRIMARY_KEY
END

答案 1 :(得分:1)

使用检查约束可以在没有触发器的情况下解决此问题。但您需要确保同时更新VOCATIONTYPE以避免例外情况。也就是说,如果VOCATION = 2TYPE = 5,那么您将无法使用VOCATION更新1而无需将TYPE更改为TYPE相关值,如果没有6的相应更改,您将无法使用VOCATION更新TYPE。如果约束条件允许,您仍然可以在不更改VOCATION的情况下更新ALTER TABLE dbo.T1 ADD CONSTRAINT CK_T1_TypeVocation CHECK ( VOCATION = 1 AND TYPE IN (2, 3, 4, 6) OR VOCATION = 2 AND TYPE IN (4, 5) OR … /* other conditions as necessary */ )

这是约束定义:

{{1}}

答案 2 :(得分:1)

一个想法:

  • 创建另一个表(T1Check,比如说),只有VOCATION和TYPE
  • T1Check上的主键是两列
  • 使用有效对填充T1Check
  • 在T1上为VOCATION和TYPE创建一个外键,引用T1Check

这意味着只允许T1中的数据与T1Check中允许的对匹配。

更重要的是,您可以将新的VOCATION和TYPE组合添加到T1Check ,而无需更改任何代码(触发器)或CHECK约束。它是所有数据驱动的,更易于维护。

您甚至可以构建一个GUI,让业务用户在T1Check中定义新的VOCATION / TYPE规则。