oracle生成主键

 

create table SYS_SEQUENCE
(
  PK1           VARCHAR2(32) not null,
  ATYPE         VARCHAR2(20) not null,
  OWNER         VARCHAR2(10) not null,
  INITCYCLE     CHAR(1) not null,
  CUR_SERNUM    VARCHAR2(50) not null,
  ZERO_FLG      VARCHAR2(2) not null,
  SEQUENCESTYLE VARCHAR2(50),
  MEMO          VARCHAR2(60)
);
-- Add comments to the columns 
comment on column SYS_SEQUENCE.PK1
  is '主键';
comment on column SYS_SEQUENCE.ATYPE
  is '序列号类型';
comment on column SYS_SEQUENCE.OWNER
  is '序列号所有者';
comment on column SYS_SEQUENCE.INITCYCLE
  is '序列号递增';
comment on column SYS_SEQUENCE.CUR_SERNUM
  is '序列号';
comment on column SYS_SEQUENCE.ZERO_FLG
  is '序列号长度';
comment on column SYS_SEQUENCE.SEQUENCESTYLE
  is '序列号样式';
comment on column SYS_SEQUENCE.MEMO
  is '备注';
-- Create/Recreate primary, unique and foreign key constraints 
alter table SYS_SEQUENCE
  add primary key (PK1);
-- Create/Recreate indexes 
create index PK_SYS_SEQUENCE on SYS_SEQUENCE (ATYPE, OWNER);

 

 

insert into SYS_SEQUENCE (PK1, ATYPE, OWNER, INITCYCLE, CUR_SERNUM, ZERO_FLG, SEQUENCESTYLE, MEMO)
values ('0A772AEDFBED4FEEA46442003CE1C6A6', 'ZDBCONTCN', '750405', '1', '200002', '7', '$YEAR$年$ORGAPP$质字第$SER$号', '质押合同中文编号');

insert into SYS_SEQUENCE (PK1, ATYPE, OWNER, INITCYCLE, CUR_SERNUM, ZERO_FLG, SEQUENCESTYLE, MEMO)
values ('0A772AEDFBED4FEEA46442003CE1C6A7', 'T_BASIC_ROLE', '750405', '1', '9200022', '8', '$SER$', '质押合同中文编号');

 

 

 

CREATE OR REPLACE FUNCTION GEN_SYS_SEQUENCE(I_ATYPE IN VARCHAR2, /*序列类别*/
                                            I_OWNER IN VARCHAR2 /*序列所有者*/)
  RETURN VARCHAR2 IS
  /**************************************************************************************************/
  /* PROCEDURE NAME : GEN_SYS_SEQUENCE               */
  /* DEVELOPED BY : WANGXF                  */
  /* DESCRIPTION : 主要用来生成自定义的序列号             */
  /* DEVELOPED DATE : 2016-10-08                 */
  /* CHECKED BY  :                    */
  /* LOAD METHOD : F1-DELETE INSERT                */
  /**************************************************************************************************/

  O_AUTOCODE        VARCHAR2(100); /*输出的序列号*/
  V_INITCYCLE       SYS_SEQUENCE.INITCYCLE%TYPE; /*序列号递增*/
  V_CUR_SERNUM      SYS_SEQUENCE.CUR_SERNUM%TYPE; /*序列号*/
  V_ZERO_FLAG       SYS_SEQUENCE.ZERO_FLG%TYPE; /*序列号长度*/
  V_SEQUENCESTYLE   SYS_SEQUENCE.SEQUENCESTYLE%TYPE; /*序列号样式*/
  V_SEQ_NUM         VARCHAR2(100); /*本次序列号*/
  V_DATE_YEAR       CHAR(4); /*年份,如2016*/
  V_DATE_YEAR_MONTH CHAR(6); /*年份月份,如201610*/
  V_DATE_DATE       CHAR(8); /*年份月份日,如20161008*/
  V_DATE_DATE_ALL   CHAR(14); /*完整年份序列,如20161008155732*/

  /*
   支持的参数序列:
   $YEAR$ --> 年份
   $YEAR_MONTH$ --> 年份+月份,不含汉子
   $DATE$ --> 年份+月份+日期,不含汉子
   $DATE_ALL$ --> 完整日期,不含汉子
   $ORGAPP$ --> 所有者
   $SER$ --> 当前序列号
  */

  --解决查询事务无法执行DML的问题
  Pragma Autonomous_Transaction;
