如何在 SQL 中使用触发器来更新一行,基于另外两行

Posted

技术标签:

【中文标题】如何在 SQL 中使用触发器来更新一行,基于另外两行【英文标题】:How to use a trigger in SQL to update a row, based in two other rows 【发布时间】:2019-11-24 12:24:11 【问题描述】:

也许这太简单了,但我对这项任务感到头疼,我正在为一些作业建立一个健身房数据库,我必须分别根据名为身高和体重的其他行计算 BMI。我不知道更新这个表的方法,我已经尝试过

create or replace trigger calculate_BMI
after insert or update on evaluation
begin
    update evaluation
    set BMI = i.bmi, weight = weight(height*height)
    from inserted as i
end

这就是我发现的

SQL Error: ORA-04098: trigger 'BJ111237.CALCULATE_BMI' is invalid and failed re-validation
04098. 00000 -  "trigger '%s.%s' is invalid and failed re-validation"
*Cause:    A trigger was attempted to be retrieved for execution and was
           found to be invalid.  This also means that compilation/authorization
           failed for the trigger.
*Action:   Options are to resolve the compilation/authorization errors,
           disable the trigger, or drop the trigger.

它不起作用,如果有人带我看一些内容来学习如何正确执行此操作,我将不胜感激,因为我被卡住了

【问题讨论】:

【参考方案1】:

假设您使用标准 BMI 计算并且您的值使用适当的单位存储,那么更新的 Oracle 语法将是:

create or replace trigger calculate_BMI
before insert or update on evaluation
for each row
begin
    :new.bmi := :new.weight / (:new.height * :new.height);
end;

这是一个“之前”触发器。它只是设置新值进行计算。不需要更新,因为您想更改正在更新的同一个表的同一行中的列值。

Here 是一个展示它的实验者。

【讨论】:

create or replace trigger calculate_bmi before insert or update on evaluation begin :new.bmi = :new.weight/ (:new.height*:new.height); end; 我试过了,但返回 ORA-04082: NEW or OLD references not allowed in table level trigger @GabrieRabelo 。 . .触发器需要for each row。我还修正了一个错字并添加了一个工作示例。【参考方案2】:

您需要指定是要更改现在更新的新值还是旧值。

例如:

set new.BMI = i.bmi, weight = new.weight(height*height)

【讨论】:

【参考方案3】:

您的代码有问题:

触发器无法操作触发它的表;您确实需要设置 bmibefore 触发器,而不是尝试更新表 evaluationafter 触发器

您的触发器应该逐行触发,而不是在语句级别触发(因此它需要for each row 选项)

伪表inserted在Oracle中不存在;相反,您可以使用 :new. 访问为更新或插入传递的值

你可能想要:

create or replace trigger calculate_bmi
after insert or update on evaluation
for each row
begin
    :new.bmi := :new.weight / (:new.height * :new.height);
end

【讨论】:

我试过这个:```在插入或更新每一行的评估之前创建或替换触发器calculate_bmi 开始:new.bmi = :new.weight / (:new.height * :new 。高度); end ``` 但它也不起作用,它正在返回 Encountered the symbol "=" 当期待以下之一时::= 。 ( @ % ; 指示符 在预期以下情况之一时遇到符号“;”:) , * & - + / at mod remaining rem and or ||年日 @GabrieRabelo:抱歉,它必须是 :new.bmi := 而不是 set :new.bmi =。固定。

以上是关于如何在 SQL 中使用触发器来更新一行,基于另外两行的主要内容,如果未能解决你的问题,请参考以下文章

PL / SQL触发器在更新或插入后更新同一个表

如何创建只更新一行的触发器

如何在 SQL 中对触发器进行语法化,以便在插入后从同一个表中更新列(oracle 数据库)

使用 PL/SQL 在触发器中中止插入/更新操作

SQL间的两个数据库表的同步更新

SQL Server2008 触发器中,根据一个表修改另外一个表