#分割字符串
create or replace procedure sp_string(v_string in varchar2)
 as
  /*author:xuguoqi
  time:  2018-12-10
  usage: 输入一个以逗号分割的字符串,输出分割后的结果 如 输入:aa,bb,cc
                                                        输出:aa
                                                             bb
                                                             cc
                                                       
  */
  v_array dbms_utility.lname_array;
  v_tab binary_integer;
  v_list varchar(100):=v_string;
  valid_string exception;
  begin
   if instr(v_list,\',\')<=0 then 
     raise valid_string;
   else  
     dbms_utility.comma_to_table(list=>v_list,tab=>v_array,tablen=>v_tab);
      for i in 1..v_tab loop
        dbms_output.put_line(v_array(i));
       end loop;
   end if;
   exception 
           when valid_string then 
              dbms_output.put_line(\'只能以逗号作为分隔符,如 aa,bb,cc,dd\');
           when others then 
              dbms_output.put_line(sqlerrm);
  end;
  


#util_file包的使用

create or replace directory dir2 as \'/home/oracle/utlfile\';
grant read,write on directory dir2 to scott;
grant execute on utl_file to scott;



create or replace procedure utl_file_use(v_str in varchar2,v_filename in varchar2)
as
/*author:xuguoqi
  time:  2018-12-10
  usage: 输入一个sql语句,在服务器上面生成一个文件
  */
 file_type utl_file.file_type;               --定义file_type
 v_dir_name varchar2(100) default \'DIR2\';    --dirname
 v_check_dir varchar2(20);                   --检查dir的是否存在
 invalid_directory exception;                --定义异常
 file_name varchar2(100):=to_char( current_timestamp,\'yyyymmddhh24miss\');         --定义filename为时间.txt
 type v_recoed is table of varchar(4000);    --定义一个table type
 v_rc v_recoed;
 v_cur sys_refcursor;                        --声明一个游标
begin
     select nvl(DIRECTORY_NAME,\'0\') into v_check_dir from dba_directories where DIRECTORY_NAME=v_dir_name;
     if v_check_dir=\'0\' then
       raise invalid_directory;
     else
         file_name :=file_name||\'_ \'||v_filename||\'.txt\';
        
         file_type :=utl_file.fopen(v_dir_name,file_name,\'W\',1000);         
                open v_cur for v_str;
                loop 
                  exit when v_cur%notfound;
                   fetch v_cur bulk collect into v_rc;
                    for i in v_rc.first..v_rc.last loop                                                    
                             utl_file.put_line(file_type,v_rc(i));
                    end loop;
                end loop; 
                close v_cur;         
     end if;
     utl_file.fflush(file_type);
     utl_file.fclose(file_type);
    exception 
             when invalid_directory then
                  dbms_output.put_line(\'检查输入的directory是否存在或者是否授予访问 读写权限\');
             when others then
                  dbms_output.put_line(sqlerrm);
end;


运行结果:
[oracle@oracle utlfile]$ more 20181130113724_emp.txt
7369,SMITH,CLERK
7499,ALLEN,SALESMAN
7521,WARD,SALESMAN
7566,JONES,MANAGER
7654,MARTIN,SALESMAN
7698,BLAKE,MANAGER
7782,CLARK,MANAGER
7839,KING,PRESIDENT
7844,TURNER,SALESMAN
7876,ADAMS,CLERK
7900,JAMES,CLERK
7902,FORD,ANALYST
7934,MILLER,CLERK



create or replace type str is table of varchar(50);
/


CREATE OR REPLACE FUNCTION random_strings (v_number IN INTEGER

)
/*author:xuguoqi
  生成长度为10的随机字符串
*/
   RETURN str
   AUTHID CURRENT_USER
IS
    string str := str();
BEGIN
    string.EXTEND (v_number);

   FOR indx IN 1 .. v_number
   LOOP
      string(indx) := DBMS_RANDOM.string (\'u\', 10);
   END LOOP;

   RETURN string;
END;



#把查询结果转换为列名
create table ass(acptnum varchar(30),qu_name varchar(4000),awname varchar(2000));


insert into ass values(\'15101232097\',\'问题1\',\'答案1\');
insert into ass values(\'15101232097\',\'问题2\',\'答案2\');
insert into ass values(\'15101232097\',\'问题3\',\'答案3\');
insert into ass values(\'18290890601\',\'x\',\'x\');
insert into ass values(\'18290890601\',\'x1\',\'x2\');
insert into ass values(\'18290890601\',\'x2\',\'x2\');
insert into ass values(\'18290890601\',\'x3\',\'x3\');

select * from ass;
  acptnum     qu_name   awname                  
1	15101232097	问题1	    答案1
2	15101232097	问题2	    答案2
3	15101232097	问题3	    答案3
4	18290890601	x	        x
5	18290890601	x1	      x2
6	18290890601	x2	      x2
7	18290890601	x3	      x3


         
create or replace procedure exeute_select(v_out out sys_refcursor)
as
/*把列值转换为列名*/
c1    sys_refcursor;
v_sql VARCHAR(1000):=\'\';
c2 ass.qu_name%type;
BEGIN
       v_sql:=\'select acptnum\';
       open c1 for select distinct qu_name from ass;
       loop
         fetch c1 into c2;
         
         exit when c1%notfound;
         
         v_sql :=v_sql||\',max(case qu_name when  \'\'\'||c2||\'\'\'   then  awname else null end ) as \' ||c2;
         
       end loop;
         close c1;
         
           v_sql :=v_sql|| \' from ass group by acptnum\';
           
           open v_out for v_sql;           
  END;  


#实现效果

address    name   color

北京       苹果   绿色

北京       香蕉   黄色

北京       葡萄   紫色


address     苹果   香蕉  葡萄

北京        绿色   黄色  紫色



#parallel

oracle 批量更新大表:

select task_name,chunk_type,status from dba_parallel_execute_tasks;

grant create job to SCOTT; 
grant execute on dbms_scheduler to SCOTT;
grant execute on dbms_parallel_execute to SCOTT;


CREATE OR REPLACE PROCEDURE PARALLEL_SQL
authid current_user
AS
  l_sql_stmt VARCHAR2(1000);
  l_try NUMBER;
  l_status NUMBER;
  v_start number;
  v_end  number;
  v_task_name varchar2(100):=\'xugq\';
  v_table_owner varchar2(100) :=\'SCOTT\';
  v_table_name varchar2(100) :=\'LFN_TASK_TEST\';
BEGIN
	/*如果 CREATE_CHUNKS_BY_ROWID 必须写 where rowid between :start_id and :end_id*/
  l_sql_stmt := \'UPDATE /*+ rowid (dda) */ LFN_TASK_TEST SET SAL=18000 where rowid between :start_id and :end_id\';
  v_start :=dbms_utility.get_time;
  DBMS_PARALLEL_EXECUTE.CREATE_TASK (v_task_name);
  DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID(v_task_name,v_table_owner,v_table_name, true, 100);
  
  DBMS_PARALLEL_EXECUTE.RUN_TASK(v_task_name,l_sql_stmt,DBMS_SQL.NATIVE,parallel_level => 1);
  l_try := 0;
  l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS(v_task_name);
  WHILE(l_try < 2 and (l_status != DBMS_PARALLEL_EXECUTE.FINISHED)) 
  LOOP
    l_try := l_try + 1;
    DBMS_PARALLEL_EXECUTE.RESUME_TASK(v_task_name);
    l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS(v_task_name);
  END LOOP;
  DBMS_PARALLEL_EXECUTE.DROP_TASK(v_task_name);
  v_end :=dbms_utility.get_time;
  DBMS_OUTPUT.PUT_LINE(\'执行时间:\'||to_char(v_end-v_start));  
  commit;
        exception
                when others then
                     DBMS_PARALLEL_EXECUTE.DROP_TASK(v_task_name);
                     DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;



#建立job 执行job 删除job 停止job.


create or replace package action_job
as
 procedure create_job;
 procedure run_job(v_job_name in number);
 procedure drop_job(v_job in number);
 procedure stop_job(v_stop_num_job number);
 procedure select_info_job(v_out out sys_refcursor);
end;

create or replace package body action_job
as
  /*新建一个Job*/
  procedure create_job
    is
       v_job_num number;               --定义job号
       v_what varchar2(150):=\'utl_file_use\';              --要执行的sp或者函数
       v_next_date varchar2(100):=\'2018-12-12 18:00:00\';  --第一次执行的时间
       v_interval  varchar2(100):=\'sysdate+1/24\';  --执行时间间隔
       /*example interval=sysdate+1/24         每隔一小时
                 interval=sysdate+1/(24*60*60) 每秒钟运行一次
                 interval=sysdate+1/(24*60)    每分钟运行一次
                 interval=last_day(sysdate)+1+1/24 没月凌晨一点执行
                 interval=trunc(next_day(sysdate,\'Mon\'))+1/24
       
       */
       begin
           dbms_job.submit(job=>v_job_num,
                           what=>v_what||\';\',
                           next_date => to_date(v_next_date,\'yyyy-mm-dd hh24:mi:ss\'),
                           interval=>v_interval
                           );
       dbms_output.put_line(\'the job number is:\'||v_job_num);
       end;
   /*删除Job*/
   procedure drop_job(v_job in number)
      is
      drop_num number:=v_job;     
      begin
         dbms_job.remove(drop_num);
         dbms_output.put_line(\'job\'||drop_num||\'has been deleted\');
         exception 
                  when others then
                    dbms_output.put_line(\'please input a validate job number\');
      end;
    /*运行Job*/  
    procedure run_job(v_job_name in number)
      is
      begin
           dbms_job.run(v_job_name);
           exception 
                   when others then
                     dbms_output.put_line(sqlerrm);
      end;  
    /*停止Job*/
    procedure stop_job(v_stop_num_job number)
      is
      v_broken boolean:=True;
      begin
           dbms_job.broken(v_stop_num_job,broken => v_broken);
             exception
                      when others then
                        dbms_output.put_line(sqlerrm);
      end;
      
      /*查询job相关信息*/
      procedure select_info_job(v_out out sys_refcursor)
        is 
          begin
               open v_out for select * from user_jobs;
          end;
          
                       
end action_job;



Oracle with字句:
with e as (select * from emp),
     d as (select * from dept)
 select e.ename,d.dname from e,d 
  where e.empno=7369 and d.deptno=20;


ENAME      DNAME
---------- --------------
SMITH      RESEARCH


with t(a,b) as (select 1,2 from dual)
select t.a from t;


#



declare
  type c1 is table of indeic_test.name%type index by pls_integer;
  c2 c1;
 begin
 	   c2(1):=\'lfn\';
 	   c2(10):=\'xugq\';
 	   forall i_index in indices of c2
 	       update indeic_test set num=12
 	       where name=c2(i_index);
 	   dbms_output.put_line(sql%rowcount);
 end;
 /

SCOTT@PROD>select * from indeic_test;

NAME              NUM
---------- ----------
lfn                12
xugq               12
bei               500
shen              900


declare
  type c1 is table of indeic_test.name%type index by pls_integer;
  c2 c1;
  type c3 is table of boolean index by pls_integer;
  c4 c3;
 begin
 	   c2(1):=\'lfn\';
 	   c2(10):=\'xugq\';
 	   c2(12):=\'null\';
 	   c4(1) :=FALSE;
 	   c4(10):=TRUE;
 	   c4(12):=null;
 	   forall i_index in indices of c4 between 1 and 30
 	       update indeic_test set num=18
 	       where name=c2(i_index);
 	   dbms_output.put_line(sql%rowcount);
 end;
 /
 
 
#insert all 
insert all 
  into indeic_test(name,num)
  into indeic_test(name,num)
  select \'ab\',1 from dual;




declare
   type my_table_type is table of integer;
   t1   my_table_type := my_table_type(1,2,3,4);
   t2   my_table_type := my_table_type(2,4,4,5);
   s    integer;
begin
   for i in 1..t1.count loop
      s := t1(i) + t2(i);
      if not mod(s,2)=1 then
         continue;
      end if;
      dbms_output.put_line(t1(i)||\'\'||t2(i));
      dbms_output.put_line(s);
   end loop;
end;
/

 

收藏 打印