BEGIN
    --格式化当前日期
  SELECT TO_CHAR(SYSDATE, 'yyyy'),
         TO_CHAR(SYSDATE, 'yyyyMM'),
         TO_CHAR(SYSDATE, 'yyyyMMdd'),
         TO_CHAR(SYSDATE, 'yyyyMMddHH24MISS')
    INTO V_DATE_YEAR, V_DATE_YEAR_MONTH, V_DATE_DATE, V_DATE_DATE_ALL
    FROM DUAL;
    
  begin
    -- 查询复核条件的序列号配置
    SELECT T.INITCYCLE, T.CUR_SERNUM, T.ZERO_FLG, T.SEQUENCESTYLE
      INTO V_INITCYCLE, V_CUR_SERNUM, V_ZERO_FLAG, V_SEQUENCESTYLE
      FROM SYS_SEQUENCE T
     WHERE T.ATYPE = I_ATYPE
       AND T.OWNER = I_OWNER;
  EXCEPTION
    WHEN OTHERS THEN
      null;
      insert into SYS_SEQUENCE
        (PK1,
         ATYPE,
         OWNER,
         INITCYCLE,
         CUR_SERNUM,
         ZERO_FLG,
         SEQUENCESTYLE,
         MEMO)
      values
        (I_ATYPE || V_DATE_DATE_ALL,
         I_ATYPE,
         I_OWNER,
         '1',
         '0',
         '8',
         '$SER$',
         V_DATE_DATE_ALL||'系统生成');
    
      SELECT T.INITCYCLE, T.CUR_SERNUM, T.ZERO_FLG, T.SEQUENCESTYLE
        INTO V_INITCYCLE, V_CUR_SERNUM, V_ZERO_FLAG, V_SEQUENCESTYLE
        FROM SYS_SEQUENCE T
       WHERE T.ATYPE = I_ATYPE
         AND T.OWNER = I_OWNER;
  end;


  -- 日期处理
  O_AUTOCODE := REPLACE(V_SEQUENCESTYLE, '$YEAR$', V_DATE_YEAR);
  O_AUTOCODE := REPLACE(O_AUTOCODE, '$YEAR_MONTH$', V_DATE_YEAR_MONTH);
  O_AUTOCODE := REPLACE(O_AUTOCODE, '$DATE$', V_DATE_DATE);
  O_AUTOCODE := REPLACE(O_AUTOCODE, '$DATE_ALL$', V_DATE_DATE_ALL);

  --所有者处理
  O_AUTOCODE := REPLACE(O_AUTOCODE, '$ORGAPP$', I_OWNER);

  --序号处理
  V_SEQ_NUM := TO_CHAR(TO_NUMBER(V_CUR_SERNUM) + TO_NUMBER(V_INITCYCLE));

  --反写当前序列号,确保每次都是递增
  UPDATE SYS_SEQUENCE T
     SET T.CUR_SERNUM = V_SEQ_NUM
   WHERE T.ATYPE = I_ATYPE
     AND T.OWNER = I_OWNER;

  --不满足长度的前面补0
  IF LENGTH(V_SEQ_NUM) < TO_NUMBER(V_ZERO_FLAG) THEN
    /*
       LOOP
        V_SEQ_NUM := '0'||V_SEQ_NUM;
       EXIT WHEN LENGTH(V_SEQ_NUM) = TO_NUMBER(V_ZERO_FLAG);
       END LOOP;
          */
    V_SEQ_NUM := LPAD(V_SEQ_NUM, TO_NUMBER(V_ZERO_FLAG), '0');
  END IF;

  O_AUTOCODE := REPLACE(O_AUTOCODE, '$SER$', V_SEQ_NUM);

  COMMIT;
  RETURN O_AUTOCODE;
EXCEPTION
  --如果没有对应的配置项,则返回ERROR值
  WHEN NO_DATA_FOUND THEN
    ROLLBACK;
    DBMS_OUTPUT.put_line('there is no config as you need...');
    RETURN 'ERROR';
END GEN_SYS_SEQUENCE;

 

 

 

