我有一个包含10行的参数表。称为parameter_table。 在我的PL / SQL过程中,我循环了200万条记录。每次都查询这个参数表。
我想将此参数表加载到内存中并减少I / O过程。
这样做的最佳方式是什么?
FOR cur_opt
IN (SELECT customer_ID,
NVL (customer_type, 'C') cus_type
FROM invoice_codes
WHERE ms.invoice_type='RT')
LOOP
....
...
Select data From parameter_table Where cus_type = cur_opt.cus_type AND cr_date < sysdate ; -- Where clause is much complex than this..
....
...
END LOOP;
答案 0 :(得分:3)
您可以将其加入主查询:
select customer_id, data
from parameter_table t, invoice_codes c
where t.cus_type = nvl(c.customer_type, 'C')
and t.cr_date < sysdate
但是,如果你在invoice_codes
中有200万条记录,那么加入参数表是你最不关心的问题 - 循环这将需要一些时间(可能是你的真正原因) / O问题)。
答案 1 :(得分:1)
我认为您可以更改查询,加入parameter_table,因此不需要在循环内点击select语句。 (就像@Chris Saxon解决方案一样)
但作为使用兑现数据的一种方式,
您可以填写字典,如数组,然后在必要时引用它
这样的事情可能有所帮助:
你必须在开始主进程之前调用Fill_parameters_cash
并调用get_parameter
来获取数据,调用get_parameter
的输入参数是字典键
TYPE ga_parameter_t IS TABLE OF parameter_table%ROWTYPE INDEX BY BINARY_INTEGER;
ga_parameter ga_parameter_t;
procedure Fill_parameters_cash is
begin
ga_parameter.DELETE;
SELECT * BULK COLLECT
INTO ga_parameter
FROM parameter_table;
end Fill_parameters_cash;
FUNCTION get_parameter(cus_type invoice_codes.cus_type%TYPE,
is_fdound OUT BOOLEAN)
RETURN parameter_table%ROWTYPE IS
result_value parameter_table%ROWTYPE;
pos NUMBER;
BEGIN
result_value := NULL;
is_fdound := FALSE;
IF cus_type IS NULL THEN
RETURN NULL;
END IF;
pos := ga_parameter.FIRST;
WHILE pos IS NOT NULL
LOOP
EXIT WHEN ga_parameter(pos).cus_type = cus_type;
pos := ga_parameter.NEXT(pos);
END LOOP;
IF pos IS NOT NULL THEN
is_fdound := TRUE;
result_value := ga_parameter(pos);
END IF;
RETURN result_value;
END get_parameter;
答案 2 :(得分:0)
我猜想循环播放一百万条记录已经导致了问题。不太确定这个参数表查找是如何使它真正恶化的。
无论如何,如果这是你可以采取的唯一方法,那么你可以在游标声明中进行内部或外部连接。
----
FOR cur_opt
IN (SELECT customer_ID,
NVL (customer_type, 'C') cus_type
FROM invoice_codes codes,
parameter_table par
WHERE ms.invoice_type='RT'
and codes.cus_type = par.cus_type -- (or an outer join) maybe?
) loop
..........