之前对于oracle的包不太熟悉,最近深入学习了plsql中的包。在做项目过程中,操作数据库时,存在大量重复的工作,正好写个package来巩固下所学。

一.先对写的东西碰到的问题作下说明,也方便以后自己回顾解决问题的过程:

1.如何给存储过程或函数传递数组参数

https://blog.csdn.net/zzkongfu/article/details/7480958

https://blog.csdn.net/wonder4/article/details/649869

2.如果直接运行创建sequence的语句可以正常运行,用的也是dba权限,但是在存储过程、函数、包中写的创建sequence的语句运行后却提示没有权限

https://blog.csdn.net/jerryitgo/article/details/79220598

http://www.cnblogs.com/yhoralce/p/6817010.html?utm_source=itdadao&utm_medium=referral

3.如何给序列做回退操作

(1)网上有说无法回退,只能删掉重新创建;

(2)其实还有别的方法,可以利用sequence本身的increment值来处理

https://blog.csdn.net/u010999809/article/details/79943924 这个说的是将数据库里的所有序列统一回退某个值(比如统一减少100)

https://blog.csdn.net/pete_emperor/article/details/82853277 这个说的是将数据库里某个序列恢复至指定值

下面写的是第二个链接的情况(借鉴的也是第二种。这两个链接实现效果不同,但原理都是一样的,都利用了sequence本身的increment值来处理)

二.接下来,直接上代码:

create or replace package myutil_pkg authid current_user as

  --定义通用的字符串数组参数类型(传入或返回参数)
  type tab_str is table of varchar2(30);

  /**
  * 将序列的当前值恢复至指定数字
  * seqName 序列名称
  * num 需要恢复到哪个数字
  **/
  --使用示例:
  /**
  * begin
  *   myutil_pkg.updateSeqToNum('seq_mytest',1);
  * end;
  *
  * 运行select seq_mytest.currval from dual;可以进行验证
  */
  procedure updateSeqToNum(seqName varchar2, num number);

  /**
  * 批量创建序列
  * seqNames 序列名称数组
  **/
  --使用示例:
  /*
  declare
    seqNames myutil_pkg.tab_str:=myutil_pkg.tab_str(null);
  begin
    seqNames.extend(2,1);
    seqNames(1):='seq_mytest1';
    seqNames(2):='seq_mytest2';
    seqNames(3):='seq_mytest3';
    myutil_pkg.createSeqs(seqNames);
  end;
  */
  procedure createSeqs(seqNames tab_str);

  /**
  * 批量删除序列
  * seqNames 序列名称数组
  **/
  --使用示例:
  /*
  declare
    seqNames myutil_pkg.tab_str:=myutil_pkg.tab_str(null);
  begin
    seqNames.extend(2,1);
    seqNames(1):='seq_mytest1';
    seqNames(2):='seq_mytest2';
    seqNames(3):='seq_mytest3';
    myutil_pkg.dropSeqs(seqNames);
  end;
  */
  procedure dropSeqs(seqNames tab_str);

end myutil_pkg;
create or replace package body myutil_pkg as

  /**
  * 将序列的当前值恢复至指定数字
  * seqName 序列名称
  * num 需要恢复到哪个数字
  **/
  procedure updateSeqToNum(seqName varchar2, num number) as
    n number;
    comm_exception exception;
  begin
    if num < 1 then
      raise comm_exception;
    else
      --https://blog.csdn.net/u010999809/article/details/79943924
      --https://blog.csdn.net/pete_emperor/article/details/82853277
      --获取序列的下一个值
      execute immediate 'select '||seqName||'.nextval from dual' into n;

      --修改序列的minvalue参数
      execute immediate 'alter sequence '||seqName||' minvalue 1';

      if n>1 then
        n:=-(n-num); --这里是要恢复到num(num>=1)
        --修改increment参数
        execute immediate 'alter sequence '||seqName||' increment by '||n;
        execute immediate 'select '||seqName||'.nextval from dual' into n;

        --恢复increment参数值
        execute immediate 'alter sequence '||seqName||' increment by 1';
      end if;
    end if;
  exception
    when comm_exception then
      raise_application_error(-20001,'序列数字不能小于1');

  end updateSeqToNum;

  /**
  * 批量创建序列
  * seqNames 序列名称数组
  **/
  procedure createSeqs(seqNames tab_str) as
  begin
    --https://blog.csdn.net/zzkongfu/article/details/7480958
    --https://blog.csdn.net/wonder4/article/details/649869
    --提示权限不足
    --https://blog.csdn.net/jerryitgo/article/details/79220598
    --http://www.cnblogs.com/yhoralce/p/6817010.html?utm_source=itdadao&utm_medium=referral
    --循环table中的数据
    for i in 1 .. seqNames.count loop
      --如果存放的不是空字符串,则拼接语句执行创建序列
      if seqNames(i) is not null then
        --dbms_output.put_line('++++++'||seqNames(i));
        execute immediate 'create sequence '||seqNames(i)||' '||
        'minvalue 1 start with 1 '||
        'increment by 1 cache 20';
      end if;
    end loop;
  end createSeqs;

  /**
  * 批量删除序列
  * seqNames 序列名称数组
  **/
  procedure dropSeqs(seqNames tab_str) as
  begin
    for i in 1 .. seqNames.count loop
      if seqNames(i) is not null then
        execute immediate 'drop sequence '||seqNames(i);
      end if;
    end loop;
  end dropSeqs;
end myutil_pkg;
01-16 11:27