• 在oracle中使用基表建立月表的存储过程


    某些系统需要按月分表来保存数据。下面的存储过程演示了如何使用基表来建立每个月的月表。
    处理思路是:
        1:首先,为基表建立好表和对应的索引。
        2:将基表保存到一个存储过程需要的表中。
        3:存储过程读取配置表,根据配置表中的名字,去数据库中查询对应的表的建表语句,然后,用月表的表名去替换语句中的表名,接着就建表。再去查询基表的表是不是有索引,如果有,则从数据库中得到索引的建表语句,然后,替换建表语句中的索引名称和表名称,最后执行建立索引的语句。
     
    -- oracle环境的sql
    -- 基础表准备
    drop table base_config_monthly_table;
    create table base_config_monthly_table
    (
    base_table_name varchar2(50),
    valid_flag number(1) default 1,
    remark varchar2(1000)
    );
    
    select * from base_config_monthly_table ;
    insert into base_config_monthly_table(base_table_name,valid_flag,remark)
    select 'aa_wanglc_test',1,'王路长提供的样例' from dual;
    commit;
    
    -- 待用函数的测试
    SELECT REPLACE( '15800003367', substr('1580003367',4,4), '****') from dual;
    select instr('abcdef','d') from dual;
    select length('abdf') from dual;
    select to_char(add_months(trunc(sysdate),-1),'yyyy') from dual;
    select to_char(1,'fm00') from dual;
    
    CREATE TABLE aa_wanglc_test AS SELECT * FROM dual;
    SELECT * FROM aa_wanglc_test;
    CREATE INDEX idx_wt_d009091 ON aa_wanglc_test(dummy);
    
    -- 通过基表建立月表,且通过基表的索引建立月表的索引
    CREATE OR REPLACE procedure proc_create_monthly_tables
     AUTHID CURRENT_USER IS
    v_base_monthly_table base_config_monthly_table%rowtype; -- 配置表
    v_base_ddl varchar2(4000); -- 保存基表的sql
    v_sql varchar2(4000);   -- 最终需要使用的sql
    v_new_tableName varchar2(50);   -- 月表的表名
    v_yyyy varchar2(10);    --月表的年变量
    v_month number := 0;    --月表的月变量
    v_current_month varchar2(10);   -- 月份的循环变量
    v_exists_flag number := 0;
    v_base_table_name_upper varchar2(50);   -- 大写格式的基表名字
    
    cursor v_cur_get_basetable is
    select * from base_config_monthly_table where valid_flag = 1;
    
    type cur_get_index is ref cursor; --声明一个动态游标类型,因为游标不是类型所以要声明一个动态游标类型,需要查询每个基表的索引
    v_cur_get_index cur_get_index;  --声明一个动态游标变量
    
    v_index_ddl varchar2(4000); -- 建立索引的sql
    v_index_name_str varchar2(30);
    v_index_name_num NUMBER;
    v_index_name varchar2(30);
    v_old_index_name varchar2(30);
    
    begin
        open v_cur_get_basetable;
        loop
            fetch v_cur_get_basetable
                into v_base_monthly_table;
            exit when v_cur_get_basetable%notfound;
    
            select to_char(sysdate,'yyyy') into v_yyyy from dual;
    
            select upper(v_base_monthly_table.base_table_name) into v_base_table_name_upper from dual;
            --dbms_output.put_line(v_base_table_name_upper);
            v_exists_flag := 0;
            select count(*) into v_exists_flag from  user_tables where table_name = v_base_table_name_upper ;
    
            -- 如果基表不存在,则不处理这条配置记录
            if v_exists_flag = 0 then
                continue;
            end if;
    
            -- 在数据库系统取得基表的建表语句
            SELECT DBMS_METADATA.GET_DDL('TABLE', v_base_table_name_upper)
            into v_base_ddl
            from dual;
    
            --dbms_output.put_line(v_base_ddl);
            v_month := 0;
    
            loop
                v_month := v_month +1;
                exit when v_month > 12;
                select to_char(v_month,'fm00') into v_current_month from dual;
                v_new_tableName := v_base_table_name_upper||'_'||v_yyyy||v_current_month;
                -- dbms_output.put_line(v_new_tableName);
    
                v_exists_flag := 0;
                select count(*) into v_exists_flag from  user_tables where table_name = upper(v_new_tableName)
                or table_name = '"'||v_new_tableName||'"';
    
                -- dbms_output.put_line(v_exists_flag);
                -- 如果月表已经创建,则不再创建
                if v_exists_flag > 0 then
                    continue;
                end if;
    
                -- 用月表的表名来替换建表语句中的基表表名
                SELECT REPLACE(v_base_ddl,
                    v_base_table_name_upper,
                    v_new_tableName)
                into v_sql
                from dual;
    
                --dbms_output.put_line(v_sql);
                execute IMMEDIATE v_sql;
    
                -- 查找索引
                v_sql := 'SELECT DBMS_METADATA.GET_DDL('''||CHR(73)||'NDEX'', index_name),index_name
                        FROM USER_INDEXES WHERE table_name = '''||v_base_table_name_upper||'''
                        AND UNIQUEness = ''NONUNIQUE''';
                open v_cur_get_index for v_sql;    -- 打开游标,并且SQL执行结果存放到游标
                LOOP
                    fetch v_cur_get_index into v_index_ddl,v_old_index_name;
                    exit when v_cur_get_index%notfound;  -- 退出循环
    
                    -- 为索引取一个名字,名字是随机取得
                    SELECT dbms_random.string ('x', 8) INTO v_index_name_str FROM dual;
                    select trunc(dbms_random.value(0,100000)) INTO v_index_name_num from dual;
                    v_index_name := 'idx_'||v_index_name_str||'_'||to_char(v_index_name_num);
    
                    -- 把建立索引的语句中的索引名字改掉
                    SELECT REPLACE(v_index_ddl,
                        v_old_index_name,
                        v_index_name)
                    into v_sql
                    from dual;
    
                    --dbms_output.put_line(v_sql);
                    -- 把建立索引的语句中的表名改掉
                    SELECT REPLACE(v_sql,
                        v_base_table_name_upper,
                        v_new_tableName)
                    into v_sql
                    from dual;
    
                    --dbms_output.put_line(v_sql);
                    execute IMMEDIATE v_sql;
    
                END LOOP; -- 创建索引的动态游标结束
            end loop;
        end loop;
        close v_cur_get_basetable;
    end ;
    
    -- 查看存储过程是不是有错误
    select * from user_errors;
    
    -- 执行存储过程
    begin
    proc_create_monthly_tables;
    end;
    
    -- 查看效果
    SELECT * FROM user_tables WHERE table_name LIKE upper('aa_wanglc_test%');
    SELECT * FROM USER_indexes WHERE table_name LIKE upper('aa_wanglc_test%');
    
    -- 删除测试表的语句
    select 'drop table '|| table_name || ';' from user_tables where table_name like upper('aa_wanglc_test%');

    结果说明
        这个存储过程可以通过一个表来建其他表,并且能建立源表的主键和索引等对象。
  • 相关阅读:
    聊一聊所谓的B端C化
    NetCore3.1IIS其他网站出现HTTP503无法访问解决办法
    技术方案模板 fn
    技术方案模板
    composer的常用操作(composer 2.2.1)
    thinkphp6: 用validate验证参数合法性(thinkphp 6.0.9/php 8.0.14)
    thinkphp6: 从6.0.9升级(php 8.0.14)到 6.0.10lts版本(php 8.1.1)
    thinkphp6: 自定义配置文件(php 8.1.1 / thinkphp v6.0.10LTS)
    linux(ubuntu21.10):为chrome安装jsonvue(chrome 96)
    thinkphp6:mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
  • 原文地址:https://www.cnblogs.com/babyha/p/11596902.html
Copyright © 2020-2023  润新知