Sql 在ORACLE中添加新值后更新列

Sql 在ORACLE中添加新值后更新列,sql,oracle,Sql,Oracle,我在创建一个触发器时遇到了一些问题,该触发器将获得一个人的当前点数,检查他将获得什么奖励,然后更新他的奖励标题。所以这是一个场景: PersonTable | Person (PK) | RewardTitle (FK) | Score| | A | Beginner | 0 | | B | MidRange | 17 | | C | Professio

我在创建一个触发器时遇到了一些问题,该触发器将获得一个人的当前点数,检查他将获得什么奖励,然后更新他的奖励标题。所以这是一个场景:

     PersonTable
    | Person (PK) | RewardTitle (FK) | Score|
    | A           | Beginner         | 0    |
    | B           | MidRange         | 17   |
    | C           | Professional     | 32   |

     RewardTable
    | RewardTitle (PK) | BottomScore | UpperScore| Reward        |
    | Beginner         | 0           | 9         | Free food     |
    | MidRange         | 10          | 19        | Free games    |
    | Professional     | 20          | 100       | Unlimited time|
情况是,我想更新A个人,使他现在有11分,然后找出他的新分数属于哪一个奖赏头衔,并相应地更改他的奖赏头衔,因此,由于他有11分,他的奖赏头衔现在将是中等的

我试图创建一个触发器,试图找到他所属的RewardTitle,然后相应地更新该值,但我一直收到一个错误,上面说:

    Person is mutating, trigger/function may not see it
我理解这个问题,但我想不出任何其他方法来实现这个结果。我试过使用

    pragma autonomous_transaction;
但它仍然不起作用,以下是我的尝试:

    UPDATE PersonTable
    SET Score = 11
    WHERE Person = 'A';

    DELIMITER //
    CREATE OR REPLACE TRIGGER person_upd_trigger
    AFTER UPDATE ON PersonTable
    FOR EACH ROW
    DECLARE
        temp_variable VARCHAR(120);
    BEGIN
        SELECT r.RewardTitle INTO temp_variable
        FROM PersonTable p, RewardTable r
        WHERE :NEW.Person = p.Person
        AND p.Score BETWEEN r.BottomScore AND r.UpperScore;

        UPDATE PersonTable
        SET RewardTitle = temp_variable
        WHERE :NEW.Person = Person;
   END;

我将非常感谢我能得到的所有帮助,我对Oracle SQL还很陌生。谢谢

您不能在BEFORE触发器中更新您正在更新的同一个表(如果假定允许,将导致无限循环)。相反,您需要将触发器重新写入:

为了使其工作,您应该将触发器定义更改为
之前的

CREATE OR REPLACE TRIGGER person_upd_trigger
BEFORE UPDATE ON PersonTable -- declare it as BEFORE
FOR EACH ROW
DECLARE
    temp_variable VARCHAR(120);
BEGIN
    SELECT r.RewardTitle INTO temp_variable
    FROM RewardTable r
    WHERE :NEW.Score BETWEEN r.BottomScore AND r.UpperScore;

    -- here you are setting the new value, no need for an update.
    :NEW.RewardTitle := temp_variable;
END;

不能在BEFORE触发器中更新已在更新的表(如果假定允许,将导致无限循环)。相反,您需要将触发器重新写入:

为了使其工作,您应该将触发器定义更改为
之前的

CREATE OR REPLACE TRIGGER person_upd_trigger
BEFORE UPDATE ON PersonTable -- declare it as BEFORE
FOR EACH ROW
DECLARE
    temp_variable VARCHAR(120);
BEGIN
    SELECT r.RewardTitle INTO temp_variable
    FROM RewardTable r
    WHERE :NEW.Score BETWEEN r.BottomScore AND r.UpperScore;

    -- here you are setting the new value, no need for an update.
    :NEW.RewardTitle := temp_variable;
END;

你好,Jorge,谢谢你的回复,我已经尝试根据你的建议更改我的触发器,但是在执行时,它会给我一个“无法更改此触发器类型的新值”?抱歉,没有注意到你的触发器是AFTER。我会更改答案。非常感谢Jorge,你帮了我很大的忙,它现在可以工作了。很高兴我能帮上忙:)嗨Jorge谢谢你的回答,我已经尝试根据你的建议更改我的触发器,但是在执行时给了我一个“无法更改此触发器类型的新值”?抱歉,没注意到你的扳机是一个后发的。我会改变答案。非常感谢你Jorge,你帮了我很大的忙,它现在起作用了。很高兴我能帮上忙:)