2012-06-25创建数据库函数的基本语法

create or replace function minday
(sid varchar2, npr number)      //参数不能具体写变量类型,如number(5,2)
return number is md number(5,2);   //返回结果要明确类型和精度
 
//定义数组型变量类型,因为select into 后只能跟一个变量(确认?),因此需select出多个列时,只能预先定义数组型变量。
type m9s_t is record(m1 number(5,2),m2 number(5,2),m3 number(5,2),m4 number(5,2),m5 number(5,2),m6 number(5,2),m7 number(5,2),m8 number(5,2),m9 number(5,2) ); 
 
//定义类型的实例
m9s m9s_t; 
 
begin      
md:=0;
select mn1,mn2,mn3,mn4,mn5,mn6,mn7,mn8,mn9 into m9s from jb where id=sid;  //sid变量名不能与字段名重复
if npr<=m9s.m9 and m9s.m9>0 then md:=9; 
elsif npr<=m9s.m8 and m9s.m8>0 then md:=8;   //注意elsif 少一个e
elsif npr<=m9s.m7 and m9s.m7>0 then md:=7; 
elsif npr<=m9s.m6 and m9s.m6>0 then md:=6; 
elsif npr<=m9s.m5 and m9s.m5>0 then md:=5; 
elsif npr<=m9s.m4 and m9s.m4>0 then md:=4; 
elsif npr<=m9s.m3 and m9s.m3>0 then md:=3; 
elsif npr<=m9s.m2 and m9s.m2>0 then md:=2; 
elsif npr<=m9s.m1 and m9s.m1>0 then md:=1;  
end if;
return md;    
end;     

create or replace function mb40 (sid varchar2,pr number) return number is nm number(5,2);

mpr number(5,2);

begin

mpr:=0;

select max(pr) into mpr from DY where id =sid and rownum<40 order by dt desc;

if pr=0 or mpr=0 then return 0;

else

nm:=100*(pr-mpr)/mpr;

nm:=round(nm,2);

return nm;

end if;

end;

//////////////////////////

create or replace function bl (n1 number,n2 number,w number)

return number is nm number(5,2);

begin

if n2=0 then return 0;

else

nm:=100*(n1-n2)/n2;

nm:=round(nm,w);

return nm;

end if;

end;

以下4函数来自临时航线

1、/////////////////////////////////////////////////////

create or replace function airlinemingao(aid in number) return number is

--函数功能是返回航线aid最低高度层

restStr varchar2(200); --该航线所有高度层组合在一起字符串

splitchar varchar2(5); --分隔符

minval number(5); --最小高度值

thisStr varchar2(18);--取得的当前被分割出的字符串

indexStr int;--临时存放分隔符在字符串中的位置

tmp number(5);

begin

splitchar:='/';

minval:=125; --默认最小高度值时12500米

select  levels ||'/'|| level_chg_1 ||'/'|| level_chg_2||'/'|| level_chg_3||'/'|| level_chg_4||'/'|| level_chg_5 into restStr

from COMPANY_ENROUTE where company_enroute_id =aid;

while length(restStr) != 0

                   LOOP

                     <<top>>

                     indexStr := instr(restStr,splitchar); --从子串中取分隔符的第一个位置

                     if indexStr = 0 and length(restStr) != 0  then--在剩余的串中找不到分隔符

                          thisStr := restStr; --取得当前的字符串

                          thisStr:=REGEXP_REPLACE(thisStr,'[^0-9]');--用正则表达式去除当前字符串中的非数字字符

                          if length(thisStr)=0 then

                          thisStr:='125';

                          end if;

                           tmp:=to_number(thisStr); --将当前字符串转化为数字

                           if tmp < minval then --比较得到最小值

                           minval:=tmp;

                           end if;

                          return minval;

                     end if;

                     if indexStr = 1 then---第一个字符便为分隔符,此时去掉分隔符

                             restStr := substr(restStr,2);

                             goto   top;

                     end if;

                     if length(restStr) = 0 or restStr is null then

                        return minval;

                     end if;

                     thisStr := substr(restStr,1,indexStr - 1); --取得当前的字符串

                     restStr := substr(restStr,indexStr + 1);---取剩余的字符串

                     thisStr:=REGEXP_REPLACE(thisStr,'[^0-9]'); --用正则表达式去除当前字符串中的非数字字符

                     if length(thisStr)=0 then

                     thisStr:='125';

                     end if;

                     tmp:=to_number(thisStr); --将当前字符串转化为数字

                     if tmp < minval then --比较得到最小值

                     minval:=tmp;

                     end if; 

                   END LOOP;  

  return minval;

end;

2、//////////////////////////////////////////////////

create or replace function alinepnts(alid in number)

return tab_airline_pnt is --返回航线的所有航路点组成

srt number(5);

alpnts tab_airline_pnt:=tab_airline_pnt();

dt     tab_pnt:= tab_pnt(); 

dr     row_airline_pnt:=row_airline_pnt(0,0,0,0);

oldpid number(12); --上一点id,因为航路点首尾会重复

begin

srt:=0;

oldpid:=0;

for myrow in(

select  company_enroute_id, val_sort, en_route_rte_id, start_point_id , end_point_id

from COMPANY_RTE where  company_enroute_id = alid

order by  val_sort

)loop

  dt:=subairway(myrow.start_point_id,myrow.en_route_rte_id,myrow.end_point_id);

--  for v in dt.first..dt.last loop

    for v in 1..dt.count() loop

      if oldpid <> dt(v).pid then --判断是否跟上点重复

        srt:=srt+1;

        dr:=row_airline_pnt(alid,myrow.en_route_rte_id,srt,dt(v).pid);

        alpnts.extend();

        alpnts(alpnts.count()):=dr;

        oldpid:=dt(v).pid;

      end if;

  end loop;

