【问题标题】:Whats wrong in this merge operation?这个合并操作有什么问题?
【发布时间】:2019-12-18 15:36:04
【问题描述】:

我正在 Oracle 11g 中执行 MERGE 操作,但它们返回的行数比预期的要多。

create table sales(product varchar2(20),month date, amount number(10))
insert into sales values('LG','01-Jan-17',20000);
insert into sales values('sony','01-Jan-18',22000);
insert into sales values('panasonic', '22-dec-17',18000);

create table sales_history(product varchar2(20),month date, amount number(10)) 
insert into sales_history values('sony', '22-dec-17',24000);
insert into sales_history values('panasonic', '22-dec-17',18000);

select * from sales;
select * from sales_history

merge into sales_history sh using(select product,month,amount from sales)s 
on (s.product=sh.product) 
when matched then update set sh.month=s.month,sh.amount=s.amount 
when not matched then insert(sh.product,sh.month,sh.amount)
values(s.product,s.month,s.amount);

我尝试在 Pl/SQL 中执行相同的查询,这将给我相同的结果,但它返回的行更多是重复的行。为什么会这样?

set serveroutput on
declare
s_product varchar2(20);
s_month date; 
s_amount number(10);
p_product s_product%type;
m_month s_month%type;
a_amount s_amount%type;

cursor sc1 is 
select product,month,amount from sales;
cursor shc2 is 
select product,month,amount from sales_history;

begin
open sc1;
open shc2;
loop <<l1>>
fetch sc1 into s_product,s_month,s_amount;
fetch shc2 into p_product,m_month,a_amount;
if s_product = p_product then
  if s_month <> m_month then
  update sales_history set month = s_month where product = s_product;
  end if;
  if s_amount <> a_amount then
  update sales_history set amount = s_amount where product = s_product;
  end if;
else
  INSERT INTO  sales_history(product, month, amount)
  SELECT product, month, amount FROM sales;
  dbms_output.put_line('DATA IS UPDATED');
end if;
exit when sc1%notfound;
exit when shc2%notfound;
end loop l1;
close sc1;
close shc2;
end;

select * from sales_history

【问题讨论】:

  • 合并查询返回的行数与您写入的行数一样多。它将始终返回销售数量,因为您正在为每一行执行更新或插入操作。如果您有想要的结果,请用它更新问题。

标签: sql plsql oracle11g sql-merge


【解决方案1】:

我已经尝试在 oracle 12c 中执行上述案例并且它正在工作。请参阅下面提到的输出

 [SQL]create table sales(product varchar2(20),month date, amount number(10))
    Affected rows: 0
    Time: 0.012s

[SQL]insert into sales values('LG','01-Jan-17',20000)
Affected rows: 1
Time: 0.003s

[SQL]insert into sales values('sony','01-Jan-18',22000)
Affected rows: 1
Time: 0.004s

[SQL]insert into sales values('panasonic', '22-dec-17',18000)
Affected rows: 1
Time: 0.003s

[SQL]create table sales_history(product varchar2(20),month date, amount number(10))
Affected rows: 0
Time: 0.004s

[SQL]insert into sales_history values('sony', '22-dec-17',24000)
Affected rows: 1
Time: 0.002s

[SQL]insert into sales_history values('panasonic', '22-dec-17',18000)
Affected rows: 1
Time: 0.003s

[SQL]merge into sales_history sh using(select product,month,amount from sales)s 
on (s.product=sh.product) 
when matched then update set sh.month=s.month,sh.amount=s.amount 
when not matched then insert(sh.product,sh.month,sh.amount)
values(s.product,s.month,s.amount)
Affected rows: 3
Time: 0.015s

【讨论】:

  • 我建议使用 Merge 查询,因为与 PL/SQL 过程相比,它花费的时间更少。
  • 请提供代码为 sn-p 而不是屏幕截图。
  • 我在问题中使用了与上述相同的代码,为了显示成功执行,我添加了屏幕截图。现在,我已经用代码替换了屏幕截图。谢谢
【解决方案2】:

当你写作时 如果 s_product = p_product 那么 别的

当第一个产品名称是表sales中的sony时,它确实与sales_history中的sony匹配并给出期望输出,但它也与sales_hist中的其他条目不匹配并执行插入的代码的else部分,这给出结果是多行。 请参阅下面的输出,我尝试使用多个 dbms 输出。当索尼松下等时,其他部分正在执行。

set serveroutput on
declare
s_product varchar2(20);
s_month date; 
s_amount number(10);
p_product s_product%type;
m_month s_month%type;
a_amount s_amount%type;

cursor sc1 is 
select product,month,amount from sales;
cursor shc2 is 
select product,month,amount from sales_history;

begin
open sc1;
open shc2;
loop <<ll>>
fetch sc1 into s_product,s_month,s_amount;
fetch shc2 into p_product,m_month,a_amount;
dbms_output.put_line('outside if');
dbms_output.put_line(s_product);
dbms_output.put_line(p_product);
if s_product = p_product then
  dbms_output.put_line(p_product);
  if s_month <> m_month then
  dbms_output.put_line(m_month);
  update sales_history set month = s_month where product = s_product;
  end if;
  if s_amount <> a_amount then
  update sales_history set amount = s_amount where product = s_product;
  end if;
else
  INSERT INTO  sales_history(product, month, amount)
  SELECT product, month, amount FROM sales;
  dbms_output.put_line('DATA IS UPDATED');
end if;
exit when sc1%notfound;
exit when shc2%notfound;
end loop l1;
close sc1;
close shc2;
end;

 Output
outside if
LG
sony
DATA IS UPDATED
outside if
sony
panasonic
DATA IS UPDATED
outside if
panasonic
panasonic
panasonic

【讨论】:

  • 好的..我明白了..非常感谢先生
  • 如果有帮助,请标记答案正确或有帮助。
猜你喜欢
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 2017-04-19
  • 2011-05-14
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多