Oracle循环连接语句

时间:2015-04-30 13:20:53

标签: oracle plsql oracle11g

我需要在PL-SQL中执行一个语句,该语句选择ID,对这些ID的子集执行连接...在下面的示例中,我有大约700000个客户,以及 far 这个例子中简单的while循环显示比这里更复杂的查询...我播种的性能很差,如果将我当前的PL-SQL切换成'块'会产生性能增加,我很好奇吗? / p>

目前:

declare
  TYPE customerIdTabType IS TABLE OF customer.CustomerId%TYPE INDEX BY BINARY_INTEGER;
  vars customerIdTabType;

  -- maybe this should be in a table?
  cursor c is
  select
      c.CustomerId
  from customer c
  join productcustomers pc on pc.customerid = c.customerid
  join product p on p.productid = pc.productid
  where
      c.CustomerId > 1000;

begin  
  open c;
  loop
  fetch c bulk collect into vars limit 1000;

  -- here is where instead of looping through each item in vars
  -- i actually want to 'join' to the 1000 that i have.  
  forall i in 1..vars.count
  insert into xxx (CustomerId) 
  values (vars(i));
  commit;

  exit when vars.count = 0;
  end loop;
  close c;

end;
  1. 选择一个CustomerIds列表到“临时”存储容器中 - 不确定选项是什么?
  2. 通过将这些CustomerId加入另一个查询来批量处理这些CustomerIds
  3. 将所有结果插入物理表
  4. 所以,在T-SQL中可能是..

    -- create a temp table
    create table #MyTempTable (
        id int identity(1,1)
        ,customerid varchar(10)
    )
    
    -- populate that table
    insert into #MyTempTable
    select Customerid 
    from schema.Customers
    
    -- create some vars for looping
    declare i int, c int;
    select i = 0;
    select c = count(*) from #MyTempTable;
    
    -- loop through the original set in 'chunks' of 1000​
    while i < c
    begin
        insert into SomeOtherTable
            (CustomerId, CustomerAttribute)
        select
            o.CustomerId
            ,o.CustomerAttribute
        from OtherTable o
        join #MyTempTable t
        on o.CustomerId = t.CustomerId
        where
            t.Id between i and i+1000    -- from 0 to 1000
    
        set @i = i+1000    ​-- next loop will be from 1000 to 2000
    end
    

    由于

2 个答案:

答案 0 :(得分:0)

游标和临时表都是糟糕的解决方案。但游标是两者中最差的。 CTE(通用表格表达式)将是更好的解决方案,但即使这样也不是必需的。为什么不直接使用get-go中的... select语句

Insert into xxx (CustomerId)
select
    c.CustomerId
from customer c
     join productcustomers pc on pc.customerid = c.customerid
     join product p on p.productid = pc.productid
where
    c.CustomerId > 1000;

如果确实需要拆分,请不要使用游标或临时表。我希望CTE是一个更好的解决方案。

答案 1 :(得分:0)

然后,这个怎么样

select startid = min(id) from customer;
select maxid = max(id) from customer;

i = startid
while i <= maxid

begin
   with myCTE as (select ... from customer where id >= i and id < i + 1000)
   insert into xxx (....)
   select ....
   from myCustomerChunk
        join productcustomers pc on ....
        join product p on ....

   i = i+1000
end

这避免了在一个语句中执行所有700000次插入,这可能会削弱您的查询......并且光标使事情变得更糟。 PS:这是伪代码和实际代码的大杂烩,所以你必须弄清楚真正的语法。