我是Oracle的新手。 我正在尝试创建一个具有多个功能的包。 这是我想做的伪代码
function FunctionA(UserID, startdate, enddate)
/* Select TransactionDate, Amount
from TableA
where TransactionDate between startdate and enddate
and TableA.UserID = UserID */
Return TransactionDate, Amount
end FunctionA
function FunctionB(UserID, startdate, enddate)
/* Select TransactionDate, Amount
from TableB
where TransactionDate between startdate and enddate
and TableB.UserID = UserID */
Return TransactionDate, Amount
end FunctionA
TYPE TRANSACTION_REC IS RECORD(
TransactionDate DATE,
TransactionAmt NUMBER);
function MainFunction(startdate, enddate)
return TBL
is
vTrans TRANSACTION_REC;
begin
FOR rec IN
( Select UserID, UserName, UserStatus
from UserTable
where EntryDate between startdate and enddate )
LOOP
vTrans := FunctionA(rec.UserID, startdate, enddate)
if vTrans.TransactionDate is null then
vTrans := FunctionB(rec.UserID, startdate, enddate)
if vTrans.TransactionDate is null then
rec.UserStatus := 'Inactive'
endif;
endif;
END Loop;
PIPE ROW(USER_OBJ_TYPE(rec.UserID,
rec.UserName,
rec.UserStatus,
vTrans.TransactionDate,
vTtans.TransactionAmt));
end MainFunction
运行这种代码需要很长时间,因为TableA和TableB是一个非常大的表,我只从表中获得每条记录1个条目。
我想在包中创建一个临时表(TempTableA,TempTableB),它将暂时存储基于startdate和enddate的所有记录,这样当我尝试检索每个rec的TransactionDate和Amount时,我只会请参阅TempTables(小于TableA和TableB)。
我还想考虑在TableA和TableB中是否找不到UserID。所以基本上,当TableA和TableB中没有找到记录时,我也想要输出中的条目,但是表明用户处于非活动状态。
感谢您的帮助。
答案 0 :(得分:3)
SQL是一种基于集合的语言。执行一个返回所需行的语句比执行多个返回单行的语句要高效得多。
这是一次获取所有行的方法。它使用公用表表达式,因为您读取了整个UserTable,并且您应该只执行一次。
with cte as
(select UserID
, UserStatus
from UserTable )
select cte.UserID
, cte.UserStatus
, TableA.TransactionDate
, TableA.Amount
from cte join TableA
on (cte.UserID = TableA.UserID)
where cte.UserStatus = 'A'
and TableA.TransactionDate between startdate and enddate
union
select cte.UserID
, cte.UserStatus
, TableB.TransactionDate
, TableB.Amount
from cte join TableB
on (cte.UserID = TableB.UserID)
where cte.UserStatus != 'A'
and TableB.TransactionDate between startdate and enddate
顺便说一下,要小心临时表。它们不像T-SQL中的临时表。它们是永久堆表,只是它们的数据是临时的。这意味着填充临时表是一个昂贵的过程,因为数据库会将所有这些行写入磁盘。因此,我们需要确保通过从临时表中读取数据集获得的性能增益值得所有这些写入的开销。
您的代码肯定不会这样。事实上,性能问题的答案最终证明是“使用全局临时表”,至少在Oracle中是这样。更好的查询是要走的路,特别是拥抱集合的喜悦!
答案 1 :(得分:2)
可能更好地在一个查询中执行此操作,例如:
Select UserTable.UserID, UserTable.UserName, UserTable.UserStatus
,TableA.TransactionDate AS ATransactionDate
,TableA.Amount AS AAmount
,TableB.TransactionDate AS BTransactionDate
,TableB.Amount AS BAmount
from UserTable
left join TableA
on (UserTable.UserID = TableA.UserID)
left join TableB
on (UserTable.UserID = TableB.UserID)
where UserTable.EntryDate between startdate and enddate