基于ORACLE数据库的循环建表及循环创建存储过程的SQL语句实现

简介: 一、概述 在实际的软件开发项目中,我们经常会遇到需要创建多个相同类型的数据库表或存储过程的时候。

一、概述
在实际的软件开发项目中,我们经常会遇到需要创建多个相同类型的数据库表或存储过程的时候。例如,如果按照身份证号码的尾号来分表,那么就需要创建10个用户信息表,尾号相同的用户信息放在同一个表中。
对于类型相同的多个表,我们可以逐个建立,也可以采用循环的方法来建立。与之相对应的,可以用一个存储过程实现对所有表的操作,也可以循环建立存储过程,每个存储过程实现对某个特定表的操作。
本文中,我们建立10个员工信息表,每个表中包含员工工号(8位)和年龄字段,以工号的最后一位来分表。同时,我们建立存储过程实现对员工信息的插入。本文中的SQL语句基于ORACLE数据库实现。

二、一般的实现方式
在该实现方式中,我们逐个建立员工信息表,并在一个存储过程实现对所有表的操作。具体SQL语句如下:
建表语句:

-- tb_employeeinfo0
begin
    execute immediate 'drop table tb_employeeinfo0 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo0
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo0 on tb_employeeinfo0(employeeno);

prompt 'create table tb_employeeinfo0 ok';
commit;

-- tb_employeeinfo1
begin
    execute immediate 'drop table tb_employeeinfo1 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo1
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo1 on tb_employeeinfo1(employeeno);

prompt 'create table tb_employeeinfo1 ok';
commit;

-- tb_employeeinfo2
begin
    execute immediate 'drop table tb_employeeinfo2 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo2
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo2 on tb_employeeinfo2(employeeno);

prompt 'create table tb_employeeinfo2 ok';
commit;

-- tb_employeeinfo3
begin
    execute immediate 'drop table tb_employeeinfo3 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo3
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo3 on tb_employeeinfo3(employeeno);

prompt 'create table tb_employeeinfo3 ok';
commit;

-- tb_employeeinfo4
begin
    execute immediate 'drop table tb_employeeinfo4 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo4
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo4 on tb_employeeinfo4(employeeno);

prompt 'create table tb_employeeinfo4 ok';
commit;

-- tb_employeeinfo5
begin
    execute immediate 'drop table tb_employeeinfo5 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo5
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo5 on tb_employeeinfo5(employeeno);

prompt 'create table tb_employeeinfo5 ok';
commit;

-- tb_employeeinfo6
begin
    execute immediate 'drop table tb_employeeinfo6 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo6
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo6 on tb_employeeinfo6(employeeno);

prompt 'create table tb_employeeinfo6 ok';
commit;

-- tb_employeeinfo7
begin
    execute immediate 'drop table tb_employeeinfo7 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo7
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo7 on tb_employeeinfo7(employeeno);

prompt 'create table tb_employeeinfo7 ok';
commit;

-- tb_employeeinfo8
begin
    execute immediate 'drop table tb_employeeinfo8 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo8
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo8 on tb_employeeinfo8(employeeno);

prompt 'create table tb_employeeinfo8 ok';
commit;

-- tb_employeeinfo9
begin
    execute immediate 'drop table tb_employeeinfo9 cascade constraints';
    exception when others then commit;
end;

/
create table tb_employeeinfo9
(
    employeeno      varchar2(10)  not null,         -- employee number
    employeeage     int           not null          -- employee age
);
create unique index idx1_tb_employeeinfo9 on tb_employeeinfo9(employeeno);

prompt 'create table tb_employeeinfo9 ok';
commit;

存储过程创建语句:

create or replace procedure pr_insertdata
(
    v_employeeno   in   varchar2,
    v_employeeage  in   int
)
as 
    v_employeecnt     int;
    v_tableindex      varchar2(2);

