在oracle中,序列(sequence)是可以產生一組等間隔的數值的一種生成器。常用來生成表的主鍵或者其他有規律或自增/減的字段值。當前專案是用來生成表的主鍵,由於某些原因,當前的某些序列值小於了對應表的id值,導致繼續使用序列生成id,會造成id重複。所以需要修改當前的序列值,使其大於對應表id。
修改序列值的思路,可分解為如下:
oracle中,當前序列值無法直接修改
通過查詢當前序列的方式,可以使當前序列值遞增一次
select 序列名.nextval from dual;
修改當前序列值,可以通過修改 序列遞增值 ,然後再 查詢一次當前序列值使其遞增一次,到達修改的目的
alter sequence 序列名 increment by 5;
//修改當前序列遞增值
select 序列名.nextval from dual;
//查詢序列,使其自增
當前遞增值 改為 5,然後再查詢一次,即可以讓當前序列值增加5。但注意最後要將遞增值改回來
也可以通過 迴圈查詢 當前序列值,每迴圈一次,序列就遞增一次。
note:
dual是一張只有一行一列的oracle虛擬表,也叫偽表,一般用於補充語句完整性。
eg:查詢當前時間,可以通過 to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') 得到。
但執行sql的時候,必須滿足sql語法定義,所以, select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual; 就可以補充完整語法。
針對當前情況,處理邏輯是:
遍歷所有表,查詢每張表的最大id、序列、序列遞增值;
如果當前表 id 小於序列值,則進行修改序列值,否則跳過;
修改序列值:首先判斷 id 與序列的差值,然後將 序列差值+序列遞增值 作為新的 序列遞增值;
執行一次查詢序列,使序列自增一次。此時序列遞增值已經修改,所以自增後,序列已經大於了 id 值,可以正常自增生成id了;
改回自增值為原來的值。
完整的案例如下:
declare
v_tablename varchar2(64
);-- 當前表名
v_maxid number;
-- 當前表 最大id
v_sql varchar2
(1024);
-- 查最大id sql
v_sql_updateseq varchar2
(1024);
-- 更新遞增值 sql
v_sql_currentseq varchar2
(1024);
-- 查當前表 序列值、遞增值
v_sql_addseq varchar2
(1024);
-- 更新當前序列值
v_count number;
-- 判斷表是否有id欄位的臨時標識
v_current_seq number;
-- 當前表的序列值
v_current_increment number;
-- 當前表的遞增值
v_temp_add number;
-- 當前表的修改後遞增值
v_hasseq number;
-- 是否存在該序列表的標識 >
0 為有
v_tempdata number;
-- 臨時存放,只是為了select動態sql能夠順利執行,並不拿來使用
cursor tablename_cur is select table_name from user_tables;
rowtypes user_tables%rowtype;
begin
for rowtypes in tablename_cur loop
v_tablename :
= rowtypes.table_name;
select count(1
) into v_count from cols where table_name = v_tablename and column_name =
'id'
;if v_count >
0 then
-- 查當前表最大id
v_sql :
='select max(id) from '
||v_tablename;
execute immediate v_sql into v_maxid;
exit when tablename_cur%notfound;
if v_maxid is not null then
-- 遞增當前序列
v_sql_addseq :
='select '
||v_tablename||
'_seq.nextval from dual'
;-- 查當前表序列值、遞增值
select count(1
) into v_hasseq from user_sequences where sequence_name = v_tablename||
'_seq'
;if v_hasseq >
0 then
select last_number into v_current_seq from user_sequences where sequence_name = v_tablename||
'_seq'
; select increment_by into v_current_increment from user_sequences where sequence_name = v_tablename||
'_seq'
;-- 判斷當前表序列值是否小於id,是則修改
if v_maxid > v_current_seq then
-- 計算新遞增值
v_temp_add :
= v_maxid - v_current_seq + v_current_increment;
dbms_output.
put_line
(v_tablename||
'--'
||v_maxid||
'--'
||v_current_seq||
'--'
||v_current_increment||
'--'
||v_temp_add||
' '
||v_sql_addseq)
;-- 修改遞增值
v_sql_updateseq :
='alter sequence '
||v_tablename||
'_seq increment by '
||v_temp_add;
execute immediate v_sql_updateseq;
-- 再查詢一次當前序列,修改序列值
execute immediate v_sql_addseq into v_tempdata;
-- 將遞增值恢復
v_sql_updateseq :
='alter sequence '
||v_tablename||
'_seq increment by '
||v_current_increment;
execute immediate v_sql_updateseq;
select last_number into v_current_seq from user_sequences where sequence_name = v_tablename||
'_seq'
; select increment_by into v_current_increment from user_sequences where sequence_name = v_tablename||
'_seq'
;dbms_output.
put_line
(v_tablename||
'--'
||v_maxid||
'--'
||v_current_seq||
'--'
||v_current_increment||
'--'
||v_temp_add)
; end if
; end if
; end if;
end if
; end loop;
end;
declare
可直接作為sql執行
create or replace procedure
是編寫儲存過程的方法,編寫完儲存後,還需要進行呼叫
linux如何修改當前時間
用於時間不准的 如我安裝contos的時候時區選的是上海,但還是差幾個小時 只有root使用者才可以操作哦 cst 中國標準時間 china standard time 這個解釋可能是針對redhat linux。gmt 格林尼治標準時間 舊譯格林威治平均時間或格林威治標準時間 英語 greenwi...
oracle修改序列當前值
很多時候,我們都會用到oracle序列,那麼我們怎麼修改序列的當前值呢?首先我們可以檢視當前序列值是多少,如下 select 序列名.nextval from dual 比方說我現在查出來值是10,那麼我要把當前值改成8,那麼可以這麼改 alter sequence 序列名 increment by...
ORACLE 修改當前會話的語言環境
修改當前會話的語言環境變數引數 alter session set 將語言改為英語 sql alter session set nls language american session altered.將語言改回中文 sql alter session set nls language simpl...