2014-10-02 24 views
0

我有一些Oracle Update語句與組功能有關的問題 我想更新另一個表中所有記錄的列。 但它顯示SQL錯誤:ORA-01427:單行子查詢返回多個行 這是我的示例。帶有組功能的Oracle更新聲明

create table branch_cp 
(
area varchar2 (5) , 
branch_code varchar2 (5) primary key, 
branch_name varchar2 (20)); 
------ 
create table branch_cp_2 
(
area varchar2 (5) , 
branch_code varchar2 (5) primary key, 
branch_name varchar2 (20)); 
---------------------------------- 
insert into branch_cp values ('01', '01', 'A'); 
insert into branch_cp values ('01', '02', 'B'); 
insert into branch_cp values ('03', '03', 'C'); 
---------- 
insert into branch_cp_2 values ('01', '04', 'D'); 
insert into branch_cp_2 values ('01', '05', 'E'); 
insert into branch_cp_2 values ('03', '06', 'F'); 
---------------------- 
select * from branch_cp; 
------------------ 
update branch_cp 
set branch_cp.branch_code = (select branch_cp_2.branch_code 
from branch_cp_2 
where branch_cp.area =branch_cp_2.area) 
where exists (select 1 from branch_cp_2 where branch_cp_2.area = branch_cp.area) ; 

如何在更新語句中使用組函數。請幫助

+0

area是主鍵列brach_cp_2,因爲插入相同的值01兩次,您的插入應該失敗。 – radar 2014-10-02 15:44:24

+0

對不起,它是輸入錯誤。分支是主鍵 – 2014-10-02 16:04:22

+0

那麼,你有兩個'branch_cp_2'記錄,其中'area'是'01'。那麼,你如何決定這個區域的兩個'branch_cp'行的每個'branch_code'值?你說你想分組,但你需要說明你想要的 - 最小或最大代碼?兩個記錄都會得到相同的值,這會違反您的主鍵。 – 2014-10-02 16:13:29

回答

3

您在每個表中有兩個記錄,其中area01,並且您需要將它們設置爲不同的值以滿足主鍵 - 您無法將它們都設置爲第二個表中的最大值或最小值,所以你不想做任何分組。

似乎沒有任何其他的記錄之間有相同的area排序,所以我會認爲它是任意的,每個area從哪個記錄中獲取哪個branch_code與其他表無關。如果它不是任意的,則需要指定規則...

如果您需要在一組記錄中以任意順序進行匹配,則相關的更新會非常棘手。您需要某種方法來確定行順序,但將row_number()列添加到原始表以創建內聯視圖將導致ORA-01732錯誤。

但是,您可以使用目標表的rowid僞列;您只需在關聯中進行額外的連接即可獲得相同的值以及新的branch_code。喜歡的東西:

select bc.rid, 
    bc.area, 
    bc.branch_code, 
    bc.branch_name, 
    bc2.area, 
    bc2.branch_code, 
    bc2.branch_name 
from (
    select bc.*, 
    bc.rowid as rid, 
    row_number() over (partition by bc.area order by bc.branch_code) as rn 
    from branch_cp bc 
) bc 
join (
    select bc2.*, 
    row_number() over (partition by bc2.area order by bc2.branch_code) as rn 
    from branch_cp_2 bc2 
) bc2 
on bc2.area = bc.area 
and bc2.rn = bc.rn; 

它給你:

RID    AREA BRANCH_CODE BRANCH_NAME AREA BRANCH_CODE BRANCH_NAME 
------------------ ----- ----------- ----------- ----- ----------- ----------- 
AAAwy+AAEAAAA0DAAA 01 01   A   01 04   D   
AAAwy+AAEAAAA0DAAB 01 02   B   01 05   E   
AAAwy+AAEAAAA0DAAC 03 03   C   03 06   F   

現在你實際上並不需要所有這些列,你只需要rid(在branch_cp.rowid)和相關branch_cp_2.branch_code

但是你也只想在有匹配的時候更新 - 在其他表中沒有任何值的行上無效歸零 - 因此你必須在exists子查詢中重複那個連接。

所以,很簡單做一個merge

merge into branch_cp bc 
using (
    select bc.rid, 
     bc2.branch_code 
    from (
     select bc.*, 
     bc.rowid as rid, 
     row_number() over (partition by bc.area order by bc.branch_code) as rn 
     from branch_cp bc 
    ) bc 
    join (
     select bc2.*, 
     row_number() over (partition by bc2.area order by bc2.branch_code) as rn 
     from branch_cp_2 bc2 
    ) bc2 
    on bc2.area = bc.area 
    and bc2.rn = bc.rn 
) bc2 
on (bc.rowid = bc2.rid) 
when matched then update set bc.branch_code = bc2.branch_code; 

3 rows merged. 

你的表現擁有:

select * from branch_cp; 

AREA BRANCH_CODE BRANCH_NAME 
----- ----------- ----------- 
01 04   A   
01 05   B   
03 06   C   

SQL Fiddle

+0

哇..感謝了很多。這對我完全有幫助。我也嘗試在兩個表中添加一個新的匹配行。它的工作原理。再次感謝。 :) – 2014-10-02 18:22:56

+0

@K_islam:請接受這個答案,如果它適合你。 – toddlermenot 2014-10-02 19:31:13