zoukankan      html  css  js  c++  java
  • SQL server函数转Oracle问题之一,强行使用临时表

    此文转载自:https://blog.csdn.net/qq_40791652/article/details/112213180#commentBox

    SQL server函数转Oracle问题之一,强行使用临时表
    (多次修改,现在可以用了)
    1.工作中遇见的问题,背景是客户的数据库迁移,SQL server迁到Oracle。网上没有对应的办法,也不知对不对,至少不报BUG了,分享给大家

    流程如下图
    在这里插入图片描述

    这种创建方法百度“Oracle函数返回结果集(或临时表)”有一堆,不重复说了。

    注意:

    临时表函数中还要定义,格式如下:

    在这里插入图片描述

    (就像JAVA的定义)

    然后剩余步骤:

    在这里插入图片描述
    *****************分割线
    在这里插入图片描述
    *****************分割线
    在这里插入图片描述
    *****************分割线
    在这里插入图片描述
    *****************分割线
    在这里插入图片描述
    *****************分割线
    在这里插入图片描述

    sqlserver源码:

    CREATE function [dbo].[fn_g_CompareAllData](@pk_corp varchar(20),@BeginDate datetime,@EndDate datetime)
    returns @tem table
    (
    	SN bigint,
    	--csalereceiveid char(20),				--发货单主键
    	vreceivecode char(30),					--发货单号
    	nnumber decimal(20,0),					--数量
    	ntotaloutinvnum decimal(20,0),		--数量
    	ntotaltransnum decimal(20,0),		--累计运输数量
    	--csaleid char(20),							--发货单主键				
    	--pk_transport_h char(20),			--运输单主键
    	vbillcode_t char(30),						--运输单号
    	ntotalnumber decimal(20,0),			--存货总数量
    	reserve5 decimal(20,0),					--周转桶数
    	--transportcode char(20),				--运输单主键
    	vbillcode_r char(30),						--回收单号
    	ntotalnumber2 numeric(28,0),			--发货单数量
    	backwaternum numeric(28,0),			--退水数量
    	exwaternum numeric(28,0),			--换水数量
    	yabucketnum numeric(28,0),			--押退桶数量
    	getbucketnum numeric(28,0),			--借/还桶数量
    	sendbucketnum numeric(28,0),		--赠桶数量
    	backbucketnum numeric(28,0),		--回桶数量
    	notclearnum numeric(28,0)				--车辆未结清数量
    )
    begin
    	--set @pk_corp = '3001'
    	--set @BeginDate = '2013-08-01'
    	--set @EndDate = '2013-08-11'
    
    	set @pk_corp = (select top 1 pk_corp from bd_corp where unitcode = @pk_corp);
    
    	declare @All table
    	(
    		SN bigint identity(1,1),
    		csalereceiveid char(20),				--发货单主键
    		vreceivecode char(30),					--发货单号
    		nnumber decimal(20,0),					--数量
    		ntotaloutinvnum decimal(20,0),		--数量
    		ntotaltransnum decimal(20,0),		--累计运输数量
    		csaleid char(20),							--发货单主键				
    		pk_transport_h char(20),				--运输单主键
    		vbillcode_t char(30),						--运输单号
    		ntotalnumber decimal(20,0),			--存货总数量
    		reserve5 decimal(20,0),					--周转桶数
    		transportcode char(20),				--运输单主键
    		vbillcode_r char(30),						--回收单号
    		ntotalnumber2 numeric(28,0),			--发货单数量
    		backwaternum numeric(28,0),			--退水数量
    		exwaternum numeric(28,0),			--换水数量
    		yabucketnum numeric(28,0),			--押退桶数量
    		getbucketnum numeric(28,0),			--借/还桶数量
    		sendbucketnum numeric(28,0),		--赠桶数量
    		backbucketnum numeric(28,0),		--回桶数量
    		notclearnum numeric(28,0)				--车辆未结清数量
    	);
    	with so_salereceive_w as
    	(
    		select 
    			b.csalereceiveid,
    			b.vreceivecode,
    			sum(c.nnumber) as nnumber,
    			sum(c.ntotaloutinvnum) as ntotaloutinvnum,
    			sum(c.ntotaltransnum) as ntotaltransnum
    		from	so_salereceive b with(nolock)
    		inner join so_salereceive_b c with(nolock) on b.csalereceiveid = c.csalereceiveid
    		inner join bd_invbasdoc d with(nolock) on c.cinvbasdocid = d.pk_invbasdoc 
    		inner join bd_invcl e with(nolock) on d.pk_invcl = e.pk_invcl
    		where e.invclassname = '产成品' 
    			and b.pk_corp = @pk_corp
    			and b.dapprovedate between @BeginDate and @EndDate
    			and IsNull(b.dr,0) = 0
    		group by b.csalereceiveid,b.vreceivecode
    	),
    	transport_w as
    	(
    		select 
    			a.csaleid,
    			a.pk_transport_h,
    			b.vbillcode,
    			sum(a.ntotalnumber) as ntotalnumber,
    			sum(a.reserve5) as reserve5
    		from lbs_transport_b a with(nolock)
    		inner join lbs_transport_h b with(nolock) on a.pk_transport_h = b.pk_transport_h
    		inner join so_salereceive_w c with(nolock) on c.csalereceiveid = a.csaleid
    		where IsNull(b.dr,0) = 0
    		group by a.csaleid,a.pk_transport_h,b.vbillcode
    	),
    	tempReceipt_w as
    	(
    		select  distinct
    			b.pk_receivebill_h,b.transportcode,b.vbillcode
    		from  lbs_receivebill_h b with(nolock) 
    		inner join transport_w c with(nolock) on c.pk_transport_h = b.transportcode
    		where IsNull(b.dr,0) = 0
    	),
    	Receive_w as
    	(
    		select 
    			b.transportcode,
    			b.vbillcode,
    			sum(a.ntotalnumber) as ntotalnumber,			--发货单数量
    			sum(backwaternum) as backwaternum,		--退水数量
    			sum(exwaternum) as exwaternum,				--换水数量
    			sum(yabucketnum) as yabucketnum,			--押退桶数量
    			sum(getbucketnum) as getbucketnum,			--借/还桶数量
    			sum(sendbucketnum) as sendbucketnum,		--赠桶数量
    			sum(backbucketnum) as backbucketnum,		--回桶数量
    			sum(notclearnum)	 as notclearnum				--车辆未结清数量
    		from lbs_receivebill_b a with(nolock) 
    		inner join tempReceipt_w b with(nolock) on a.pk_receivebill_h = b.pk_receivebill_h
    		group by b.transportcode,b.vbillcode
    	)
    
    	insert @All
    	(
    		--发货单
    		--csalereceiveid,				--发货单主键
    		vreceivecode,
    		nnumber,					--数量
    		ntotaloutinvnum,			--数量
    		ntotaltransnum,			--累计运输数量
    		--运输单
    		--csaleid,						--发货单主键				
    		--pk_transport_h ,			--运输单主键
    		vbillcode_t,
    		ntotalnumber,				--存货总数量
    		reserve5,					--周转桶数
    		--回桶单
    		--transportcode,				--运输单主键
    		vbillcode_r,
    		ntotalnumber2,			--发货单数量
    		backwaternum,			--退水数量
    		exwaternum,				--换水数量
    		yabucketnum,				--押退桶数量
    		getbucketnum,				--借/还桶数量
    		sendbucketnum,			--赠桶数量
    		backbucketnum,			--回桶数量
    		notclearnum 				--车辆未结清数量
    	)
    	select
    		a.vreceivecode,
    		a.nnumber,						--数量
    		a.ntotaloutinvnum,			--数量
    		a.ntotaltransnum,
    		-----------------------
    		b.vbillcode,
    		b.ntotalnumber,				--存货总数量
    		b.reserve5,						--周转桶数
    		-----------------------
    		c.vbillcode,
    		c.ntotalnumber,				--发货单数量
    		c.backwaternum,				--退水数量
    		c.exwaternum,					--换水数量
    		c.yabucketnum,				--押退桶数量
    		c.getbucketnum,				--借/还桶数量
    		c.sendbucketnum,			--赠桶数量
    		c.backbucketnum,			--回桶数量
    		c.notclearnum 	
    	from so_salereceive_w a with(nolock) 
    	left join transport_w b with(nolock) on a.csalereceiveid = b.csaleid
    	left join Receive_w c with(nolock) on b.pk_transport_h = c.transportcode
    	order by a.csalereceiveid,b.pk_transport_h,c.transportcode
    	;
    	update @All set nnumber = null,ntotaloutinvnum = null,ntotaltransnum = null
    	from @All ta
    	where SN <> (select min(SN) from @All where csalereceiveid = ta.csalereceiveid)
    	;
    	update @All set ntotalnumber = null,reserve5 = null
    	from @All ta
    	where SN <> (select min(SN) from @All where pk_transport_h = ta.pk_transport_h and csaleid = ta.csaleid)
    	;
    	insert @tem
    	(
    		SN,
    		--发货单
    		--csalereceiveid,				--发货单主键
    		vreceivecode ,				--发货单号
    		nnumber,					--数量
    		ntotaloutinvnum,			--数量
    		ntotaltransnum,			--累计运输数量
    		--运输单
    		--csaleid,						--发货单主键				
    		--pk_transport_h ,			--运输单主键
    		vbillcode_t,
    		ntotalnumber,				--存货总数量
    		reserve5,					--周转桶数
    		--回桶单
    		--transportcode,				--运输单主键
    		vbillcode_r,
    		ntotalnumber2,			--发货单数量
    		backwaternum,			--退水数量
    		exwaternum,				--换水数量
    		yabucketnum,				--押退桶数量
    		getbucketnum,				--借/还桶数量
    		sendbucketnum,			--赠桶数量
    		backbucketnum,			--回桶数量
    		notclearnum 				--车辆未结清数量
    	)
    	 select 
    		SN,
    		--发货单
    		--csalereceiveid,				--发货单主键
    		vreceivecode ,				--发货单号
    		nnumber,					--数量
    		ntotaloutinvnum,			--数量
    		ntotaltransnum,			--累计运输数量
    		--运输单
    		--csaleid,						--发货单主键				
    		--pk_transport_h ,			--运输单主键
    		vbillcode_t,
    		ntotalnumber,				--存货总数量
    		reserve5,					--周转桶数
    		--回桶单
    		--transportcode,				--运输单主键
    		vbillcode_r,
    		ntotalnumber2,			--发货单数量
    		backwaternum,			--退水数量
    		exwaternum,				--换水数量
    		yabucketnum,				--押退桶数量
    		getbucketnum,				--借/还桶数量
    		sendbucketnum,			--赠桶数量
    		backbucketnum,			--回桶数量
    		notclearnum 				--车辆未结清数量
    	from @All 
    	order by SN;
    	return;
    end	
    
    

    转化后的Oracle:

    3, fn_g_CompareAllData			--√
    Oracler :
    create sequence fn_g_Compare_sq maxvalue 99999999999999999999    
              increment by 1    
              start with 1;  
    --步长为1
    
    create or replace type all_obj_type as object(
    SN number(20),  --发货单主键
    		csalereceiveid varchar2(20),				--发货单主键
    		vreceivecode varchar2 (30),					--发货单号
    		nnumber number (20,0),					--数量
    		ntotaloutinvnum number (20,0),		--数量
    		ntotaltransnum number (20,0),		--累计运输数量
    		csaleid varchar2 (20),				--发货单主键				
    		pk_transport_h number (20),				--运输单主键
    		vbillcode_t number (30),						--运输单号
    		ntotalnumber number (20,0),			--存货总数量
    		reserve5 number (20,0),					--周转桶数
    		transportcode varchar2 (20),				--运输单主键
    		vbillcode_r varchar2 (30),						--回收单号
    		ntotalnumber2 number (28,0),			--发货单数量
    		backwaternum number(28,0),			--退水数量
    		exwaternum number (28,0),			--换水数量
    		yabucketnum number (28,0),			--押退桶数量
    		getbucketnum number (28,0),			--借/还桶数量
    		sendbucketnum number (28,0),		--赠桶数量
    		backbucketnum number (28,0),		--回桶数量
    		notclearnum number (28,0)				--车辆未结清数量
    ); 
    
    CREATE OR REPLACE TYPE all_tab_type IS TABLE OF all_obj_type;
    
    create or replace type tem_obj_type as object(
    SN number,
    	--csalereceiveid char(20),				--发货单主键
    	vreceivecode varchar2 (30),					--发货单号
    	nnumber number (20,0),					--数量
    	ntotaloutinvnum number (20,0),		--数量
    	ntotaltransnum number (20,0),		--累计运输数量
    	vbillcode_t varchar2 (30),						--运输单号
    	ntotalnumber number (20,0),			--存货总数量
    	reserve5 number (20,0),					--周转桶数
    	vbillcode_r varchar2 (30),						--回收单号
    	ntotalnumber2 number (28,0),			--发货单数量
    	backwaternum number (28,0),			--退水数量
    	exwaternum number (28,0),			--换水数量
    	yabucketnum number (28,0),			--押退桶数量
    	getbucketnum number (28,0),			--借/还桶数量
    	sendbucketnum number (28,0),		--赠桶数量
    	backbucketnum number (28,0),		--回桶数量
    	notclearnum number (28,0)				--车辆未结清数量
    );
    CREATE OR REPLACE TYPE tem_tab_type IS TABLE OF tem_obj_type;
    --定义工具类表,之后清除里面的数据
    create table all_tab_linshi(
    SN number(20),  
    csalereceiveid varchar2(20),	
    vreceivecode varchar2 (30),			
    nnumber number (20,0),			
    ntotaloutinvnum number (20,0),		
    ntotaltransnum number (20,0),		
    csaleid varchar2 (20),						
    pk_transport_h number (20),			
    vbillcode_t number (30),				
    ntotalnumber number (20,0),			
    reserve5 number (20,0),				
    transportcode varchar2 (20),		
    vbillcode_r varchar2 (30),					
    ntotalnumber2 number (28,0),			
    backwaternum number(28,0),		
    exwaternum number (28,0),		
    yabucketnum number (28,0),			
    getbucketnum number (28,0),		
    sendbucketnum number (28,0),	
    backbucketnum number (28,0),	
    notclearnum number (28,0)		
    );
    Create table tem_tab_linshi(
    SN number, 
    vreceivecode varchar2 (30),				--发货单号
    nnumber number (20,0),					--数量
    ntotaloutinvnum number (20,0),		--数量
    ntotaltransnum number (20,0),		--累计运输数量
    vbillcode_t varchar2 (30),				--运输单号
    ntotalnumber number (20,0),			--存货总数量
    reserve5 number (20,0),					--周转桶数
    vbillcode_r varchar2 (30),				--回收单号
    ntotalnumber2 number (28,0),			--发货单数量
    backwaternum number (28,0),			--退水数量
    exwaternum number (28,0),			--换水数量
    yabucketnum number (28,0),			--押退桶数量
    getbucketnum number (28,0),			--借/还桶数量
    sendbucketnum number (28,0),		--赠桶数量
    backbucketnum number (28,0),		--回桶数量
    notclearnum number (28,0)
    );
    --序列预备的函数
    create or replace function get_fn_g_Compare_sq 
    return number
    is
      seq_val number ;
    begin
      execute immediate 'select fn_g_Compare_sq. NEXTVAL from dual' into seq_val ;
      return seq_val ;
    end get_fn_g_Compare_sq;
    --函数本体
    CREATE OR REPLACE function fn_g_CompareAllData(pk_corp_dec in varchar2,BeginDate_dec in date,EndDate_dec in date)
    return tem_tab_type
    IS
    	tab_tem tem_tab_type:= tem_tab_type();
    	v_pk_corp varchar2(20);
    begin
    
    select pk_corp into v_pk_corp
    from(
    select  pk_corp 
    from bd_corp 
    where unitcode = pk_corp_dec) where rownum=1;
    --这是分割线
    insert into all_tab_linshi
    (
    Sn,
    vreceivecode,
    nnumber,					--数量
    ntotaloutinvnum,			--数量
    ntotaltransnum,			--累计运输数量
    vbillcode_t,
    ntotalnumber,				--存货总数量
    reserve5,					--周转桶数
    vbillcode_r,
    ntotalnumber2,			--发货单数量
    backwaternum,			--退水数量
    exwaternum,				--换水数量
    yabucketnum,				--押退桶数量
    getbucketnum,				--借/还桶数量
    sendbucketnum,			--赠桶数量
    backbucketnum,			--回桶数量
    notclearnum 				--车辆未结清数量
    )
    with so_salereceive_w as
    (
    select 
    b.csalereceiveid,
    b.vreceivecode,
    sum(c.nnumber) as nnumber,
    sum(c.ntotaloutinvnum) as ntotaloutinvnum,
    sum(c.ntotaltransnum) as ntotaltransnum
    from	so_salereceive b 
    inner join so_salereceive_b c on b.csalereceiveid = c.csalereceiveid
    inner join bd_invbasdoc d on c.cinvbasdocid = d.pk_invbasdoc 
    inner join bd_invcl e on d.pk_invcl = e.pk_invcl
    where e.invclassname = '产成品' 
    and b.pk_corp = v_pk_corp
    and b.dapprovedate between BeginDate_dec and EndDate_dec
    and nvl(b.dr,0) = 0
    group by b.csalereceiveid,b.vreceivecode),
    transport_w as
    (
    select 
    a.csaleid,
    a.pk_transport_h,
    b.vbillcode,
    sum(a.ntotalnumber) as ntotalnumber,
    sum(a.reserve5) as reserve5
    from lbs_transport_b a 
    inner join lbs_transport_h b on a.pk_transport_h = b.pk_transport_h
    inner join so_salereceive_w c on c.csalereceiveid = a.csaleid
    where nvl(b.dr,0) = 0
    group by a.csaleid,a.pk_transport_h,b.vbillcode
    ), 
    tempReceipt_w as
    (
    select  distinct
    b.pk_receivebill_h,b.transportcode,b.vbillcode
    from  lbs_receivebill_h b 
    inner join transport_w c on c.pk_transport_h = b.transportcode
    where nvl(b.dr,0) = 0
    ),
    Receive_w as
    (
    select 
    b.transportcode,
    b.vbillcode,
    sum(a.ntotalnumber) as ntotalnumber,	--发货单数量
    sum(backwaternum) as backwaternum,		--退水数量
    sum(exwaternum) as exwaternum,			--换水数量
    sum(yabucketnum) as yabucketnum,		--押退桶数量
    sum(getbucketnum) as getbucketnum,		--借/还桶数量
    sum(sendbucketnum) as sendbucketnum,	--赠桶数量
    sum(backbucketnum) as backbucketnum,	--回桶数量
    sum(notclearnum)	 as notclearnum		--车辆未结清数量
    from lbs_receivebill_b a 
    inner join tempReceipt_w b on a.pk_receivebill_h = b.pk_receivebill_h
    group by b.transportcode,b.vbillcode) 
    Select
    get_fn_g_Compare_sq,
    a.vreceivecode,
    a.nnumber,						--数量
    a.ntotaloutinvnum,			--数量
    a.ntotaltransnum,
    -----------------------
    b.vbillcode,
    b.ntotalnumber,				--存货总数量
    b.reserve5,						--周转桶数
    -----------------------
    c.vbillcode,
    c.ntotalnumber,				--发货单数量
    c.backwaternum,				--退水数量
    c.exwaternum,					--换水数量
    c.yabucketnum,				--押退桶数量
    c.getbucketnum,				--借/还桶数量
    c.sendbucketnum,			--赠桶数量
    c.backbucketnum,			--回桶数量
    c.notclearnum 	
    from so_salereceive_w a 
    left join transport_w b on a.csalereceiveid = b.csaleid
    left join Receive_w c on b.pk_transport_h = c.transportcode
    order by a.csalereceiveid,b.pk_transport_h,c.transportcode
    ;
    update all_tab_linshi set nnumber = null,ntotaloutinvnum = null,ntotaltransnum = null
    where SN != (select min(SN) from all_tab_linshi);
    update all_tab_linshi set ntotalnumber = null,reserve5 = null
    where SN != (select min(SN) from all_tab_linshi);
    insert into tem_tab_linshi
    (
    		SN, 
    		vreceivecode ,				--发货单号
    		nnumber,					--数量
    		ntotaloutinvnum,			--数量
    		ntotaltransnum,			--累计运输数量
    		
    		vbillcode_t,
    		ntotalnumber,				--存货总数量
    		reserve5,					--周转桶数
    		vbillcode_r,
    		ntotalnumber2,			--发货单数量
    		backwaternum,			--退水数量
    		exwaternum,				--换水数量
    		yabucketnum,				--押退桶数量
    		getbucketnum,				--借/还桶数量
    		sendbucketnum,			--赠桶数量
    		backbucketnum,			--回桶数量
    		notclearnum 				--车辆未结清数量
    	)
    	 select 
    		SN, 
    		vreceivecode ,				--发货单号
    		nnumber,					--数量
    		ntotaloutinvnum,			--数量
    		ntotaltransnum,			--累计运输数量
    		vbillcode_t,
    		ntotalnumber,				--存货总数量
    		reserve5,					--周转桶数
    		vbillcode_r,
    		ntotalnumber2,			--发货单数量
    		backwaternum,			--退水数量
    		exwaternum,				--换水数量
    		yabucketnum,				--押退桶数量
    		getbucketnum,				--借/还桶数量
    		sendbucketnum,			--赠桶数量
    		backbucketnum,			--回桶数量
    		notclearnum 				--车辆未结清数量
    	from all_tab_linshi 
    	order by SN;
    --将临时表数据插入函数中的自定义表,
    --然后情况临时表数据,返回自定义表
    for i in 
    (SELECT Sn,vreceivecode,nnumber,ntotaloutinvnum,ntotaltransnum,
    vbillcode_t,ntotalnumber,reserve5,vbillcode_r,ntotalnumber2,
    backwaternum,exwaternum,yabucketnum,getbucketnum,sendbucketnum,
    backbucketnum,notclearnum
    FROM tem_tab_linshi)
    loop
    tab_tem.extend;
    tab_tem (tab_tem.count) := tem_obj_type (i.Sn,i.vreceivecode,i.nnumber,i.ntotaloutinvnum,i.ntotaltransnum,
    i.vbillcode_t,i.ntotalnumber,i.reserve5,i.vbillcode_r,
    i.ntotalnumber2,i.backwaternum,i.exwaternum,i.yabucketnum,
    i.getbucketnum,i.sendbucketnum,i.backbucketnum,i.notclearnum
    );
    end loop; 
    execute immediate 
    ' truncate table tem_tab_linshi ';
    execute immediate 
    ' truncate table all_tab_linshi ';
    
    return tab_tem;
    end	;
    
    

    有点随意,希望能给遇见同样问题的朋友帮助,可以私信我,不过新手很菜,只能帮一些。
    (网上也有很多人不建议这种方法,如果想返回结果集,最好使用游标。但我还不熟悉游标,也恳请看到的大神给我建议)

    然而这样的函数不报错,但使用 select 函数名(形参。。。) from dual 调用时却报查询或者DML中不允许执行DDL。。。。。。这方法不行

    ----分割线
    PRAGMA AUTONOMOUS_TRANSACTION;
    上面那一句,加在函数或者存储过程的第一个BEGIN之前,然后每一个函数或存储过程中的DML后面添加一个 commit;
    如下面两个代码:

    PRAGMA AUTONOMOUS_TRANSACTION;
    begin
    
    execute immediate 
    ' delete so_salereceive_linshi ';
    Commit;
    execute immediate 
    ' delete temReceipt_linshi ';
    Commit;
    execute immediate 
    ' delete temReceipt2_linshi ';
    Commit;
    
    

    原理大概是Oracle中函数或者存储过程不允许DDL,DML的话要提交,PRAGMA AUTONOMOUS_TRANSACTION; 这句语句声明函数或存储过程为自治事务,然后使用delete 表名代替 truncate table 表名。

    改后之后的函数可以用下面语句调用测试:
    select 函数名(形参,形参。。。) from dual ; 的方法调用

       

    更多内容详见微信公众号:Python测试和开发

    Python测试和开发

  • 相关阅读:
    linux下查看主板内存槽与内存信息
    centos 6 与 centos 7 服务开机启动、关闭设置的方法
    linux 配置本地光盘YUM源
    linux crontab定时任务不执行
    Linux下安装MySQL5.6
    Linux shell 自动删除n天前日志
    nginx request_time 和upstream_response_time
    linux中文件多行合并为一行的例子
    awk 处理文本:行转列,列转行
    nfs环境搭建报错clnt_create: RPC: Program not registered
  • 原文地址:https://www.cnblogs.com/phyger/p/14247146.html
Copyright © 2011-2022 走看看