【问题标题】:Auto-increment in Oracle without using a trigger不使用触发器在 Oracle 中自动递增
【发布时间】:2010-09-23 22:31:53
【问题描述】:

除了使用触发器之外,oracle 中实现自增的其他方法是什么?

【问题讨论】:

标签: oracle triggers auto-increment sequences


【解决方案1】:

您可以创建和使用 oracle 序列。语法和详细信息位于 http://www.techonthenet.com/oracle/sequences.php

另请阅读文章 http://rnyb2.blogspot.com/2006/02/potential-pitfall-with-oracle-sequence.html 了解其他 RDBMS 中关于 AUTONUMBER 的限制

【讨论】:

  • 没错。缓存和回滚使这几乎不可能...... +1。
【解决方案2】:

如果您不需要序列号而只需要唯一 ID,则可以使用 SYS_GUID() 的默认值。即:

CREATE TABLE xxx ( ID RAW(16) DEFAULT SYS_GUID() )

【讨论】:

    【解决方案3】:

    从序列中获取下一个值的触发器是实现等价于 AUTOINCREMENT 的最常见方法:

    create trigger mytable_trg
    before insert on mytable
    for each row
    when (new.id is null)
    begin
        select myseq.nextval into :new.id from dual;
    end;
    

    如果您控制插入,则不需要触发器 - 只需使用插入语句中的序列:

    insert into mytable (id, data) values (myseq.nextval, 'x');
    

    这可以隐藏在 API 包中,因此调用者不需要引用序列:

    mytable_pkg.insert_row (p_data => 'x');
    

    但使用触发器更“透明”。

    【讨论】:

    • 只有当 :new.id 为 NULL 时,触发器才可能生成一个序列值,这将更接近于其他数据库品牌中的自动增量。
    • 请注意,您需要 FOR EACH ROW 否则 :new 不可访问...或者至少这是我在 PL/SQL 上一门课时教科书所说的。
    【解决方案4】:

    据我在 Oracle 时代的回忆,如果不使用 TRIGGER,您将无法实现自动增量列。任何用于制作自动增量列的解决方案都涉及 TRIGGER 和 SEQUENCE(我假设您已经知道这一点,因此没有触发备注)。

    【讨论】:

    • 当然可以。您创建一个获取 nextval 的插入过程。您撤销该表上的 Insert 并授予该 proc/package 上的执行权限。不需要触发器。
    • 为什么选择了这个答案?
    • 因为这是真的。如果不使用 Trigger 和 Sequence,您将无法执行简单的 INSERT 并获得与自动增量相同的效果。如果您将 Stored Proc 视为普通插入,Mark Brady 的回答也是正确的。
    【解决方案5】:

    创建一个序列:

    create sequence seq;
    

    然后添加一个值

    insert into table (id, other1, other2)
    values (seq.nextval, 'hello', 'world');
    

    注意:查找 oracle 文档以获取有关序列的更多选项(起始值、增量等)

    【讨论】:

      【解决方案6】:

      从 12c 开始,您可以使用 identity column,它明确表和自动增量之间的链接;不需要触发器或序列。语法是:

      create table <table_name> ( <column_name> generated as identity );
      

      【讨论】:

        【解决方案7】:

        除了例如FerranB 的回答:
        可能值得一提的是,与 auto_incement 在 MySQL 中的工作方式不同:

      • 序列在数据库范围内工作,因此它们可以用于多个表,并且值对于整个数据库是唯一的
      • 因此:截断表不会重置“自动增量”功能
      • 【讨论】:

          【解决方案8】:

          如果您真的不想使用“基于触发器”的解决方案,您可以通过编程方式实现自增功能,通过getGeneratedKeys() 方法获取自增键的值。

          这里有一个代码 sn-p 供您参考:

          Statement stmt = null;
          ResultSet rs = null;
          
          stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                                          java.sql.ResultSet.CONCUR_UPDATABLE);
          
          stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTable");
          
          stmt.executeUpdate("CREATE TABLE autoIncTable ("
                          + "priKey INT NOT NULL AUTO_INCREMENT, "
                          + "dataField VARCHAR(64), PRIMARY KEY (priKey))");
          
          stmt.executeUpdate("INSERT INTO autoIncTable  (dataField) "
                          + "values ('data field value')",
                          Statement.RETURN_GENERATED_KEYS);
          
          int autoIncKeyFromApi = -1;
          
          rs = stmt.getGeneratedKeys();
          
          if (rs.next()) {
              autoIncKeyFromApi = rs.getInt(1);
          }
          else {
              // do stuff here        
          }
          
          rs.close();
          

          来源:http://forums.oracle.com/forums/thread.jspa?messageID=3368856

          【讨论】:

            【解决方案9】:
            SELECT max (id) + 1 
            FROM   table
            

            【讨论】:

            • 我认为它不是真正的并发友好
            • “我认为它不是真正的并发友好”我会支持。我已经看到以这种方式编码的 Web 应用程序做了各种有趣的事情......
            • 这真的是最糟糕的做法。永远不要使用这样的东西。
            • 如果表为空怎么办? :-(
            • 如果桌子满了怎么办? ;)
            猜你喜欢
            • 2012-04-01
            • 2012-04-17
            • 2013-04-29
            • 1970-01-01
            • 2011-11-08
            • 2016-05-30
            • 2015-11-11
            • 2015-06-09
            相关资源
            最近更新 更多