创建触发器以保留最新记录

问题描述 投票:2回答:2

我有一个Product表,该表不断添加具有product_id和price的行。它具有数百万行。

它具有product_id作为主键,如下所示。

CREATE TABLE ProductPrice(
product_id VARCHAR2(10),
prod_date DATE ,
price NUMBER(8,0) ,
PRIMARY KEY (product_id)
)

现在,它具有数百万行,并且为了获得最新价格,它花费了大量时间。

因此,为了管理最新价格,我创建了另一个表,该表将仅保留具有相同格式的最新价格。

CREATE TABLE ProductPriceLatest(
product_id VARCHAR2(10),
prod_date DATE ,
price NUMBER(8,0) ,
PRIMARY KEY (product_id)
)

并且在原始表的每个插入上,我都会编写一个触发器来更新此表中的行。

但是我如何在触发器主体中获取新插入的值?

我尝试过这样的事情:

CREATE OR REPLACE TRIGGER TRIG_HISTory
AFTER INSERT
  on ProductPriceLatest
  FOR EACH ROW 

DECLARE

BEGIN

UPDATE latest_price
SET price = NEW.price , 
WHERE product_id = NEW.product_id ;        

END;

提前感谢。

database oracle query-performance database-trigger
2个回答
0
投票

您需要使用:new关键字来区分:old值。另外,最好使用AFTER触发器:

CREATE OR REPLACE TRIGGER TRIG_HISTORY 
AFTER INSERT ON source_table_name
    FOR EACH ROW
DECLARE

BEGIN
MERGE INTO dest_table_name d
    USING (select :new.price p, :new.product_id p_id from dual) s
    ON (d.product_id = s.p_id)
  WHEN MATCHED THEN
    UPDATE SET d.price = s.p
  WHEN NOT MATCHED THEN
    INSERT (price, product_id)
    VALUES (s.p, s.p_id);
END;

0
投票

如果索引正确,从第一张表中获取最新价格应该很快。与尝试维护单独的表相比,在ProductPrice表上构建正确的索引是更好的解决方案

您的查询以获取最新价格将如下所示。

SELECT p.product_id, p.prod_date, p.price
  FROM ProductPrice p
  JOIN (
           SELECT product_id, MAX(prod_date) latest_prod_date
             FROM ProductPrice
            GROUP BY product_id 
       ) m  ON p.product_id = m.product_id 
           AND p.prod_date = m.latest_prod_date
 WHERE p.product_id = ????

之所以有效,是因为子查询查找每个产品的最新产品日期。然后,它将使用该信息在表中找到向右显示的行。

如果在(product_id, prod_date, price)上创建复合索引,该查询将运行得几乎快得惊人。这是因为查询计划者可以在O(log n)或更短的时间内找到正确的索引项。

您可以将其变成这样的视图:

CREATE OR REPLACE VIEW ProductPriceLatest AS
SELECT p.product_id, p.prod_date, p.price
  FROM ProductPrice p
  JOIN (
           SELECT product_id, MAX(prod_date) latest_prod_date
             FROM ProductPrice
            GROUP BY product_id 
       ) m  ON p.product_id = m.product_id 
           AND p.prod_date = m.latest_prod_date;

然后您可以使用如下视图:

SELECT * FROM ProductPriceLatest WHERE product_id = ???

并获得相同的高性能。

这更容易,不易出错,并且与创建单独的表并对其进行维护一样快。顺便说一下,您要创建的表的DBMS行话是物化视图。

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