2017-07-17 53 views
1

我有一個sqlite表,其中指定了產品功能。這些特徵,例如顏色,都在布爾列中。列是「1」或「NULL」。有些功能是獨家的。由於表結構是固定的,我試圖創建一個引發異常的觸發器,這是不起作用的。我究竟做錯了什麼?Sqlite:觸發器來限制行中的數量值

實施例:

CREATE TABLE productColor(
    productId INTEGER PRIMARY KEY, 
    isRed INTEGER, 
    isBlue INTEGER, 
    isYellow INTEGER, 
    isBrown INTEGER) 

該產品只能有一個顏色。我的想法是計算指定了多種顏色的列,即少於三個NULL值。如果至少有一個這樣的行,則觸發器會引發異常。所以這就是我的觸發器的樣子:

CREATE TRIGGER onlyOneColor 
    BEFORE INSERT ON productColor 
    WHEN 
     (SELECT COUNT (*) FROM 
     (SELECT ((CASE WHEN isBrown IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isRed IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isBlue IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isYellow IS NULL THEN 1 ELSE 0 END)) 
     AS sumOfNulls FROM productColor) WHERE sumOfNulls<3) 
    >=1 
    BEGIN 
    SELECT RAISE(FAIL, 'More then one color specified'); 
    END; 
+0

您想檢查哪一行?要插入的還是其他的? –

+0

插入的就足夠了。我想按照描述設置的觸發器會檢查所有行,但我想一次解決一個問題。 – Fab

回答

0

你不需要觸發器;這可以通過檢查約束來實現:

CREATE TABLE productColor (
    productId INTEGER PRIMARY KEY, 
    isRed  INTEGER CHECK (isRed = 1 OR isRed IS NULL), 
    isBlue INTEGER CHECK (isBlue = 1 OR isBlue IS NULL), 
    isYellow INTEGER CHECK (isYellow = 1 OR isYellow IS NULL), 
    isBrown INTEGER CHECK (isBrown = 1 OR isBrown IS NULL), 
    CHECK (ifnull(isRed, 0) + ifnull(isBlue, 0) + 
      ifnull(isYellow, 0) + ifnull(isBrown, 0) <= 1) 
); 

如果您存儲的所有值0或1,這些檢查會更簡單。 (0並不需要比NULL任何更多的存儲空間。)


如果你真的需要一個觸發,你可以把倒條件進入WHEN子句。 (請注意,待插入行的值可以通過NEW.isRed等進行訪問)

+0

帶有檢查限制的解決方案效果很好,我沒有進一步處理觸發器 – Fab