end loop;

return alpnts;

end;

3、/////////////////////////////////////////////////////////

create or replace function alinezx(alid in number)
return tab_airline_zx is --返回航线的所有航路、航路点组成,对航路出入点,重复该点,但航路不重复,该点在该航路中的作用
srt number(5);
alpnts tab_airline_zx:=tab_airline_zx();
dt     tab_pnt:= tab_pnt(); 
dr     row_airline_zx:=row_airline_zx(0,0,0,0,0);
ptype number(5); --点的作用
begin
srt:=0;
ptype:=0;
for myrow in(
select  company_enroute_id, val_sort, en_route_rte_id, start_point_id , end_point_id
from COMPANY_RTE where  company_enroute_id = alid
order by  val_sort
)loop
  dt:=subairway(myrow.start_point_id,myrow.en_route_rte_id,myrow.end_point_id);
    for v in 1..dt.count() loop
        srt:=srt+1;
        if v=1 then ptype:=1; --当该点是航路第一点时,标示为航路入点
        elsif v=dt.count() then ptype:=2; --当该点是航路最后一点时,标示为航路出点
        else ptype:=0; --其它情况为普通点
        end if;
        dr:=row_airline_zx(alid,myrow.en_route_rte_id,srt,dt(v).pid,ptype);
        alpnts.extend();
        alpnts(alpnts.count()):=dr;
  end loop;
end loop;
return alpnts;
end;

4、//////////////////////////////////////////////

create or replace function subairway(pid1 in number,

                                     awid in number,

                                     pid2 in number,

                                     ishis in number default 0 ) return tab_pnt is

--函数功能是返回awid航路两点间的所有航路点,使用此函数获得某航路两点间的所有点后时,不能用srt排序,否则永远只能得到按原航路顺序的点串,而不是按入点到出点顺序的点串。

 

  dr      row_pnt := row_pnt(0, 0, null); --type 行类型每条点记录 create or replace type row_pnt is object(srt number(5),pid number(11),pnm varchar2(50))

  dt      tab_pnt:= tab_pnt();            --type 表类型,返回航路所有点 create or replace type tab_pnt as table of row_pnt

  dtt tab_pnt:= tab_pnt(); --结果表,两点之间的所有表记录

  -- 表类型和行类型必须先初始化,否则编译不错但运行会提示错误

 

  n1 number(5); --两点在航路走向中的序号

  n2 number (5);

  tm number(5);

 

begin

 

if ishis=1 then --2016.9.7 原来写的临时航路居然找不到了,重写

 for myrow in

( select  sort st, airway_point_id pid, airway_point_name pnm from his_airway_pnts

where airway_id=awid

order by sort

)

loop

dr:=row_pnt(myrow.st,myrow.pid,myrow.pnm);

    dt.extend(); --dt增加一行新行

    dt(dt.count()) := dr; --dt最后一行=dr

END LOOP;

else

 for myrow in

(

  select st,pid,pnm from (

    select f1.code_sort st,f2.airway_point1 pid,f3.txt_name || decode(f3.tab, 'DES', '', f3.tab) pnm

      from rte_seg f1, segment f2, airway_point f3

     where f1.segment_id = f2.segment_id

       and f2.airway_point1 = f3.significant_point_id

       and f1.en_route_rte_id = awid

    union

    select f1.code_sort + 1 st, f2.airway_point2 pid,f3.txt_name || decode(f3.tab, 'DES', '', f3.tab) pnm

      from rte_seg f1, segment f2, airway_point f3

     where f1.segment_id = f2.segment_id

       and f2.airway_point2 = f3.significant_point_id

       and f1.code_sort =(select max(code_sort)from rte_seg where rte_seg.en_route_rte_id = f1.en_route_rte_id)

       and f1.en_route_rte_id = awid

     order by st

   )

 )

loop

dr:=row_pnt(myrow.st,myrow.pid,myrow.pnm);

    dt.extend(); --dt增加一行新行

    dt(dt.count()) := dr; --dt最后一行=dr

END LOOP;

 end if;

 

  if pid1=0 or pid2=0 then --如果输入变量首点id或末点id 0 表示返回所有航路走向

  return dt;

  end if;

 

  n1:=-1; --初始值,用于判断时候再航路上找到输入点

  n2:=-1;

 

  for v in 1..dt.count() loop --从第一行到dt表的最后一行

  if pid1 = dt(v).pid then n1:=dt(v).srt; --找到n1 n2对应位置

  elsif pid2 = dt(v).pid then n2:=dt(v).srt;

  end if;

  end loop;

 

  if n1=-1 or n2=-1 then --至少有一点没匹配上,返回空表

  return dtt;

  end if;

   

  if n1<n2 then --1序号小于点2序号,正常循环

    for v in n1..n2 loop

    if dt(v).srt >= n1 and dt(v).srt<=n2 then --dt(v).srt 从表结构逐级访问行结构、字段结构

     dtt.extend();

     dtt(dtt.count()):= dt(v);

    end if;

    end loop;

  end if;

 

  if n1>n2 then --如果n1>n2说明p1,p2顺序颠倒

    tm:=n1;

    while tm >= n2 LOOP

      begin  

      dtt.extend();

      dtt(dtt.count()):= dt(tm);

      dtt(dtt.count()).srt:=n1-tm+1; --2016.9.7 倒序排列时,为了让序号体现真正的从小到大顺序,改写每点序号

      tm:= tm - 1;

      end;

    end LOOP;

  end if; 

  return dtt;

end;

原文地址:https://www.cnblogs.com/mol1995/p/5969757.html