1. 程式人生 > >oracle 動態SQL在儲存過程中的使用

oracle 動態SQL在儲存過程中的使用

1、      靜態SQL和動態SQL

Oracle編譯PL/SQL程式塊分為兩個種(其它SQL程式碼塊包括儲存過程也是如此):

其一為前期聯編(early binding),即SQL語句在程式編譯期間就已經確定,大多數的編譯情況屬於這種型別;另外一種是後期聯編(late binding),即SQL語句只有在執行階段才能建立,例如當查詢條件為使用者輸入時,那麼Oracle的SQL引擎就無法在編譯期對該程式語句進行確定,只能在使用者輸入一定的查詢條件後才能提交給SQL引擎進行處理。通常,靜態SQL採用前一種編譯方式,而動態SQL採用後一種編譯方式。 

動態SQL的兩種寫法:

(1)    Excute immediate

動態SQL語句 using 繫結引數列表 returning into 輸出引數列表;對這一語句作如下說明:

(2)      v_sqlvarchar2(4000); v_month_name varchar2(10); …… v_sql:=’……’; execute immediatev_sql;

   v_month_name varchar2(10);

   v_sql varchar2(4000);

v_sql:=’insert into tablename(c1,c2,……,cn) select '||v_month_name||', short_name,……from tablename2’;

execute

immediate v_sql;

2、使用動態sql的業務場景

需求是根據傳入的日期,取出年份v_year和月份v_month值,然後根據業務規則來查出對應的承租率返回,然後組成資料錄入到一個新的報表表裡面去;

因為年份欄位有一個,可以用where欄位直接判斷,但是月份資料有12個欄位,而且每次傳入的日期獲取的月份數值不一定一致,所以按照比較笨的辦法是需要if else 連續判斷12次才能囊括所有的月份欄位的,這樣儲存過程就會非常冗餘笨重而且不易閱讀。

所以需要找一個新的辦法來處理,避免做連續12個if else的判斷,這裡可以採用動態sql,也就是自動根據傳入日期來組織去查表中的哪個月份欄位和年份欄位。

3、儲存過程使用動態sql示例

createorreplaceprocedure BIS_PROJECT_BUDGET(P_DATE inDATE) is

   v_date varchar2(10);

   v_year varchar2(10);

   v_month varchar2(10);

   v_month_name varchar2(10);

   v_sql varchar2(4000);

begin

--取當日的上個月的最後一天每個月首日統計上個月

select to_char((last_day(add_months(P_DATE,-1))),'yyyy-mm-dd') last_day ,

         to_char((last_day(add_months(P_DATE,-1))),'yyyy') years,

         to_char((last_day(add_months(P_DATE,-1))),'mm') months

into v_date,v_year,v_month

from dual;

select

casewhen v_month='01'then'bt.JAN_KPI'

when v_month='02'then'bt.FEB_KPI'

when v_month='03'then'bt.MAR_KPI'

when v_month='04'then'bt.APR_KPI'

when v_month='05'then'bt.MAY_KPI'

when v_month='06'then'bt.JUN_KPI'

when v_month='07'then'bt.JUL_KPI'

when v_month='08'then'bt.AUG_KPI'

when v_month='09'then'bt.SEP_KPI'

when v_month='10'then'bt.OCT_KPI'

when v_month='11'then'bt.NOV_KPI'

else'DEC_KPI'endinto v_month_name

from dual;

delete BIS_SECOND_ZS_PRO  where PRO_MONTH=to_number(v_month) and PRO_YEAR = v_year;

commit;

   v_sql:=

     insert into BIS_SECOND_ZS_PRO bp(

        BIS_SECOND_ZS_PRO_ID ,

        bis_project_id,

        PRO_YEAR,

        PRO_MONTH,

        EMPTY_PRE,

        BUDGETYEAR_MONTH,

        CREATOR,

        CREATED_DATE,

        RECORD_VERSION

        )

        select

          sys_guid(),

          m.bis_project_id,

          '||v_year||' as years,

          to_number('||v_month||') as months,

          m.budget_month,

          y.budget_year,

          ''system'',

          sysdate,

          dbms_random.value(0,100000)

        from

        (

        select

          r.bis_project_id,

          nvl(decode(r.total_square,0,0,round(('||v_month_name||' - r.open_square/r.total_square)*r.total_square,2)),0)   budget_month

        from

          (select  pt.bis_project_id,

             pt.short_name,

             pt.total_square,

             nvl(sum(af.open_square_total),0) open_square

           from

              (select p.bis_project_id,

                   p.short_name,

                   nvl(sum(vf.rent_square_total),0) total_square

              from bis_project p left join vw_bis_mall_floor_summary vf on p.bis_project_id = vf.bis_project_id

              where  p.is_business_project = ''1''

                   and p.oper_status = ''2''

              group by p.bis_project_id,p.short_name) pt,

              rep_agg_floor_month af

            where 1 = 1

                and pt.bis_project_id = af.bis_project_id

                and af.store_type = ''1''

                and af.agg_year = '||v_year||'

                and af.agg_month = to_number('||v_month||')

                group by pt.bis_project_id,pt.short_name,pt.total_square) r,

           bis_project_target bt

          where 1=1

              and r.bis_project_id = bt.bis_project_id(+)

      ) m,

      (

      select r.bis_project_id,

             nvl(decode(r.total_square,0,0,round(('||v_month_name||' - r.open_square/r.total_square)*r.total_square,2)),0)+r.off_square   budget_year                                                 

      from

      (select  pt.bis_project_id,

             pt.short_name,

             pt.total_square,

             af.agg_month,

             af.agg_year,

             nvl(sum(af.open_square_total),0) open_square,

             nvl(sum(af.off_square_total),0) off_square

      from

      (select p.bis_project_id,

             p.short_name,

             nvl(sum(vf.rent_square_total),0) total_square

      from bis_project p left join vw_bis_mall_floor_summary vf on p.bis_project_id = vf.bis_project_id

      where  p.is_business_project = ''1''

             and p.oper_status = ''2''

      group by p.bis_project_id,p.short_name) pt,rep_agg_floor_month af

      where 1 = 1

            and pt.bis_project_id = af.bis_project_id

            and af.store_type = ''1''

            and af.agg_year = '||v_year||'

            and af.agg_month = ''1''

      group by pt.bis_project_id,pt.short_name,pt.total_square,af.agg_month,af.agg_year) r,bis_project_target bt

      where r.bis_project_id = bt.bis_project_id(+)) y

      where m.bis_project_id = y.bis_project_id

     ';

executeimmediate v_sql;

--  v_sql:='select 1 as a from dual;';

commit;

EXCEPTION

-- 異常處理部份

WHENOTHERSTHEN

      dbms_output.put_line('insertBisSecondZsPro 錯誤:' || SQLERRM);

null;

end BIS_PROJECT_BUDGET;