2011-07-07 22 views
6

我知道SQL約束可以強制數據滿足有效性標準。然而,關於「學生等級」這樣的標準,只有在「最終確定」標誌爲假時才能更新?這樣的更新標準是否必須由應用程序來處理?當條件成立時,是否可以使用SQL約束來防止特定值發生更改?

+5

根據您的RDBMS,您可以在表格上使用「before」或「instead of」觸發器來強制執行此操作。 –

+0

喬說什麼,儘管也可以使用檢查約束,這取決於數據庫。 – Oded

回答

3

簡答:不,SQL約束本身無法阻止當Finalized爲'true'(但允許進行其他更改)時更改列等級。

several kinds of SQL constraints:CHECK,DEFAULT,NOT NULL,UNIQUE,主鍵和外鍵。

這些都可以單獨或組合地限制或影響列的值,但不能阻止對允許的值進行UPDATE。特別是,這些約束條件都不能阻止基於以前的Grade和Finalized值更新爲Grade和/或Finalized。

UPDATE觸發器可以執行此操作:比較Grade的新值和舊值,如果這些值不同並且Finalized ='true',則回滾UPDATE並附帶說明性錯誤消息。

但是,應用程序可以並且應該更加優雅地執行這樣的「業務規則」。規則本身可以稍微澄清一下關於Finalized值何時可以改變的說明。例如。,是否允許更改等級並同時設置Finalized ='false'?觸發器邏輯可以處理這些細節,並且將它作爲故障安全來安裝是合理的,同時使規則在應用程序的某處(前端/中間件/後端)也是明確的。

-2

IMO,我會說它應該在應用程序或存儲過程(可能兩者),而不是作爲一個實際的約束(除其他外,在你的具體例子中,一個等級被「最終確定」永遠不會意味着它實際上是最終的)。

但是,如果我實現這個作爲一個約束,我會使用一個CHECK約束(再次使用你的例子)

CONSTRAINT chk_grade CHECK(grade between 0 AND 100 and finalized = 0) 

檢查,具體的語法,但它是在那裏我開始。

+1

當最終標誌被設置時,這會如何防止更新等級?它不妨礙最終確定的國旗被設置?我不認爲這是OP的想法。 – hardmath

+0

我必須仔細檢查語法(正如我所提到的),但它/它應該做的是在允許範圍爲0 - 100之前驗證'finalized' = 0(即它是「False」)放置在'grade'中 – AllenG

+0

這不起作用(無論如何,在SQL Server中),因爲當您嘗試將'finalized'轉換爲1時,檢查失敗。 – atheaos

3

觸發器,約束和附加列。

從端部開始:

  1. 附加列存儲要被 '固定' 的值:

    ALTER TABLE ADD SavedGrade int 
    
  2. 約束限制了Grade列的變化:

    ALTER TABLE Students 
    ADD CONSTRAINT CK_Grade CHECK (Finalised = 'false' OR Grade = SavedGrade) 
    
  3. 觸發器更新附加公司lumn當Grade列被更新(以下是SQL Server):

    CREATE TRIGGER StudentsFinaliseGrade 
    ON Students AFTER INSERT, UPDATE 
    AS 
    IF UPDATE(Grade) 
        UPDATE Students 
        SET SavedGrade = i.Grade 
        FROM inserted i 
        WHERE i.ID = Students.ID 
        AND i.Grade <> i.SavedGrade 
    

所以,只要Finalised = 'false',該Grade列可以被改變。當它更改爲時,該值立即存儲到SavedGrade列中。 (我們正在更新SavedGrade,因爲否則約束將不允許我們將Finalised設置爲'true'。)只要設置了Finalised,由於約束,您不能再更改Grade列。

相關問題