public String getNewPkId(String tableName) throws SQLException {
        if (getDbType().equals("oracle")) {
            String sql = "{?= call GEN_SYS_SEQUENCE(?,?)}";
            return callDatabaseFunction(sql, tableName, "750405");
        }else if (getDbType().equals("mysql")) {
            return null;
        }
        return null;
    }

    /**
     * @param sql 类似于:{?= call SF_SYS_GEN_AUTOCODE(?,?)}
     * @return
     */
    public String callDatabaseFunction(String sql, Object... params) throws SQLException {
        String retStr = "";

        Connection connection = null;
        /**
         * 调用存储函数 1.{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
         * 调用存储过程 2.{call <procedure-name>[(<arg1>,<arg2>, ...)]}
         */
        CallableStatement callableStatement = null;
        connection = getConnection();
        /*
         * 1.通过COnnection对象的prepareCall()方法创建一个CallableStatement
         * 对象的实例,在使用Connection对象的prepareCall() 方法时,需要传入一个String类型的字符串,
         * 该字符串用于指明如何调用存储过程
         */
        callableStatement = connection.prepareCall(sql);

        /*
         * 2.通过CallableStatement对象的registerOutParameter() 方法注册Out参数
         */
        //callableStatement.registerOutParameter(1, Types.NUMERIC);
        callableStatement.registerOutParameter(1, Types.VARCHAR);

        /*
         * 3.通过CallableStatement对象的setXxx()方法设定IN或In out
         * 参数,若想将参数设为null,可以使用setNUll()
         */
        for (int i = 0; i < params.length; i++) {
            callableStatement.setObject(i + 2, params[i]);
        }

//        callableStatement.setString(2, "T_BASIC_ROLE");
//        callableStatement.setString(3, "012805");

        /* 4.通过CallableStatement对象的execute()方法执行存储过程 */
        callableStatement.execute();

        /*
         * 5.如果所调用的是带返回参数的存储过程没还需要通过CallableStatement对象的getXxx()
         */
        retStr = callableStatement.getString(1);
        DbUtils.close(connection);


        return retStr;
    }

 

转载于:https://www.cnblogs.com/yasepix/p/6512966.html

Oracle 自动生成主键是一种数据库设计策略,在创建表时,如果未明确指定主键,则 Oracle 可以自动分配唯一的标识符作为每一行的数据记录。这种功能通常通过使用序列(Sequence)、伪列(pseudo-columns)或其他特定函数来实现。 ### 序列 (Sequence): 在 Oracle 中,序列是一个用于生成唯一整数值的对象。当您插入数据到包含自动增加主键的表时,Oracle 将使用序列对象来获取下一个可用的唯一数值。这通常是通过 `NEXTVAL` 或者 `currval` 等方法来完成的。例如: ```sql CREATE SEQUENCE my_sequence; ``` 然后在表创建时,可以将该序列关联为主键的一部分: ```sql CREATE TABLE my_table ( id NUMBER PRIMARY KEY, other_column VARCHAR2(255) ); ``` 在这种情况下,每次插入新行时,Oracle 使用 `my_sequence.nextval` 来为 `id` 字段提供一个新的唯一值。 ### 伪列: 另一种生成唯一主键的方法是利用伪列(pseudo-column)。Oracle 提供了一个内置的伪列 `ROWID` 和 `ROW_NUMBER()` 函数,它们可以在插入新行时动态地生成唯一的行标识符。然而,这些方法主要用于查询操作,并非直接作为插入操作的主键生成手段。 ### 实现自动主键: 为了确保在插入数据时能够自动获得唯一的主键值,您可以按照上述方法设置序列或使用其他数据库提供的机制。一旦确定了主键的自动生成方式,只需在创建表时指明主键列即可,Oracle 将负责处理后续的唯一性检查和自动赋值过程。 ### 相关问题: 1. **如何在 Oracle 中创建并管理序列?** - 创建序列:`CREATE SEQUENCE sequence_name;` - 初始化序列:`ALTER SEQUENCE sequence_name RESTART WITH new_value;` - 删除序列:`DROP SEQUENCE sequence_name;` 2. **如何使用 Oracle 的 ROWID 列进行自动主键生成?** 虽然 `ROWID` 主要用于索引和查询性能优化,而非常规的自动主键生成,但在某些场景下可能会被用来间接实现这一功能。 3. **何时应该避免使用 Oracle 自动生成主键?** - 当需要控制主键生成顺序、范围等特性时,应考虑手动设置或使用其他定制化的解决方案。 - 如果应用程序有特定的需求,如基于业务规则生成的编号系统,自动主键可能无法满足需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值