公司的oracle服务器上有多个用户,每个用户有一些相同的表。由于表的数据量比较大,这些表每月都要增加表空间和表分区。为了方便处理,就写了一个计划任务自动处理分区和空间。
添加/删除表分区需要相应的权限 我们知道,用户拥有的role权限在存储过程是不可用的。遇到这种情况,我们一般需要显式授权,如grant create table to usera;但这种方法太麻烦,有时候可能需要进行非常多的授权才能执行存储过程,实际上,oracle给我们提供了在存储过程中使用role权限的方法:修改存储过程,加入Authid Current_User时存储过程可以使用role权限
1 -- 自动管理分区程序 2 create or replace procedure auto_operation_partition_proc(schema varchar2, 3 v_table_1 in varchar2, 4 is_del number default 0) 5 authid current_user as 6 -- 为一个用户下所有分区表自动增加分区
-- 分区的列为date类型,分区名类似 7 -- DATA_LOGOUT_042012_NAME DATA_LOGIN_042012_NAME 8 -- schema 名称 9 -- v_table_1 包含表名的字符串 如 table1,table2,table3... 10 -- is_del 是否删除表空间和表分区 11 v_table_name varchar2(50); --表名 12 v_max_partition_name varchar2(50); -- 分区名称 13 v_max_tablespace_name varchar2(50); -- 表空间名称 14 v_min_partition_name varchar2(50); -- 分区名称 15 v_min_tablespace_name varchar2(50); -- 表空间名称 16 v_add_month_1 char(6); --添加分区月 17 v_add_month_2 char(6); --分区格式 18 v_add_month varchar2(20); -- 19 v_partition_year varchar2(10); --分区年 20 v_partition_month varchar2(10); --分区月份 21 v_partition_all varchar2(10); -- 分区时间 22 v_partition_game varchar2(10); -- 游戏名称 23 v_partition_pre varchar2(20); -- 分区前缀 24 v_tablespace_pre varchar2(20); -- 分区前缀 25 v_drop_partition varchar2(1000) := ''; 26 v_drop_tablespace varchar2(1000) := ''; 27 v_add_tablespace varchar2(1000); 28 v_sql_string varchar2(1000); 29 v_tablespace_name varchar2(1000); 30 v_partition_name varchar2(1000); 31 v_total_count number(5); 32 v_schema_pre varchar2(100); 33 v_err_code varchar2(15); 34 v_err_errm varchar2(300); 35 v_sql_txt VARCHAR2(200); 36 cursor cur_part(schema varchar2) is 37 select u.table_name, 38 max(p.partition_name) max_partition_name, 39 max(p.tablespace_name) max_tablespace_name, 40 min(p.partition_name) min_partition_name, 41 min(p.tablespace_name) min_tablespace_name, 42 count(1) 43 from all_tables u, all_tab_partitions p 44 where u.table_name = p.table_name 45 and u.owner = p.table_owner 46 and u.partitioned = 'YES' 47 and u.owner = upper(schema) 48 group by u.table_name, u.owner; 49 begin 50 if substr(trunc(sysdate), 0, 2) >= 28 then 51 v_schema_pre := schema || '.'; 52 select to_char(add_months(sysdate, 1), 'yyyymm') 53 into v_add_month_1 54 from dual; 55 select to_char(add_months(sysdate, 2), 'mmyyyy') 56 into v_add_month_2 57 from dual; 58 select to_char(add_months(trunc(sysdate, 'mm'), 2), 'yyyy-mm-dd') 59 into v_add_month 60 from dual; 61 open cur_part(schema); 62 if cur_part%isopen then 63 loop 64 fetch cur_part 65 into v_table_name, 66 v_max_partition_name, 67 v_max_tablespace_name, 68 v_min_partition_name, 69 v_min_tablespace_name, 70 v_total_count; 71 -- 退出条件 72 exit when cur_part%notfound; 73 -- 判断表名是否在参数字符串中 74 if instr(upper(v_table_1), v_table_name) > 0 then 75 -- 判断表分区和空间条数 76 if v_total_count >= 2 then 77 v_tablespace_pre := substr(v_max_tablespace_name, 78 1, 79 instr(v_max_tablespace_name, '_')); 80 v_partition_pre := substr(v_max_partition_name, 81 1, 82 instr(v_max_partition_name, 83 '_', 84 -1, 85 2)); 86 v_partition_all := substr(v_max_partition_name, 87 instr(v_max_partition_name, 88 '_', 89 -1, 90 2) + 1, 91 6); 92 v_partition_game := substr(v_max_partition_name, 93 instr(v_max_partition_name, '_', -1) + 1); 94 v_partition_month := substr(v_partition_all, 1, 2); 95 v_partition_year := substr(v_partition_all, 3, 4); 96 if to_number(v_partition_year || v_partition_month) <= 97 to_number(substr(v_add_month_1, 1)) then 98 v_tablespace_name := v_tablespace_pre || v_add_month_2 || '_' || 99 v_partition_game; 100 v_partition_name := v_partition_pre || v_add_month_2 || '_' || 101 v_partition_game; 102 if is_del > 0 then 103 -- 删除表分区 104 v_drop_partition := 'alter table ' || v_schema_pre || 105 v_table_name || ' drop partition ' || 106 v_min_partition_name; 107 v_sql_txt := v_drop_partition; 108 --dbms_output.put_line(v_drop_partition); 109 -- 删除表空间 110 v_drop_tablespace := 'drop tablespace ' || 111 v_min_tablespace_name || 112 ' including contents and datafiles'; 113 v_sql_txt := v_drop_tablespace; 114 --dbms_output.put_line(v_drop_tablespace); 115 execute immediate (v_drop_tablespace); 116 execute immediate(v_drop_partition); 117 end if; 118 --添加表空间 119 v_add_tablespace := 'CREATE TABLESPACE ' || v_tablespace_name || 120 ' DATAFILE ''/opt/oracle/oradata/orcl/' || 121 lower(v_partition_game) || '/' || 122 lower(v_tablespace_name) || 123 '.dbf'' 124 SIZE 512M REUSE AUTOEXTEND ON NEXT 8M MINIMUM EXTENT 16M 125 DEFAULT STORAGE (INITIAL 16M NEXT 16M MINEXTENTS 8 MAXEXTENTS 4096)'; 126 v_sql_txt := v_add_tablespace; 127 -- dbms_output.put_line(v_add_tablespace); 128 -- 添加表分区 129 v_sql_string := 'alter table ' || v_schema_pre || 130 v_table_name || ' add partition ' || 131 v_partition_name || 132 ' VALUES LESS THAN ( to_date(''' || 133 v_add_month || 134 ''',''yyyy-mm-dd'') ) tablespace ' || 135 v_tablespace_name; 136 v_sql_txt := v_sql_string; 137 --dbms_output.put_line(v_sql_string); 138 execute immediate v_add_tablespace; 139 execute immediate v_sql_string; 140 else 141 null; 142 end if; 143 end if; 144 else 145 null; 146 end if; 147 end loop; 148 end if; 149 150 close cur_part; 151 end if; 152 exception 153 when others then 154 v_err_code := sqlcode; 155 v_err_errm := substr(sqlerrm, 1, 200); 156 insert into exec_err_info 157 (game_name, 158 table_name, 159 tablespace_name, 160 partition_name, 161 error_codes, 162 error_info, 163 sql_txt, 164 stat_time) 165 values 166 (schema, 167 v_table_name, 168 v_max_tablespace_name, 169 v_max_tablespace_name, 170 v_err_code, 171 v_err_errm, 172 v_sql_txt, 173 sysdate); 174 commit; 175 end;