1. 程式人生 > 資料庫 >SQL server函式轉Oracle問題之一,強行使用臨時表

SQL server函式轉Oracle問題之一,強行使用臨時表

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
execute immediate 'Create Global Temporary Table tab_f_lbs_cuacc
  ( 
custcode varchar2(40),
custname varchar2(200),
respname varchar2(200),
pccode varchar2(40),
pcname varchar2(40),
skmny number(20,2),
ysmny number(20,2),
somny number(20,2),
allowmny number(20,2) )
On Commit Delete Rows ';
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	;

有點隨意,希望能給遇見同樣問題的朋友幫助,可以私信我,不過新手很菜,只能幫一些。
(網上也有很多人不建議這種方法,如果想返回結果集,最好使用遊標。但我還不熟悉遊標,也懇請看到的大神給我建議)