合并语句,不影响数据没有变化的记录

时间:2015-05-06 19:29:02

标签: oracle plsql merge

我有一个存储过程,它从几个表中获取数据并创建一个只包含我想要的列的新表。我现在想通过仅尝试插入/更新具有至少一列新数据的行来提高性能。对于只接收已有数据的现有行,我想完全跳过该行的更新。

例如,如果一行包含数据:

ID |   date    | population | gdp
15 | 01-JUN-10 | 1,530,000  | $67,000,000,000

并且合并声明来自ID 15和日期01-JUN-10,人口1,530,000和gdp $ 67,000,000,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 )

但肯定有更干净/更有效的方法吗?

1 个答案:

答案 0 :(得分:1)

另外,你可以使用ora_hash来获取行的哈希值。所以你的where子句可能就像。

其中ora_hash(src.col1 || src.col2 || src.col3 || src.col4)= ora_hash(src.col1 || src.col2 || src.col3 || src.col4)