【问题标题】:What is the difference between Oracle's "sequence" and MySql's Auto_increment feature?Oracle“序列”和MySql自动增量功能有什么区别?
【发布时间】:2015-03-08 05:05:06
【问题描述】:

我不完全明白Oracle的sequence和MySql的auto_increment的区别。

我是一个mysql人,但对oracle一无所知。我希望有人可以为我快速了解这一点。

【问题讨论】:

  • 一个序列更像是一个规则而不是一个主键列
  • 快速:有一些非常显着的差异:AUTO_INCREMENT 绑定到单个表中的列,每个表只有一个。 Oracle SEQUENCE 不是。在数据库重新启动时,对于 InnoDB 表,AUTO_INCREMENT 被重置为最高列值。 Oracle SEQUENCE 不是。 Oracle SEQUENCE 对象是一个完全独立的对象,专为生成唯一值而设计,具有低争用/高并发性。 (确实,我们可以使用 SEQUENCE 和 BEFORE INSERT 触发器模拟 MySQL AUTO_INCREMENT,但“最终”,Oracle SEQUENCE 与 AUTO_INCREMENT 几乎没有相似之处。
  • 如果问题是:“我们可以在 Oracle 中模拟 MySQL 风格的 AUTO_INCREMENT 吗?”这个问题的答案是肯定的。如果问题是关于差异... Oracle 序列:可以有下限和上限;增量可以有负值;可以换行(达到上限后,重新开始指定的下限);可以使用 SELECT 语句检索新值,不需要 INSERT;单个序列可以被多种不同的触发器、函数、程序使用;可以独立于任何表删除/重新创建; SEQUENCE 的值在数据库重启等期间保留。

标签: mysql oracle


【解决方案1】:

Oracle 没有自动递增列。您需要创建一个序列并在插入触发器之前从序列中读取 NEXTVAL 并设置列的值

【讨论】:

  • 是的,你在 oracle 中是对的,你必须在任何表的任何数字列上添加额外的细节才能自动递增
  • @DanielBaughman:如果您的结论是“功能相同”,那么这是一个糟糕的答案,因为它们从根本上不同,是一些显着的特征差异。 (正如这个答案所指出的那样,我们可以在 Oracle 中模拟类似 MySQL 的 AUTO_INCREMENT,并且模拟可以有效地使用 SEQUENCE 对象来做到这一点,但 Oracle SEQUENCE 是方式不仅仅是 AUTO_INCREMENT。
  • 如果您使用 oracle12c,您可以模拟 auto_increment 声明一个数字列,例如:id number generated as identity
  • 是的,创建另一个单行单列存储下一个id值的表。然后在原始表上创建一个插入触发器,增加第二个表中的值,抓取它,并将其用于第一个表上的 ID 列
  • @Aramillo:是的,并且标识列是使用序列实现的。可以很好地了解差异。
【解决方案2】:

序列是 Oracle 中不同的数据库对象。

在 MySQL 中,当您有一个自动增量列并且您在表中插入一个新行时,您根本不会提及自动增量列,而 MySQL 将它放在那里。然后,您可以通过引用 LAST_INSERT_ID() 将相同的数字插入到另一个表中。

 INSERT INTO person  (name, date)                             /*MySQL*/
                 VALUES ('joe', '2015-01-01');
 INSERT INTO contact (person_id, phone)
                 VALUES (LAST_INSERT_ID(), '555-1212');

在 Oracle 中,您可以通过提及序列对象的 .nextval 属性来填充 id 列。您可以通过引用其.currval 属性来获取该序列的刚刚使用的值。

 INSERT INTO person (id, name, date)                         -- Oracle
                   VALUES (person_seq.nextval, 'joe', '2015-01-01');
 INSERT INTO contact (id, person_id, phone)
                   VALUES (contact_seq.nextval, person_seq.currval, '555-1212');

每次提及序列的.nextval 属性时,都会保证给出一个新数字。

当您需要与某个表或其他表的主键不直接相关的唯一数字时,序列对象非常酷。您可以在 MySQL 中执行此操作,但这很麻烦:如果您创建下表:

 CREATE TABLE sequence (                                       /*MySQL*/
     sequence_id BIGINT NOT NULL AUTO_INCREMENT,
     PRIMARY KEY (`sequence_id`)
) 

然后依次发出这三个查询:

INSERT INTO sequence () VALUES ();                            /*MySQL*/
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
SELECT LAST_INSERT_ID() AS sequence;

保证第三个查询返回一个唯一的序列号。即使您有几十个不同的客户端程序连接到您的数据库,这种保证仍然有效。 (DELETE 查询只是防止这个原本毫无意义的表占用太多空间。)

使用 Oracle,您可以创建序列

create sequence seq                                           --Oracle

然后就做吧

SELECT seq.nextval FROM DUAL                                  --Oracle

获得一个新的序列号,就是这样。即使有数十个连接的客户端程序,它也能保证唯一性。

同样,如果你需要你刚刚用.nextval生成的序列的值,你可以发出这个命令并得到它。

SELECT seq.currval FROM DUAL                                 --Oracle

与 MySQL 的 LAST_INSERT_ID() 一样,这是逐个会话处理的,因此使用该序列的另一个客户端不会让您获得他们的号码而不是您的号码。

底线:两个 DBMS 都可以生成唯一的整数。这两种方案的完整性旨在在服务器停止和重新启动时保持不变。 Oracle 序列更灵活。

【讨论】:

  • 这对 MySQL 来说是一个很棒的技术。比试图在控制表中保留序列要好得多。感谢您的建议。
【解决方案3】:

Oracle DB 中的序列是一个单独的实体,您可以在查询中访问它以获取/增加其值,并且您可以对多个表/字段使用相同的序列。

MySQL 中的自动增量绑定到表中的单个字段并用于定义该字段的值,当插入查询中未给出时。

【讨论】:

  • 不仅“理论上”我们可以对多个表使用相同的 SEQUENCE,我们也可以“在实践中”这样做。
  • @spencer7593 感谢您的澄清,我对 Oracle 没有太多经验。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2016-10-01
相关资源
最近更新 更多