2013-02-21 65 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