Cad*_*oux 44 sql oracle primary-key sequence oracle10g
出于某种原因,过去的人不使用sequence.NEXTVAL插入数据.因此,当我使用sequence.NEXTVAL来填充表时,我得到了PK违规,因为该数字已在表中使用.
如何更新下一个值以使其可用?现在,我只是一遍又一遍地插入,直到它成功(INSERT INTO tbl (pk) VALUES (sequence.NEXTVAL)),然后同步下一个.
Bas*_*Roy 84
您可以临时增加缓存大小并执行一次虚拟选择,然后将缓存大小重置为1.例如
ALTER SEQUENCE mysequence INCREMENT BY 100;
select mysequence.nextval from dual;
ALTER SEQUENCE mysequence INCREMENT BY 1;
Run Code Online (Sandbox Code Playgroud)
Cad*_*oux 16
这两个过程让我重置序列并根据表中的数据重置序列(对此客户端使用的编码约定道歉):
CREATE OR REPLACE PROCEDURE SET_SEQ_TO(p_name IN VARCHAR2, p_val IN NUMBER)
AS
l_num NUMBER;
BEGIN
EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num;
-- Added check for 0 to avoid "ORA-04002: INCREMENT must be a non-zero integer"
IF (p_val - l_num - 1) != 0
THEN
EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by ' || (p_val - l_num - 1) || ' minvalue 0';
END IF;
EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num;
EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by 1 ';
DBMS_OUTPUT.put_line('Sequence ' || p_name || ' is now at ' || p_val);
END;
CREATE OR REPLACE PROCEDURE SET_SEQ_TO_DATA(seq_name IN VARCHAR2, table_name IN VARCHAR2, col_name IN VARCHAR2)
AS
nextnum NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT MAX(' || col_name || ') + 1 AS n FROM ' || table_name INTO nextnum;
SET_SEQ_TO(seq_name, nextnum);
END;
Run Code Online (Sandbox Code Playgroud)
DCo*_*kie 13
如果您可以指望表处于稳定状态且没有新插入的时间段,则应该这样做(未经测试):
DECLARE
last_used NUMBER;
curr_seq NUMBER;
BEGIN
SELECT MAX(pk_val) INTO last_used FROM your_table;
LOOP
SELECT your_seq.NEXTVAL INTO curr_seq FROM dual;
IF curr_seq >= last_used THEN EXIT;
END IF;
END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)
这使您可以使序列与表同步,而不会删除/重新创建/重新授予序列.它也不使用DDL,因此不执行隐式提交.当然,你将不得不追捕那些坚持不使用序列来填充列的人...
Len*_*rri 10
在我来说,我有一个叫做序列PS_LOG_SEQ其中有一个LAST_NUMBER = 3920.
然后我将一些数据从PROD我的本地机器导入并插入到PS_LOG表中.生产数据有多个20000行,最新的LOG_ID(主键)是20070.导入后我尝试在此表中插入新行但是在保存时我遇到了类似这样的异常:
ORA-00001: unique constraint (LOG.PS_LOG_PK) violated
Run Code Online (Sandbox Code Playgroud)
当然这PS_LOG_SEQ与PS_LOG表格相关的序列有关.的LAST_NUMBER是与I导入的数据,其已经从使用的下一个ID值的碰撞PS_LOG_SEQ.
为了解决这个问题,我使用此命令将序列更新为最新的\ max(LOG_ID)+ 1:
alter sequence PS_LOG_SEQ restart start with 20071;
Run Code Online (Sandbox Code Playgroud)
此命令重置该LAST_NUMBER值,然后我可以在表中插入新行.不再碰撞了.:)
注意:此alter sequence命令是Oracle 12c中的新增功能.
使用oracle 10.2g:
select level, sequence.NEXTVAL
from dual
connect by level <= (select max(pk) from tbl);
Run Code Online (Sandbox Code Playgroud)
将当前序列值设置为表格的最大值(pk)(即下次调用NEXTVAL将为您提供正确的结果); 如果您使用Toad,请按F5键运行语句,而不是F9,它会对输出进行分页(从而停止增量,通常为500行).好的一面:这个解决方案只有DML,而不是DDL.只有SQL而且没有PL-SQL.不好的一面:这个解决方案输出max(pk)行输出,即通常比ALTER SEQUENCE解决方案慢.