ORACLE 序列sequence添加数据 重复添加

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ORACLE 序列sequence添加数据 重复添加相关的知识,希望对你有一定的参考价值。

我的添加 sql语句是
insert into a
select a_seq.nextval,'张三','男' from dual 后台日志显示 sql只执行了一次, 却生成了 两条记录
1 张三 男
2 张三 男

(1)不排除以前执行过或手动插入过记录的可能。
(2)如果代码本身只是这么简单的代码,那我没看出来什么问题,如果代码并不是这么简单,那么就仔细检查一下代码,入股确定代码没有任何问题,那么我有了以下猜想。
(2)个人觉得很扯淡的一种解释(可能),你可以试验一下,未必是真的,但如果是真的,那就发现bug了
首先声明,我没试验过,仅仅是一种猜想,猜错了是绝对可能的,毕竟一般情况下怎么也不可能在最开始只添加一条数据。
在最开始(划重点)的一条数据来说,应该是两条数据。因为有两个值,一个是init起始值,一个是nextval值,也就是说序列最开始(划重点)插入时至少是有两条数据的,这也就解释了为什么你的编号1,2插入时是两条,其他值插入值为1条。至于以后添加的nextval值,则都是以当前值为基础的,所以不会出现这种情况。当然这种情况应该只会出现在起始值+只添加一条数据的情况下。(以上均为猜测,具体的要靠你的试验来证明)
想排除这种可能,只要再建立一张表,一个序列,最开始(起始值)还是像这样一样只插入一条,看看是不是两条,如果是两条,那么就说明这猜测可能是真的,如果是一条,那就应该是我的猜想错误。
虽然我也知道猜想好像很扯淡,但是不妨试试。追问

首先谢谢,但是你看看这个现象还有点让人头疼, 我是循环给学分插入审核日志, 这些学分有的生成了一条日志, 有的生成了两条, 从后台日志上看, 日志是都一样的, 一直到 jdbcTemplate执行namedParameterJdbcTemplate.update(sql, params);

追答

不应该的啊,按照我的想法只有最开始的值(也就是序列的最初值,也就是说只会出现一次,以后都不会出现)才会出现这种情况,以后应该不会出现才对,如果一直出现这种情况,那么应该就不是我说的那种情况,这个就不好分析了,光这么说是没用的,你查查看oracle自己的日志吧,或者也看看原表有没有id相同的情况,反正这个就和我的猜想不同了。

追问

你这个想法很靠谱, 这个问题有点不靠谱, 不知道是什么bug, 我都怀疑框架和oracle了.等运维回来 让他看看能不能调取一下执行的日志吧 怎么生成的这两条数据 , 问题找到了, 是项目布了两台机器, 所以在点击置灰之前分发了两次请求,形成了 并发

参考技术A

怎么测试也是一条,我怀疑你不小心多点了一次

追问

开始也是怀疑 执行了两次 添加的方法, 但是日志上看, 执行这个方法之前只打印了一行数据,

追答

那你好好检查一下你的代码吧

追问

我觉得这事得找运维!! - -#

追答

在代码确认无误的情况下,再找运维人员,看他们是怎么操作的,这样才能找到具体的原因

追问

好的,谢谢了,, 对了 还有一点, 就是这个执行期间有时候是一条 有时候是两条

ORACLE Sequence 自增长

Sequence是数据库系统按照一定规则自动增加的数字序列。这个序列一般作为代理主键(因为不会重复),没有其他任何意义。

Sequence是数据库系统的特性,有的数据库有Sequence,有的没有。比如Oracle、DB2、PostgreSQL数据库有Sequence,MySQL、SQL Server、Sybase等数据库没有Sequence。

根据我个人理解,Sequence是数据中一个特殊存放等差数列的表,该表受数据库系统控制,任何时候数据库系统都可以根据当前记录数大小加上步长来获取到该表下一条记录应该是多少,这个表没有实际意义,常常用来做主键用,非常不错,呵呵,不过很郁闷的各个数据库厂商尿不到一个壶里–各有各的一套对Sequence的定义和操作。在此我对常见三种数据库的Sequence的定义和操作做一个对比和总结,以便日后查看。
一、定义Sequence

