1
我有一個存儲過程,它從多個表中獲取數據,並創建一個只包含我想要的列的新表。我現在想通過嘗試插入/更新至少包含一列新數據的行來提高性能。對於只接收已有數據的現有行,我想跳過該行的更新。合併聲明而不影響數據沒有變化的記錄
例如,如果一個行包含的數據:
ID | date | population | gdp
15 | 01-JUN-10 | 1,530,000 | $67,000,000,000
和MERGE語句來爲ID 15日01-JUN-10與人口1,530,000和國內生產總值$六七○○○○○○○○○然後我不想更新行。
下面是我的一些代碼片段:
create or replace PROCEDURE COUNTRY (
fromDate IN DATE,
toDate IN DATE,
filterDown IN INT,
chunkSize IN INT
) AS
--cursor
cursor cc is
select c.id, cd.population_total_count, cd.evaluation_date, cf.gdp_total_dollars
from countries c
join country_demographics cd on c.id = cd.country_id
join country_financials cf on cd.country_id = cf.country_id and cf.evaluation_date = cd.evaluation_date
where cd.evaluation_date > fromDate and cd.evaluation_date < toDate
order by c.id,cd.evaluation_date;
--table
type cc_table is table of cc%rowtype;
c_table cc_table;
BEGIN
open cc;
loop -- cc loop
fetch cc bulk collect into c_table limit chunkSize; --limit by chunkSize parameter
forall j in 1..c_table.count
merge
into F_AMB_COUNTRY_INFO_16830 tgt
using (
select c_table(j).id cid,
c_table(j).evaluation_date eval_date,
c_table(j).population_total_count pop,
c_table(j).gdp_total_dollars gdp
from dual
) src
on (cid = tgt.country_id AND eval_date = tgt.evaluation_date)
when matched then
update
set tgt.population_total_count = pop,
tgt.gdp_total_dollars = gdp
when not matched then
insert (
tgt.country_id,
tgt.evaluation_date,
tgt.population_total_count,
tgt.gdp_total_dollars)
values (
cid,
eval_date,
pop,
gdp);
exit when c_table.count = 0; --quit condition for cc loop
end loop; --end cc loop
close cc;
EXCEPTION
when ACCESS_INTO_NULL then -- catch error when table does not exist
dbms_output.put_line('Error ' || SQLCODE || ': ' || SQLERRM);
END ;
我在想,在on
聲明,我可以說,沿着線的東西:
on (cid = tgt.country_id AND eval_date = tgt.evaluation_date
AND pop != tgt.population_total_count AND gdp != tgt.gdp_total_dollars)
,但肯定有一個更清潔/更有效的方式來做到這一點?
如果你的目標是提高性能,我的第一個偏見就是完全消除循環,只是對所有數據做一個「MERGE」。這可能比在循環中做一個MERGE更快。 SQL應該總是比PL/SQL更快。除此之外,如果你只想更新有變化的行,假設你的列不可爲空,你修改'ON'子句的建議看起來是正確的。如果他們允許NULL值,你的謂詞需要更復雜一點。 –
只有ID和DATE不可空。其餘的都是。 – Ted
然後,你可能需要更多的涉及謂詞(即,如果要從NULL到非NULL值並且如果要從非NULL值變爲NULL,則要更新數據)。我會把它寫成((src.col1!= dest.col1或src.col1爲null,dest.col1不爲null或src.col1不爲null,dest.col1爲null)''但還有其他方法可以構造使用'NVL'來用一個不可能的但非NULL值'nvl(src.col1,'Impossible')!= nvl(dest.col1,'Impossible')替換NULL值的謂詞。 –