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

Database 创建触发器以保留最新记录,database,oracle,query-performance,database-trigger,Database,Oracle,Query Performance,Database Trigger,我有一个Product表,它不断添加带有Product\u id和price的行。它有数百万行 它有一个产品id作为主键,如下所示 CREATE TABLE ProductPrice( product_id VARCHAR2(10), prod_date DATE , price NUMBER(8,0) , PRIMARY KEY (product_id) ) 现在这有数百万行,要想得到最新的价格,需要很多时间 因此,为了管理最新价格,我创建了另一个表,该表只保留相同格式的最新价格 CREAT

我有一个Product表,它不断添加带有Product\u id和price的行。它有数百万行

它有一个产品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)
)
在原始表上的每个insert上,我将编写一个触发器,它将更新该表中的行

但是如何才能在触发器体中获得新插入的值呢

我试过这样的方法:

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

提前感谢。

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

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;

如果索引正确,从第一个表中检索最新价格应该很快。在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 = ????
这是因为子查询查找每个产品的最新产品日期。然后,它使用该信息在表中找到要显示的正确行

如果您在
(产品id、生产日期、价格)
上创建一个复合索引,那么这个查询将运行得几乎快得不可思议。这是因为查询计划器可以在O(logn)时间或更长时间内找到正确的索引项

您可以将其设置为如下视图:

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;
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 = ???
然后可以使用如下视图:

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;
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术语是物化视图。

您需要在trigger.MySQL DBMS中使用
:new
关键字吗?还是Oracle数据库管理系统?请删除此问题上的错误标签,保留正确的标签。只需通过
prod\u date
@Jones Done创建索引即可。我展示了一些我做过的事情你做了一些奇怪的动作<代码>产品id
为主键。同时-在插入之前创建触发器
(这意味着您插入了以前从未存在过的新
产品id
),但您尝试使用此不存在的值更新记录…如果有新产品id怎么办?这张桌子不会有那一排。如何检查是否没有行,然后不进行更新,而是进行插入。在上述情况下,触发器失败,原始表上的插入也失败。所以我需要处理这个场景