使用序列的錯誤ORA-02287

來源:互聯網
上載者:User

使用序列的錯誤ORA-02287

今天一個開發的同事問我一個問題,說在執行一條sql語句的時候報了ORA錯誤,腦海中刪除了各種許可權的問題之後,他提供給我的錯誤還是在我預料之外。
ERROR at line 1:
 ORA-02287: sequence number not allowed here

這個問題看錯誤資訊是很明顯和sequence有關的。但是為什麼會報出這個錯誤呢,在幾封郵件交流之後,問題就明朗起來,語句是類似下面這樣的結構,insert into customer(xxxxx,xxxxx,xxx...............)
 select distinct xxxxx,seq_value.nextval,xxxx,xxxx,xxx... from new_table group by xxx,xxx,xxx,xxx;
真實的指令碼洋洋洒洒一大頁,各種子查詢,表關聯,函數處理,看起來還是需要些耐心的。簡縮之後就是上面的結構,
 這個Insert採用了子查詢來插入資料,根據和開發的溝通,是需要提供一個補丁,做修複資料所用,所以會有大量的資料過濾操作。
 插入資料的時候使用seq_value.nextval也還是很常見的,怎麼會報出錯誤了呢,按照這個語句的結構發現還是最開頭的distinct和group操作導致的,這種資料的統計分析操作讓本來就不確定的sequence值更加不確定,所以斟酌再三還是建議他們先建立一個暫存資料表,不涉及序列的操作,只對序列之外的資料通過distinct,group by過濾之後,在insert的時候對剛建立的暫存資料表和序列結合起來,一次插入。

虛擬碼類似下面的形式,
create table temp_tab as select distinct xxxxxx  from xxxx  group by xxxxxx;
 insert into customer(xxxxx,xxxx) select xxxx,seq_vvalue.nextval from temp_tab;

我們來簡答類比一下這個問題。
 首先為了不影響原有的sequence,我們可以建立一個類似的sequence,然後在指令碼中替換即可,這樣也不會對原有環境的sequence值造成影響。
CREATE SEQUENCE  "NEW_SEQ"  MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 1012852 CACHE 20 NOORDER  NOCYCLE
然後我們建立一個表
create table new_test( id1 number,id2 number,name varchar2(30));
然後嘗試distinct和group by 操作,發現都不可以。
n1@TEST11G> select new_seq.nextval,id1,id2,name from new_test group by id1,id2,name;
 select new_seq.nextval,id1,id2,name from new_test group by id1,id2,name
                *
 ERROR at line 1:
 ORA-02287: sequence number not allowed here

n1@TEST11G> select distinct new_seq.nextval,id1,id2,name from new_test;
 select distinct new_seq.nextval,id1,id2,name from new_test
                        *
 ERROR at line 1:
 ORA-02287: sequence number not allowed here
其實這個問題的原因還是很容易理解的,這種sequence值的動態不確定性,很容易出問題。其實不光使用distinct,group by 會有問題,很多相關的操作都是如此。
 比如union,union all
 select new_seq.nextval,id1,id2,name from new_test
 union all
 select new_seq.nextval,id1,id2,name from new_test

 minus操作。
select new_seq.nextval,id1,id2,name from new_test
 minus
 select new_seq.nextval,id1,id2,name from new_test

使用In子查詢
select new_seq.nextval id1,id2,name from new_test  where id1 in (select new_seq.nextval from new_test )

 order by操作
select new_seq.nextval,id1,id2,name from new_test order by id2;

換個角度來看,對於這類問題,也可以使用暫存資料表來處理,也可以使用pl/sql來處理,都能達到比較目的,另外一個角度來說,對於sequence的使用,大家一般都認為是取之不盡,用之不竭,感覺大量使用時應該的,在很多時候還是需要好好斟酌一下,有些補丁或者臨時的處理是否一定需要使用到序列,序列資源也是很寶貴的資源,如果在測試指令碼中做了大量的自增處理也是很大的浪費。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.