我注意到这两个系统中临时表的概念是不同的,我有一个思考…我在MySQL中有以下场景:
- 删除临时表a 创建临时表'a'
- 通过存储过程填充数据
- 在另一个存储过程中使用数据
如何在Oracle中实现相同的场景?我可以(最好在一个过程中)创建一个临时表,填充它,然后在另一个(非临时)表中插入数据吗?
我认为我可以使用一个(全局)临时表,它在提交时截断,并避免步骤1&2,但我也需要别人的意见。
在Oracle中,首先很少需要临时表。您通常需要其他数据库中的临时表,因为这些数据库没有实现多版本读取一致性,并且在您的过程运行时,可能会有人从表中读取数据被阻塞,或者如果您的过程没有将数据保存到单独的结构中,则可能会执行脏读取。由于以上两种原因,在Oracle中不需要全局临时表,因为读不会阻塞写,也不可能进行脏读。
如果你只是在执行PL/SQL计算时需要一个临时的地方来存储数据,那么在Oracle中PL/SQL集合比临时表更常用。这样,您就不会将数据从PL/SQL引擎推到SQL引擎,再推回PL/SQL引擎。
CREATE PROCEDURE do_some_processing
AS
TYPE emp_collection_typ IS TABLE OF emp%rowtype;
l_emps emp_collection_type;
CURSOR emp_cur
IS SELECT *
FROM emp;
BEGIN
OPEN emp_cur;
LOOP
FETCH emp_cur
BULK COLLECT INTO l_emps
LIMIT 100;
EXIT WHEN l_emps.count = 0;
FOR i IN 1 .. l_emps.count
LOOP
<<do some complicated processing>>
END LOOP;
END LOOP;
END;
您可以创建一个全局临时表(在过程外部),并在过程内部使用全局临时表,就像使用任何其他表一样。因此,如果您愿意,可以继续使用临时表。但是,在Oracle中,我真的需要临时表的次数屈指可数。
你是对的,临时表将为你工作。
如果你决定坚持使用常规表,你可能需要使用@Johan给出的建议,以及
ALTER TABLE <table name> NOLOGGING;
我看你使用的方案没有问题。
注意,它不一定是一个临时表,您也可以使用某种类型的内存表。
像往常一样创建一个表,然后执行
ALTER TABLE <table_name> CACHE;
这将优先考虑表在内存中的存储。
只要在短时间内填充和空表,就不需要执行第1步&2。
记住cache
修饰符只是一个提示。表仍然在缓存中老化,最终将被推出内存。
只做:
通过存储过程向cache表中填充数据
在另一个存储过程中使用数据,但不要等待太久。2 a。清除cache表中的数据
在你的MySQL版本中,我没有看到第5步删除表a。所以,如果你想要或不介意保留表中的数据,你也可以使用物化视图并按需刷新。对于物化视图,您不需要管理任何INSERT语句,只需包含SQL:
CREATE MATERIALIZED VIEW my_mv
NOCACHE -- NOCACHE/CACHE: Optional, cache places the table in the most recently used part of the LRU blocks
BUILD IMMEDIATE -- BUILD DEFERRED or BUILD IMMEDIATE
REFRESH ON DEMAND
WITH PRIMARY KEY -- Optional: creates PK column
AS
SELECT *
FROM ....;
然后在其他存储过程中调用:
BEGIN
dbms_mview.refresh ('my_mv', 'c'); -- 'c' = Complete
END;
也就是说,全局临时表也可以工作,但是您需要管理插入和异常。