使用动态sql解决在同一张表格中输出不同字段

场景再现:

需求要求我们在table1中取到墓位定金和墓位成交额,然后再table2中取到墓位的管理费以及一些连带费用,但是两个表没有唯一的关联关系,故我们采用在求墓位定金、墓位成交额的的存储过程中嵌入存储函数的方式进行实现;

那么问题来了,因为我们要取得字段偏多,我们不可能新建十几个存储函数去单独取各个字段,于是,我们就可以使用动态SQL来解决这一问题;

动态sql

oracle编译PL/SQL程序块分为两种,其一为前期联编(early binding),即SQL语句在编译期间就已经确定;另一种为后期联编(late binding),即SQL语句只有在运行阶段才能建立;静态SQL采用的是前期联编,动态SQL采用的是后期联编;
2、动态SQL是一种“不确定”的SQL,这里ORACLE提供了Execute immediate语句来执行动态SQL,语法如下:Excute immediate 动态SQL语句 using 绑定参数列表 returning into 输出参数列表;
实例:根据特定ID可以查询到其姓名和薪水的信息

create or replace procedure find_info(p_id number)
as v_name varchar2(10);
v_salary number;
begin
execute immediate 'select name,salary from emp where id=:1'
using p_id
return into v_name,v_salary;--这里的动态SQL为查询语句
dbms_output.put_line(v_name ||'的收入为:'||to_char(v_salary));
exception
when others then
dbms_output.put_line('找不到相应数据')end find_info;

注意:这里的动态SQL语句使用了占位符“:1“,其实它相当于函数的形式参数,使用”:“作为前缀,然后使用using语句将p_id在运行时刻将:1给替换掉,这里p_id相当于函数里的实参。

实例二:根据大于特定的薪水的查询相应的员工信息

create or replace procedure find_emp(p_salary number)as
r_emp emp%rowtype;
type c_type is ref cursor;--声明游标
c1 c_type;--定义游标
begin
open c1 for --打开游标
'select * from emp where salary >:1'
using p_salary;
loop --开启循环输出员工薪水大于入参p_salary的
fetch c1 into r_emp;
exit when c1%notfound;
dbms_output.put_line('薪水大于‘||to_char(p_salary)||’的员工为:‘);
dbms_output.put_line('ID为'to_char(r_emp)||' 其姓名为:'||r_emp.name);
end loop;
close c1;
end find_emp;

注意:打开的游标为动态游标,它也属于动态SQL的范畴,其整个编译和开发的过程与execute immediate执行的过程很类似,这里就不在赘述了

本案例实现:
首先,我们创建个通过传入userId和字段名动态获取字段值的存储函数

create or replace function GET_SUMFY(TMPNAME VARCHAR2,QSYRID VARCHAR2) return VARCHAR is
  CONVERT_AMOUNT VARCHAR2(300);
  SQLSTR  VARCHAR2(1000);
begin
  SQLSTR :='SELECT SUM('||TMPNAME||') FROM my_jf_record T WHERE T.MY_USER_ID='''||QSYRID||''' ';
  EXECUTE IMMEDIATE SQLSTR INTO CONVERT_AMOUNT;
  return CONVERT_AMOUNT;
end GET_SUMFY;

其次,我们在之前的存储过程中直接调用该存储函数,通过传入参数来获取字段值;

 					NVL(GET_SUMFY('GL_F', X.ID), 0) GL_F,
                     NVL(GET_SUMFY('KZ_F', X.ID), 0) KZ_F,
                     NVL(GET_SUMFY('TJ_F', X.ID), 0) TJ_F,
                     NVL(GET_SUMFY('CL_F', X.ID), 0) CL_F,
                     NVL(GET_SUMFY('ZAZ_F', X.ID), 0) ZAZ_F,
                     NVL(GET_SUMFY('KFZ_F', X.ID), 0) KFZ_F,
                     NVL(GET_SUMFY('ZP_F1', X.ID), 0) ZP_F1,
                     NVL(GET_SUMFY('ZP_F2', X.ID), 0) ZP_F2,
                     NVL(GET_SUMFY('ZP_F3', X.ID), 0) ZP_F3,
                     NVL(GET_SUMFY('KF_F', X.ID), 0) KF_F,
                     NVL(GET_SUMFY('QT_F', X.ID), 0) QT_F,
                     NVL(GET_SUMFY('YJ_F', X.ID), 0) YJ_F,
                     NVL(GET_SUMFY('SJ_F', X.ID), 0) SJ_F,
                     NVL(GET_SUMFY('QF_F', X.ID), 0) QF_F

大功告成!

原文连接:https://www.cnblogs.com/AaronBear/p/11049917.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值