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

Create trigger to keep the latest record

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

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

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

现在这有数百万行,要获得最新价格需要很多时间。

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

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

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

但是我怎样才能在触发器主体中获取新插入的值?

我试过这样的事情:

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;

提前致谢。

您需要使用 :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;

如果索引正确,从第一个 table 检索最新价格应该很快。在您的 ProductPrice table 上构建正确的索引是 比维护单独的 table.

更好的解决方案

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

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 = ????

这是有效的,因为子查询查找每个产品的最新产品日期。然后它使用该信息在 table 中找到正确的行来向您展示。

如果您在 (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 = ???

并获得相同的高性能。

这更容易,更不容易出错,并且与创建一个单独的 table 并维护它一样快。顺便说一下,您建议创建的 table 的 DBMS 术语是 物化视图。