触发器功能更新所有行而不是一行(PostgreSQL)

时间:2016-06-07 16:59:42

标签: sql postgresql triggers sql-update

使用PostgreSQL。 我有的是: 3桌

1. Customer2c包含以下列: CustomerID PersonID, Number_Of_Items`。

2. SalesOrderHeader2c包含列: SalesOrderID CustomerID

  1. SalesOrderDetail2c包含以下列: SalesOrderDetailID SalesOrderIDOrderQty
  2. 我想创建一个触发器功能,只要有人使用

    就会触发

    INSERT INTO 'SalesOrderDetail2c' table

    这将获得插入的OrderQty并使用它更新对应的Number_Of_Items字段。

    我的触发器工作正常,但问题每当我向SalesOrderDetail2c插入一个新值时,该函数会获得OrderQty值,而会更新{的所有行{1}}使用它,而不是只更新通讯者。

    任何帮助表示赞赏。到目前为止我所拥有的是(这可能是完全错误的,请不要判断!):

    Number_Of_Items

3 个答案:

答案 0 :(得分:0)

我不得不使用.new作为上面提到的@Nicarus!再顺一句,再次感谢。

这是新代码,现在只更改对应的值。

CREATE OR REPLACE FUNCTION FunctionTrigger2c() RETURNS TRIGGER AS
$BODY$
BEGIN
    UPDATE Customer2c
    SET Number_Of_Items = 
    (SELECT new.OrderQty
    FROM SalesOrderDetail2c
    order by salesorderdetailid desc limit 1
    )
    FROM SalesOrderheader2c
    WHERE (SalesOrderheader2c.salesorderID = new.salesorderID) and (salesorderheader2c.customerid = customer2c.customerid)
    ;
    RETURN NEW;
    END;
$BODY$ 
language plpgsql;

CREATE TRIGGER Trigger2c
     AFTER INSERT ON SalesOrderDetail2c
     FOR EACH ROW
     EXECUTE PROCEDURE FunctionTrigger2c();

答案 1 :(得分:0)

这是我的,非常通用的触发器,用于在依赖表中执行count / sum值。您应该处理所有订单更改,即EXEC spGetNewCases '2016-03-01', '2016-05-01'以及INSERTDELETE。您还应该阅读@Nicarus关于在触发器中使用UPDATE(和NEW)的评论。

我更改了它以符合您的架构,但没有测试它......

OLD
如果您更改CREATE OR REPLACE FUNCTION FunctionTrigger2c() RETURNS trigger AS $BODY$ DECLARE BEGIN CASE TG_OP WHEN 'INSERT' THEN UPDATE Customer2c SET Number_Of_Items = Number_Of_Items + NEW.OrderQty FROM SalesOrderHeader2c WHERE Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND SalesOrderHeader2c.SalesOrderID = NEW.SalesOrderID AND SalesOrderDetailID = NEW.SalesOrderDetailID; WHEN 'UPDATE' THEN UPDATE Customer2c SET Number_Of_Items = Number_Of_Items - OLD.OrderQty FROM SalesOrderHeader2c WHERE Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND SalesOrderHeader2c.SalesOrderID = OLD.SalesOrderID AND SalesOrderDetailID = OLD.SalesOrderDetailID; UPDATE Customer2c SET Number_Of_Items = Number_Of_Items + NEW.OrderQty FROM SalesOrderHeader2c WHERE Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND SalesOrderHeader2c.SalesOrderID = NEW.SalesOrderID AND SalesOrderDetailID = NEW.SalesOrderDetailID; WHEN 'DELETE' THEN UPDATE Customer2c SET Number_Of_Items = Number_Of_Items - OLD.OrderQty FROM SalesOrderHeader2c WHERE Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND SalesOrderHeader2c.SalesOrderID = OLD.SalesOrderID AND SalesOrderDetailID = OLD.SalesOrderDetailID; END CASE; RETURN NULL; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; :)

UPDATE也能正常运作

注意,此触发器返回SalesOrderID并且应设置为NULL

AFTER INSERT OR UPDATE OR DELETE

答案 2 :(得分:0)

我指出了您原来的触发器为何无效的原因。它更新每一行的原因是由于您的UPDATE语句。插入某些内容后,它触发了更新。 当更新运行时,它得到了这些东西:

  1. 我要更新哪个表
  2. 我要在给定表的哪一列上设置什么值
  3. 我将在(FROM + WHERE)上执行哪些行

问题出在最后一部分,基本上,在UPDATE语句中调用FROM就像调用SELECT语句一样,它试图处理具有给定WHERE值的FROM子句表中的每一行。

  

有关UPDATE语句from_list参数的PostgreSQL文档指出“ A   表表达式列表,允许其他表中的列   出现在WHERE条件和更新表达式中。这是   与可以在FROM子句中指定的表的列表相似   SELECT语句。”   (https://www.postgresql.org/docs/9.1/sql-update.html

基本上,您的更新语句遍历了 SalesOrderHeader2c 中的每一行,该行方便地与 Customer2c 的每一行匹配(具有 SalesOrderHeader2c.CustomerID = Customer2c.CustomerID ),使用UPDATE SET语句中第一个找到的 Number_Of_Items 值更新 Customer2c 中每一行的值。这就是为什么 Customer2c 中的每一行都具有相同值的原因。

新触发器起作用的原因是因为update语句是使用正确选择的行完成的。