Создать триггер, чтобы сохранить последнюю запись - PullRequest
2 голосов
/ 02 марта 2020

У меня есть таблица Product , которая продолжает добавлять строки с product_id и ценой. У него миллионы строк.

У него есть 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;

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Вам нужно использовать ключевое слово :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 голосов
/ 02 марта 2020

Получение последней цены из вашей первой таблицы должно быть быстрым, если у вас правильный индекс. Построение правильного индекса для вашей таблицы 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 = ???

и получите такую ​​же высокую производительность.

Это проще, менее подвержено ошибкам и так же быстро, как создание отдельной таблицы и ее обслуживание. Кстати, жаргон СУБД для таблицы, которую вы предлагаете создать, - материализованное представление.

...