2017-02-16 199 views
3

我对SQL/PostgreSQL相对比较陌生,我们刚刚开始使用触发器和函数/过程。对SQL函数中的“NEW”关键字感到困惑

这是两个相关的表

CREATE TABLE Planes (
    regnr TEXT PRIMARY KEY, 
    capacity INT NOT NULL 
); 

CREATE TABLE AvailableFlights (
    date TEXT PRIMARY KEY, 
    price INT NOT NULL, 
    nbrOfFreeSeats INT NOT NULL, 
    flight TEXT NOT NULL REFERENCES Flights(code), 
    plane TEXT NOT NULL REFERENCES Planes(regnr) 
); 

在表格“机票”包含有关港航班等。不管怎么说一些更多的信息,所以我现在的功能就像这样:

CREATE OR REPLACE FUNCTION update_plane() RETURNS TRIGGER AS $$ 
DECLARE 
    size_difference INTEGER; 
BEGIN 
    size_difference := (SELECT capacity FROM Planes WHERE regnr = new.plane) - (SELECT capacity FROM Planes WHERE regnr = old.plane); 

    IF(NEW.numberOfFreeSeats + size_difference < 0) THEN 
     RAISE EXCEPTION 'Plane too small'; 
    ELSE NEW.numberOfFreeSeats := NEW.numberOfFreeSeats + size_difference; 
    END IF; 

    RETURN NEW; 
END 
$$ LANGUAGE 'plpgsql'; 

而且一个触发器:

CREATE TRIGGER UpdatePlane BEFORE UPDATE ON AvailableFlights 
FOR EACH ROW 
WHEN (NEW.plane <> OLD.plane) 
EXECUTE PROCEDURE update_plane(); 

所以我的问题是这样的:我怎么能简单地写NEW.nbrOfFreeSeats witho用FROM和WHERE条件选择SELECT?它是如何知道哪一行相应改变的?因为触发器只有在我写了“UPDATE table SET plane ='newVal'WHERE plane ='oldVal'之类的东西时才会触发,所以在我看来,我永远不会说明我想改变哪个nbrSeats。飞机我改变了?(澄清:它工作正常,我只是好奇,为什么)。

我希望我有任何意义,这是我在stackoverflow上的第一篇文章,所以我希望我没有做太多的错误张贴本(任何反馈意见会受到欢迎,虽然,有点贴这一个急速):)在此先感谢。

回答

3

由于documentation states

NEW

数据类型RECORD;在行级触发器中保存新数据库行的变量为 INSERT/UPDATE操作。

并且还

行级触发器烧制BEFORE [...]返回从NEW的原始值不同的行值改变将被插入或更新的行。

该页面中的示例“例39-3 PL/pgSQL触发器过程”也可能有帮助。

+0

哦,我想我明白了......但在前面的例子中,我们也做了一个函数,然后当我们想为顶部声明的东西赋值时,我们必须写ticket_price:=(SELECT price。 WHERE flight = NEW.flight)。为什么我们不能写ticket_price:= price? – Yuna

+1

@Yuna不确定。在这种情况下你尝试过NEW.price吗?也许你可以发布一些关于这种情况的代码或者创建一个新的问题? – nbouchet

+0

对不起,延期回复,但我解决了,再次感谢! – Yuna