2011-06-20 81 views
0

我有一個包含2個varchar2列的表。我已經在現有的表格中添加了新的數字列來創建此列主鍵。該表現在包括3列。我嘗試使用匿名塊如下:
declare
cnt number;
begin
select nvl(count(*),0) into cnt from sometable;
for i in 1..cnt
loop
update sometable set id=i where i=rownum;
end loop;
end;

使用此匿名塊意外更新此表。
我的解決辦法是使用下面的語句:
create table sometablecopy as select row_number() over(order by sometable.col1) as id, sometable.* from sometable;
不過我珍玩爲什麼不匿名塊產生預期的與ROWNUM僞的幫助主鍵值?它必須是rownum相關的問題。將新列添加到Oracle表後生成主鍵值

+0

意外的結果是什麼? – StevieG

+0

返回結果時分配Rownum。因此,你永遠不可以做一個SELECT ... WHERE rownum <1',因爲如果至少有一行,那麼第一個必須有rownum等於1. – Benoit

+0

StevieG:所有行都有相同的主鍵值第一行。第一行有數字1,其他行有cnt變量。 – reforrer

回答

1

ROWNUM是一個僞列。它在從select返回時分配給行。所以你不能說「select * from my_table where rownum = 42」,因爲rownum = 42的行尚未定義,它將根據你的選擇和謂詞(和「select * from my_table where rownum = 1 「將返回一行,而不是」第一「行,無論如何)。你可以做一些類似的事情(未經測試):

declare 
    cursor sel_cur is 
    select rowid as row_id 
    from my_table 
    order by orderby_col; 

    v_ctr pls_integer := 0; 
begin 
    for rec in sel_cur 
    loop 
    v_ctr := v_ctr + 1; 
    update my_table set pk_col = v_ctr where rowid = rec.row_id; 
    end loop; 
    commit; 
exception 
    when others then 
    rollback; 
    raise; 
end; 

這假設你有足夠的回滾來更新整個表。

希望有所幫助。

+0

工程很好,我會用它!謝謝! – reforrer

+0

彼得郎建議非常簡單的解決方案,而不是這個。當UPDATE語句需要更復雜時,使用遊標和rowid是更有效的方法。 – reforrer

1

您不能使用類似ROWNUM(請參閱ROWNUM in SQL)。

什麼,你可以這樣做是:

UPDATE sometable SET id = ROWNUM; 
+0

其實它太簡單了,但爲了這個任務的目的它是可以接受的:) – reforrer

+0

@reforrer:不知道你的意思。怎麼能這麼簡單? –