【问题标题】:Sqlite: Trigger to restrict number of values in rowSqlite:触发以限制行中的值数量
【发布时间】:2017-07-17 10:34:04
【问题描述】:

我有一个指定产品功能的 sqlite 表。特征,例如颜色,在布尔列中。列是“1”或“NULL”。有些功能是专有的。由于表结构是固定的,我尝试创建一个引发异常的触发器,但它不起作用。我做错了什么?

例子:

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;

【问题讨论】:

  • 您要检查哪一行?要插入的那个,还是其他的?
  • 插入一个就足够了。我想按照描述设置的触发器会检查所有行,但我想一次解决一个问题

标签: sqlite database-trigger


【解决方案1】:

您不需要触发器;这可以通过检查约束来完成:

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等访问)

【讨论】:

  • 带有检查约束的解决方案效果很好,我没有进一步处理触发器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2020-06-08
相关资源
最近更新 更多