定义一个seq_test,最小值为1,最大值为99999999999999999,从1开始,增量的步长为1,缓存为20的循环排序Sequence。

Oracle的定义方法:
create sequence seq_test
minvalue 1
maxvalue 99999999999999999
start with 1
increment by 1
cache 20
cycle
order;

DB2的写法:
create sequence seq_test
       as bigint
       start with 20000
       increment by 1
       minvalue 10000
       maxvalue 99999999999999999
       cycle
       cache 20
       order;

PostgreSQL的写法:
create sequence seq_test
       increment by 1
       minvalue 10000
       maxvalue 99999999999999999
       start 20000
       cache 20
       cycle;


二、Oracle、DB2、PostgreSQL数据库Sequence值的引用参数为:currval、nextval,分别表示当前值和下一个值。

下面分别从三个数据库的Sequence中获取nextval的值。

Oracle中:seq_test.nextval
例如:select seq_test.nextval from dual;
DB2中:nextval for SEQ_TOPICMS
例如:values nextval for seq_test;
PostgreSQL中:nextval(seq_test)
例如:select nextval(seq_test);
三、Sequence与indentity的区别与联系

Sequence与indentity的基本作用都差不多。都可以生成自增数字序列。
Sequence是数据库系统中的一个对象,可以在整个数据库中使用,和表没有任何关系;indentity仅仅是指定在表中某一列上,作用范围就是这个表。

 

ORACLE SEQUENCE的简单介绍
在oracle中sequence就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按序列号排序的地方。
 
1、Create Sequence

你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限, 
CREATE SEQUENCE emp_sequence 
     INCREMENT BY 1   — 每次加几个 
     START WITH 1     — 从1开始计数 
     NOMAXVALUE       — 不设置最大值 
     NOCYCLE          — 一直累加,不循环 
     CACHE 10; 
一旦定义了emp_sequence,你就可以用CURRVAL,NEXTVAL 
CURRVAL=返回 sequence的当前值 
NEXTVAL=增加sequence的值,然后返回 sequence 值

比如: 
   emp_sequence.CURRVAL 
   emp_sequence.NEXTVAL

可以使用sequence的地方: 
- 不包含子查询、snapshot、VIEW的 SELECT 语句 
- INSERT语句的子查询中 
- NSERT语句的VALUES中 
- UPDATE 的 SET中  

可以看如下例子: 
INSERT INTO emp VALUES (empseq.nextval, ‘LEWIS’, ‘CLERK’,7902, SYSDATE, 1200, NULL, 20); 
SELECT empseq.currval FROM DUAL; 
但是要注意的是:

– 第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENT BY值,然后返回增加后的值。CURRVAL 总是返回当前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错。一次NEXTVAL会增加一次SEQUENCE的值,所以如果你在不同的SQl语句里面使用NEXTVAL,其值是不一样的。
 
– 如果指定CACHE值,ORACLE就可以预先在内存里面放置一些sequence,这样存取的快些。cache里面的取完后,oracle自动再取一组到cache。 使用cache或许会跳号, 比如数据库突然不正常down掉(shutdown abort),cache中的sequence就会丢失. 所以可以在create sequence的时候用nocache防止这种情况。
 
2、Alter Sequence

你或者是该sequence的owner,或者有ALTER ANY SEQUENCE 权限才能改动sequence. 可以alter除start至以外的所有sequence参数.如果想要改变start值,必须 drop   sequence 再 re-create . 
Alter sequence 的例子 
ALTER SEQUENCE emp_sequence 
     INCREMENT BY 10 
     MAXVALUE 10000 
     CYCLE     — 到10000后从头开始 
     NOCACHE ;

影响Sequence的初始化参数: 
SEQUENCE_CACHE_ENTRIES =设置能同时被cache的sequence数目。  
可以很简单的Drop Sequence 
DROP SEQUENCE order_seq;

 

下面详细介绍NEXTVAL和CURRVAL用法以及sequence用法的限制
使用 NEXTVAL

