创建触发器以保持最新记录
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 术语是 物化视图。
我有一个 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 术语是 物化视图。