2013-02-21 66 views
1

我有2列(A as boolB as text)的表,这些列可以是:SQL服务器:存储过程或函数

  1. 两者空
  2. 如果A是假的,则B应为空
  3. 如果A为真,则B应该是不为空

有规则。我想要创建一个存储过程或函数来在添加或更新行时(通过触发器)检查这些规则。什么更好,存储过程或函数?如果功能,哪种类型?一般来说,哪个变体是最好的(返回布尔值或其他方式等)?

+0

为什么不使用触发器? – Kermit 2013-02-21 16:21:28

+0

这里如何写触发器? – 2013-02-21 16:24:16

+1

[阅读手册](http://msdn.microsoft.com/en-us/library/ms189799.aspx)。 – Kermit 2013-02-21 16:25:36

回答

11

我想你是在CHECK Constraint之后。

实施例:

ALTER TABLE Xxx 
    ADD CONSTRAINT chk_Xxx 
    CHECK ((A IS NULL AND B IS NULL) 
     OR (A = 0 AND B IS NULL) 
     OR (A = 1 AND B IS NOT NULL) 
     ) ; 
+0

我也赞成。对于这种情况,这可能是最好的答案。如果逻辑对于像这样的“在线”解决方案变得太复杂,我的答案是“可能性”。 – granadaCoder 2013-02-21 20:37:38

2

我会用一个检查约束有线到一个UDF。
下面是一个愚蠢的例子验证,如果你插入一个人,他们的年龄将大于17

if NOT exists (select * from sysobjects 
    where id = object_id('dbo.udfOlderThan17Check') and sysstat & 0xf = 0) 
    BEGIN 
     print 'Creating the stubbed version of dbo.udfOlderThan17Check' 
     EXEC ('CREATE FUNCTION dbo.udfOlderThan17Check (@j as smallint) RETURNS bit AS BEGIN RETURN 0 END') 
    END 
GO 


ALTER FUNCTION dbo.udfOlderThan17Check (@Age smallint ) 
    RETURNS bit AS 
    BEGIN 
     declare @exists int 

     select @exists = 0 

     if (@Age IS NULL) 
      BEGIN 
       select @exists = 1 -- NULL VALUES SHOULD NOT BLOW UP THE CONSTRAINT CHECK 
      END 

     if (@exists = 0) 

     BEGIN 

      if @Age > 17 
       begin 
        select @exists = 1 
       end  

      END 

     return @exists 
    END 



GO 



IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[Person]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
    BEGIN 
     DROP TABLE [dbo].[Person] 
    END 
GO 


CREATE TABLE [dbo].[Person] 
(
     PersonUUID [UNIQUEIDENTIFIER] NOT NULL DEFAULT NEWSEQUENTIALID() 
    , Age smallint not null 
) 

GO 


ALTER TABLE dbo.Person ADD CONSTRAINT PK_Person 
PRIMARY KEY NONCLUSTERED (PersonUUID) 
GO 


ALTER TABLE dbo.Person 
ADD CONSTRAINT [CK_Person_AgeValue] CHECK ([dbo].[udfOlderThan17Check]([Age]) != 0) 
GO 

这里有一些“测试”:

INSERT INTO dbo.Person (Age) values (33) 
INSERT INTO dbo.Person (Age) values (16) 

INSERT INTO dbo.Person (Age) select 333 UNION select 58 
INSERT INTO dbo.Person (Age) select 444 UNION select 4 

select * from dbo.Person 
+1

检查约束可能是这样做的方法,因为UDF对于在大型数据集上检查像这样的东西不会非常高效 – JNK 2013-02-21 16:30:08

+0

我同意CHECK是最有可能的候选者。请记住,我的示例是一个检查限制,但也使用UDF。但是,如果需要,UDF允许进行一些“高级”检查,所以我提供了这个选项。如果他能以正常的方式获得胜利,那将是一条可行的路。 – granadaCoder 2013-02-21 16:33:32

+0

看过这个问题稍微好一点我的例子有点没有意义:)并且这更好地捕获它... – chrisb 2013-02-21 16:41:41