begin
    v_tableindex     := substr(v_employeeno, length(v_employeeno), 1);

    if v_tableindex = '0' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo0 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo0(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '1' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo1 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo1(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '2' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo2 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo2(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '3' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo3 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo3(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '4' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo4 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo4(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '5' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo5 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo5(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '6' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo6 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo6(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '7' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo7 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo7(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '8' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo8 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo8(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    elsif v_tableindex = '9' then
    begin
        select count(*) into v_employeecnt from tb_employeeinfo9 where employeeno = v_employeeno;
        if v_employeecnt > 0 then       -- the employeeno is already in DB
        begin
            return;
        end;
        else                            -- the employeeno is not in DB
        begin
            insert into tb_employeeinfo9(employeeno, employeeage) values(v_employeeno, v_employeeage);
        end;
        end if;
    end;
    end if;
    commit;

exception when others then
    begin
        rollback;
        return;
    end;
end;
/
prompt 'create procedure pr_insertdata ok'

三、循环创建的实现方式
在该实现方式中,我们采用循环的方法建立员工信息表及存储过程。具体SQL语句如下:
建表语句:

-- tb_employeeinfo0~9
begin
     declare i int;tmpcount int;tbname varchar2(50);strsql varchar2(1000);
     begin
         i:=0;
         while i<10 loop
         begin
             tbname := 'tb_employeeinfo'||to_char(i);
             i := i+1;

             select count(1) into tmpcount from user_tables where table_name = Upper(tbname);
             if tmpcount>0 then
             begin
                 execute immediate 'drop table '||tbname;
             commit;
             end;
             end if;
             strsql := 'create table '||tbname||
             '(
                  employeeno      varchar2(10)  not null,         -- employee number
                  employeeage     int           not null          -- employee age
              )';
             execute immediate strsql;   
             strsql := 'begin 
                  execute immediate ''drop index idx1_'||tbname || ' '''
                  || ';exception when others then null;
                  end;';
             execute immediate strsql;

             execute immediate 'create unique index idx1_'||tbname||' on '||tbname||'(employeeno)';

         end;
         end loop;
     end;
end;
/

存储过程创建语句:

begin
    declare v_i int;v_procname varchar(50);v_employeeinfotbl varchar(50);strsql varchar(4000);
begin
    v_i := 0;
    while v_i < 10 loop
        v_procname        := 'pr_insertdata'||substr(to_char(v_i),1,1);
        v_employeeinfotbl := 'tb_employeeinfo'||substr(to_char(v_i),1,1);

        v_i := v_i + 1;
        strsql := 'create or replace procedure '||v_procname||'(
            v_employeeno   in   varchar2,
            v_employeeage  in   int
        )
        as
            v_employeecnt     int;

        begin       
            select count(*) into v_employeecnt from '||v_employeeinfotbl||' where employeeno = v_employeeno;
            if v_employeecnt > 0 then       -- the employeeno is already in DB
            begin
                return;
            end;
            else                            -- the employeeno is not in DB
            begin
                insert into '||v_employeeinfotbl||'(employeeno, employeeage) values(v_employeeno, v_employeeage);
            end;
            end if;
            commit;
        exception when others then
            begin
                rollback;
                return;
            end;
        end;';
        execute immediate strsql;
    end loop;
    end;
end;
/

四、总结
当相同类型的表的个数较多时(如有上百个),显然用循环创建的实现方式可以节约大量的工作时间,提高工作效率。但是,在使用该方法的时候,要特别仔细,尤其要注意单引号的使用,避免为了省事而引入代码逻辑问题。


本人微信公众号:zhouzxi,请扫描以下二维码:
这里写图片描述

目录
相关文章
|
3月前
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第18天】SQL Server 存储过程具有提高性能、增强安全性、代码复用和易于维护等优点。它可以减少编译时间和网络传输开销,通过权限控制和参数验证提升安全性,支持代码共享和复用,并且便于维护和版本管理。然而,存储过程也存在可移植性差、开发和调试复杂、版本管理问题、性能调优困难和依赖数据库服务器等缺点。使用时需根据具体需求权衡利弊。
|
3天前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
43 6
|
8天前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
106 11
|
1月前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
75 11
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
SQL 监控 安全
SQL Servers审核提高数据库安全性
SQL Server审核是一种追踪和审查SQL Server上所有活动的机制,旨在检测潜在威胁和漏洞,监控服务器设置的更改。审核日志记录安全问题和数据泄露的详细信息,帮助管理员追踪数据库中的特定活动,确保数据安全和合规性。SQL Server审核分为服务器级和数据库级,涵盖登录、配置变更和数据操作等事件。审核工具如EventLog Analyzer提供实时监控和即时告警,帮助快速响应安全事件。
|
2月前
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
43 2
|
2月前
|
SQL Java 数据库连接
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
|
3月前
|
存储 SQL 缓存
SQL Server存储过程的优缺点
【10月更文挑战第22天】存储过程具有代码复用性高、性能优化、增强数据安全性、提高可维护性和减少网络流量等优点,但也存在调试困难、移植性差、增加数据库服务器负载和版本控制复杂等缺点。
183 1
|
3月前
|
存储 SQL 数据库
Sql Server 存储过程怎么找 存储过程内容
Sql Server 存储过程怎么找 存储过程内容
237 1

推荐镜像

更多