第一次访问一个序列,在引用 sequence.CURRVAL 之前必须先引用 sequence.NEXTVAL。第一次引用 NEXTVAL,返回序列的初始值。后面每次引用 NEXTVAL,用已定义的 step 增加序列值并返回序列新的增加以后的值。

在一个 SQL 语句中只能对给定的序列增加一次。即使在一个语句中多次指定 sequence.NEXTVAL,序列也只增加一次,所以每次 sequence.NEXTVAL 出现在同一 SQL 语句中返回相同的值。除了在同一语句中多次出现这种情况以外,每个sequence.NEXTVAL表达式都会增加序列,无论后来是否提交或回滚当前事务。如果在最终回滚的事务中指定sequence.NEXTVAL,某些序列数可能被跳过。

如在PL/SQL中:
查询nextval的值等于151
select cheng.nextval from test1234 
执行insert语句
insert into test1234 values(cheng.nextval,’bb’,22);
commit或rollback后再查询nextval的值会增加到153
使用 CURRVAL

任何对CURRVAL的引用返回指定序列的当前值,该值是最后一次对NEXTVAL的引用所返回的值。用NEXTVAL生成一个新值以后,可以继续使用 CURRVAL访问这个值,不管另一个用户是否增加这个序列。如果sequence.CURRVAL和 sequence.NEXTVAL都出现在一个 SQL语句中,则序列只增加一次。在这种情况下,每个sequence.CURRVAL和 sequence.NEXTVAL表达式都返回相同的值,不管在语句中sequence.CURRVAL和sequence.NEXTVAL的顺序。

如在PL/SQL中:
select cheng.nextval,cheng.currval from test1234
nextval和currval的值都是160
序列的并发访问

序列总是在数据库中生成唯一值,即使当多个用户并发地引用同一序列时也没有可察觉的等待或锁定。当多个用户使用 NEXTVAL 来增长序列时,每个用户生成一个其他用户不可见的唯一值。当多个用户并发地增加同一序列时,每个用户看到的值是有差异的。例如,一个用户可能从一个序列生成一组值,如 11、14、16 和 18,而另一个用户并发地从同一序列生成值 12、13、15 和 17。
sequence使用的限制

NEXTVAL 和 CURRVAL 只在 SQL 语句中有效,并不在 SPL 语句中直接有效。(但是使用NEXTVAL 和CURRVAL的SQL语句可用于SPL例程)以下限制应用于 SQL 语句中的这些运算符:
[1]在 CREATE TABLE 或 ALTER TABLE 语句中,在下列上下文中不能指定 NEXTVAL 或 CURRVAL:
   在 DEFAULT 子句中。
   在检查约束中。

[2]在 SELECT 语句中,下列上下文中不能指定 NEXTVAL 或 CURRVAL:
   使用 DISTINCT 关键字时在投影列表中。
   在 WHERE、GROUP BY 或 ORDER BY 子句中。
   在子查询中。
   在 UNION 运算符结合 SELECT 语句时。

[3]在下列这些上下文中也不能指定 NEXTVAL 或 CURRVAL:
   在分段存储表达式中
   在对另一个数据库中的远程序列对象的引用中。
Oracle中实现类似自动增加 ID 的功能

我们经常在设计数据库的时候用一个系统自动分配的ID来作为我们的主键,但是在ORACLE 中没有这样的 功能,我们可以通过采取以下的功能实现自动增加ID的功能.

1.首先创建 sequence
create sequence seqmax increment by 1
2.使用方法
select seqmax.nextval id from dual
就得到了一个和ms sql的自动增加ID相同的功能id值

 

 

复制来源参考:http://www.a18zhizao.cn/y2008/617_since-the-growth-oracle-sequence.html 

                   http://blog.csdn.net/aqszhuaihuai/article/details/4100793





























































































以上是关于ORACLE 序列sequence添加数据 重复添加的主要内容,如果未能解决你的问题,请参考以下文章

Oracle Sequence创建与使用

Oracle中插入千万条测试数据

mybatis里的xml中的写添加的sql语句,怎么使用oracle数据库的序列

#194 sequence(搜索+动态规划+主席树)

Oracle数据库中序列(SEQUENCE)的用法详解

oracle数据库怎么建sequences作为自增长序列