SQLite 触发器背靠背调用

问题描述 投票:0回答:1

我在 SQLite 数据库中调用了这些背对背触发器。我有一个名为“体重”的表格,用于计算 BMI 和 NIH 健康标准体重分类。这就是我的代码的样子:

CREATE TABLE weight(
    id INTEGER PRIMARY KEY,
    date_and_time TEXT,
    weight_in_lb INTEGER,
    height_ft INTEGER,
    height_in INTEGER,
    BMI FLOAT,
    reference TEXT
);
CREATE TRIGGER insert_BMI
AFTER INSERT ON weight
FOR EACH ROW
BEGIN
    UPDATE weight
    SET BMI = (NEW.weight_in_lb/POWER(NEW.height_ft * 12 + NEW.height_in,2)) * 703
    WHERE id = NEW.id;
END;
CREATE TRIGGER insert_reference_overweight
AFTER INSERT ON weight
FOR EACH ROW
WHEN NEW.BMI > 25
BEGIN
    UPDATE weight
    SET reference = 'OVERWEIGHT'
    WHERE id=NEW.id;
END;
INSERT INTO weight(id,date_and_time,weight_in_lb,height_ft,height_in)
    VALUES(1,'4/20/2000',272,5,10);

由于某种原因,第二个触发器没有创建我想要的参考值,是因为触发器的结构没有检测到相同的 id 1 吗?或者有没有办法让该触发器在我的第一个触发器之后运行?

我希望超重参考出现在表格中。

sqlite
1个回答
0
投票

您的

INSERT
声明:

INSERT INTO weight(id,date_and_time,weight_in_lb,height_ft,height_in) VALUES (1,'4/20/2000',272,5,10);

插入一个新行,其中

null
值为
BMI

然后,您的

AFTER INSERT
触发器将按照未定义(未记录)的顺序被触发。

假设首先触发

insert_BMI
触发器并设置
BMI
的值。

您对接下来要触发的

insert_reference_overweight
的期望是设置列
reference

但是,这个触发器包含这个
WHEN
子句:

WHEN NEW.BMI > 25

并检查

BMI
插入的原始值,即
null
,而不是第一个触发器更新的值。
由于
null > 25
永远不会
true
,因此永远不会执行用于设置
UPDATE
值的
reference
语句。

您可以做的是将

insert_reference_overweight
触发器更改为
AFTER UPDATE
触发器,以便在
UPDATE
触发器的
insert_BMI
语句之后触发:

CREATE TRIGGER update_reference_overweight AFTER UPDATE ON weight
WHEN NEW.BMI > 25
BEGIN
  UPDATE weight
  SET reference = 'OVERWEIGHT'
  WHERE id = NEW.id;
END;

请注意,链接触发事件总是很棘手。

查看简化的演示

另一个解决方案是使用生成的列(需要 SQLite 版本 3.31.0+)而不是触发器:

CREATE TABLE weight(
  id INTEGER PRIMARY KEY, 
  date_and_time TEXT, 
  weight_in_lb INTEGER, 
  height_ft INTEGER, 
  height_in INTEGER, 
  BMI FLOAT GENERATED ALWAYS AS (weight_in_lb/POWER(height_ft * 12 + height_in,2)) * 703
  reference TEXT GENERATED ALWAYS AS (CASE WHEN BMI > 25 THEN 'OVERWEIGHT' END)
);

查看演示

© www.soinside.com 2019 - 2024. All rights reserved.