一种选择是创建一个由触发器填充上user_product
一个user_product_history
表,然后定义转换旧“删除”排在历史表为update
,如果该行被随后插入的触发器。
CREATE TABLE user_product_history (
user_id number,
product_id number,
cost number,
operation_type varchar2(1),
operation_date date
);
CREATE TRIGGER trg_user_product_history
AFTER INSERT OR UPDATE OR DELETE ON user_product
FOR EACH ROW
DECLARE
l_cnt integer;
BEGIN
IF(deleting)
THEN
insert into user_product_history(user_id, product_id, cost, operation_type, operation_date)
values(:old.user_id, :old.product_id, :old.cost, 'D', sysdate);
ELSIF(updating)
THEN
insert into user_product_history(user_id, product_id, cost, operation_type, operation_date)
values(:new.user_id, :new.product_id, :new.cost, 'U', sysdate);
ELSIF(inserting)
THEN
select count(*)
into l_cnt
from user_product_history
where operation_type = 'D'
and user_id = :new.user_id
and product_id = :new.product_id;
if(l_cnt > 0)
then
update user_product_history
set operation_type = 'U',
operation_date = sysdate,
cost = :new.cost
where operation_type = 'D'
and user_id = :new.user_id
and product_id = :new.product_id;
else
insert into user_product_history(user_id, product_id, cost, operation_type, operation_date)
values(:new.user_id, :new.product_id, :new.cost, 'I', sysdate);
end if;
END IF;
END;
从效率的角度来看,然而,这样的删除和插入,而不是更新将意味着,你将远远更多的负载您的数据库比是必要的。你会做比实际需要更多的I/O。最终你会得到更复杂的代码来处理更改。你几乎肯定会更好地弄清楚已经发生了什么变化,然后只是更新这些行。
为什么不只是做一个更新而不是删除和插入? – 2012-04-10 03:57:51
@丹A.它基本上是从用户到产品的一对多关系。用户可以有100多种产品。如果用户现在有10个产品。他以后可能会有40种产品。如果我向用户添加新产品,我将不得不检查该用户产品映射是否存在于表中。如果是,则更新,如果没有,则插入。所以对我来说,很容易删除一切,然后再插入所有产品。这样我不必检查现有的和新的记录,并相应地运行插入或更新查询。 – ashishjmeshram 2012-04-10 04:05:32
当您尝试追踪历史记录时,您无法检查是否存在要更新的产品会带来任何便利。在我看来,最好通过实际进行“技术更新”来执行“逻辑更新”。如果您决定在产品记录中添加“create_date”和“last_updated”列,该怎么办?如果您更新现有记录,这样做很简单。 – 2012-04-10 14:03:37