将 Oracle 序列重置为现有列中的下一个值的最佳方法?
由于某种原因,过去人们插入数据时没有使用sequence.NEXTVAL。因此,当我使用sequence.NEXTVAL来填充表时,我遇到了PK违规,因为该数字已在表中使用。
如何更新下一个值以使其可用?现在,我只是一遍又一遍地插入,直到成功(INSERT INTO tbl (pk) VALUES (sequence.NEXTVAL)
),然后同步 nextval。
For some reason, people in the past have inserted data without using sequence.NEXTVAL. So when I go to use sequence.NEXTVAL in order to populate a table, I get a PK violation, since that number is already in use in the table.
How can I update the next value so that it is usable? Right now, I'm just inserting over and over until it's successful (INSERT INTO tbl (pk) VALUES (sequence.NEXTVAL)
), and that syncs up the nextval.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
您可以暂时增加缓存大小并执行一次虚拟选择,然后将缓存大小重置回 1。例如
You can temporarily increase the cache size and do one dummy select and then reset the cache size back to 1. So for example
就我而言,我有一个名为
PS_LOG_SEQ
的序列,其中包含LAST_NUMBER = 3920
。然后,我将一些数据从
PROD
导入到本地计算机,并插入到PS_LOG
表中。生产数据有超过 20000 行,最新的 LOG_ID(主键)为 20070。导入后,我尝试在此表中插入新行,但在保存时出现如下异常:当然,这有处理与
PS_LOG
表关联的序列PS_LOG_SEQ
。LAST_NUMBER
与我导入的数据发生冲突,该数据已使用PS_LOG_SEQ
中的下一个 ID 值。为了解决这个问题,我使用此命令将序列更新为最新的 \
max(LOG_ID)
+ 1:此命令重置
LAST_NUMBER
值,然后我可以将新行插入到桌子。不再有碰撞。 :)注意:这个
alterequence
命令是 Oracle 12c 中的新命令。注意:此
博客post
记录了 ALTER SEQUENCE RESTART 选项确实存在,但截至 18c,没有记录;它显然是供 Oracle 内部使用的。In my case I have a sequence called
PS_LOG_SEQ
which had aLAST_NUMBER = 3920
.I then imported some data from
PROD
to my local machine and inserted into thePS_LOG
table. Production data had more than20000
rows with the latest LOG_ID (primary key) being 20070. After importing I tried to insert new rows in this table but when saving I got an exception like this one:Surely this has to do with the Sequence
PS_LOG_SEQ
associated with thePS_LOG
table. TheLAST_NUMBER
was colliding with data I imported which had already used the next ID value from thePS_LOG_SEQ
.To solve that I used this command to update the sequence to the latest \
max(LOG_ID)
+ 1:This command reset the
LAST_NUMBER
value and I could then insert new rows into the table. No more collision. :)Note: this
alter sequence
command is new in Oracle 12c.Note: this
blog post
documents the ALTER SEQUENCE RESTART option does exist, but as of 18c, is not documented; it is apparently intended for internal Oracle use.这两个过程让我重置序列并根据表中的数据重置序列(对此客户使用的编码约定表示歉意):
These two procedures let me reset the sequence and reset the sequence based on data in a table (apologies for the coding conventions used by this client):
如果您可以指望在一段时间内表处于稳定状态,没有进行新的插入,那么这应该可以做到(未经测试):
这使您能够使序列恢复与表同步,而不会丢失/重新创建/重新授予序列。它还不使用 DDL,因此不会执行隐式提交。当然,您将不得不追捕并打那些坚持不使用该序列填充该列的人......
If you can count on having a period of time where the table is in a stable state with no new inserts going on, this should do it (untested):
This enables you to get the sequence back in sync with the table, without dropping/recreating/re-granting the sequence. It also uses no DDL, so no implicit commits are performed. Of course, you're going to have to hunt down and slap the folks who insist on not using the sequence to populate the column...
对于 oracle 10.2g:
会将当前序列值设置为表的 max(pk)(即下一次调用 NEXTVAL 将为您提供正确的结果);如果您使用 Toad,请按 F5 运行该语句,而不是按 F9,这会对输出进行分页(因此通常会在 500 行后停止增量)。
好的一面:这个解决方案只有 DML,而不是 DDL。只有 SQL,没有 PL-SQL。
不好的一面:此解决方案打印 max(pk) 行输出,即通常比 ALTER SEQUENCE 解决方案慢。
With oracle 10.2g:
will set the current sequence value to the max(pk) of your table (i.e. the next call to NEXTVAL will give you the right result); if you use Toad, press F5 to run the statement, not F9, which pages the output (thus stopping the increment after, usually, 500 rows).
Good side: this solution is only DML, not DDL. Only SQL and no PL-SQL.
Bad side : this solution prints max(pk) rows of output, i.e. is usually slower than the ALTER SEQUENCE solution.
如今,在 Oracle 12c 或更高版本中,您可能将列定义为 GENERATED ... AS IDENTITY,并且 Oracle 会自行处理序列。
您可以使用 ALTER TABLE 语句来修改标识的“START WITH”。
Today, in Oracle 12c or newer, you probably have the column defined as GENERATED ... AS IDENTITY, and Oracle takes care of the sequence itself.
You can use an ALTER TABLE Statement to modify "START WITH" of the identity.
很抱歉没有单行解决方案,因为我的程序在 Typeorm 和 node-oracle 中运行。不过,我认为以下 SQL 命令将有助于解决这个问题。
从序列中获取
LAST_NUMBER
。从最后一行获取您的 PK 值(在本例中 ID 是 PK)。
最后将
LAST_NUMBER
更新为值 + 1:Apologies for not having a one-liner solution, since my program runs in Typeorm with node-oracle. However, I think the following SQL commands would help with this problem.
Get the
LAST_NUMBER
from your sequence.Get the value of your PK from the last row (in this case ID is the PK).
Lastly update
LAST_NUMBER
to the value + 1:就我而言,我使用了一种方法将序列重置为零,然后将目标表从零设置为最大值:
In my case I used an approach to reset sequence to zero and than setting from zero to max of target table:
我想最好的解决方案是更新序列当前值的存储过程。
我在Oracle中使用这个存储过程:
执行存储过程:(
对不起我的英语,我同意请修复我)
问候。
I guess the best solution is a stored procedure to update sequences current value.
I use this stored procedure in Oracle:
To execute the stored procedure:
(Sorry for my English, I agree fix me please)
Greetings.