下面是我的程序,执行需要51秒,我想只在找到一个计数时返回游标,以防其他任何东西将返回消息和游标为null。如果找到游标消息为null ..
我首先通过查询进行计数并稍后通过相同的查询填充数据,但仅在count为1的情况下。
无论如何都可以在时间上优化它。?
create or replace PROCEDURE sp_cp_getcrnnofrmmobdob(P_MobileNo IN VARCHAR2,
P_Dob IN VARCHAR2,
p_Output out SYS_REFCURSOR,
p_Message OUT VARCHAR2) IS
vCRN Varchar2(50) := '';
vCustid varchar2(50) := '';
vMobno varchar2(50) := '';
vCustname varchar2(400) := '';
vCustDob varchar2(50) := '';
vcount int := 0;
BEGIN
p_Message := '';
OPEN p_Output FOR
select 1 from dual;
Select count(*)
into vcount
FROM (select distinct(C.fw_customer_id_c) crn,
C.Cust_Id_n custid,
c.customername custname,
c.dob custdob,
A.MOBILE mobileno
from FCH_CASTRANSACTION.NBFC_CUSTOMER_M C,
FCH_CASMASTER.nbfc_address_m A
where A.BPID = C.Cust_Id_n and
A.mobile = P_MobileNo and
TO_CHAR(TO_DATE(C.DOB, 'DD-MON-YY'),'DD-MON-YY')=TO_CHAR(TO_DATE(P_Dob,'DD/MM/YYYY'),'DD-MON-YY'));
if (vcount = 1) then
select B.crn,
B.custid,
B.mobileno,
B.custname,
B.custdob
into vCRN, vCustid, vMobno, vCustname, vCustDob
from (select distinct(C.fw_customer_id_c) crn,
C.Cust_Id_n custid,
c.customername custname,
c.dob custdob,
A.MOBILE mobileno
from FCH_CASTRANSACTION.NBFC_CUSTOMER_M C,
FCH_CASMASTER.nbfc_address_m A
where A.BPID = C.Cust_Id_n and
A.mobile = P_MobileNo and
TO_CHAR(TO_DATE(C.DOB, 'DD-MON-YY'),'DD-MON-YY')=TO_CHAR(TO_DATE(P_Dob,'DD/MM/YYYY'),'DD-MON-YY')) B;
if ((vCRN = '') OR (vCRN IS Null)) then
p_Message := 'No data found for entered details';
else
if ((vMobno <> P_MobileNo) OR (vMobno IS Null)) then
p_Message := 'Entered mobile number is not registered with us.Please contact customer care.';
else
if ((vCustDob <> TO_CHAR(TO_DATE(P_Dob,'DD/MM/YYYY'),'DD-MON-YY')) OR (vCustDob IS Null)) then
p_Message := 'Entered date of birth is not registered with us.Please contact customer care.';
else
OPEN p_Output FOR
select vCRN as "CrnNum", vCustid as "CustId", vMobno as "MobNo", vCustname as "CustName", vCustDob as "CustDob"
from dual;
End if;
End if;
End if;
else
p_Message := 'Inconsistent details for entered data found. Please contact customer care';
End if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_Message := 'Unable to process your request.Please contact customer care.';
OPEN p_Output FOR
SELECT 1 FROM dual;
END;
如果有人能提供帮助,我真的很感激。
答案 0 :(得分:1)
SELECT ... INTO ...
并捕获异常TOO_MANY_ROWS
。''
和NULL
是一回事。DISTINCT
不一个函数 - 它是一个适用于所有行的关键字。p_output
两次。此外,某些系统可能不喜欢该函数可以向游标返回不同数量的列。所以,像这样:
create or replace PROCEDURE sp_cp_getcrnnofrmmobdob(
P_MobileNo IN VARCHAR2,
P_Dob IN VARCHAR2,
p_Output out SYS_REFCURSOR,
p_Message OUT VARCHAR2
)
IS
v_dob DATE := TO_DATE( p_dob, 'DD/MM/YYYY' );
vCRN FCH_CASTRANSACTION.NBFC_CUSTOMER_M.fw_customer_id_c%TYPE;
vCustid FCH_CASTRANSACTION.NBFC_CUSTOMER_M.Cust_Id_n%TYPE;
vMobno FCH_CASMASTER.nbfc_address_m.MOBILE%TYPE;
vCustname FCH_CASTRANSACTION.NBFC_CUSTOMER_M.customername%TYPE;
vCustDob FCH_CASTRANSACTION.NBFC_CUSTOMER_M.dob%TYPE;
BEGIN
p_Message := '';
select distinct
C.fw_customer_id_c,
C.Cust_Id_n,
c.customername,
c.dob,
A.MOBILE
into vCRN, vCustid, vMobno, vCustname, vCustDob
from FCH_CASTRANSACTION.NBFC_CUSTOMER_M C
INNER JOIN FCH_CASMASTER.nbfc_address_m A
ON ( A.BPID = C.Cust_Id_n )
WHERE A.mobile = P_MobileNo
AND TO_DATE( C.DOB, 'DD-MON-YY') = v_dob;
IF vCRN IS NULL THEN
p_Message := 'No data found for entered details';
OPEN p_Output FOR
select 1 from dual;
RETURN;
END IF;
OPEN p_Output FOR
select vCRN as "CrnNum", vCustid as "CustId", vMobno as "MobNo", vCustname as "CustName", vCustDob as "CustDob"
from dual;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_Message := 'Unable to process your request.Please contact customer care.';
OPEN p_Output FOR
SELECT 1 FROM dual;
WHEN TOO_MANY_ROWS THEN
p_Message := 'Inconsistent details for entered data found. Please contact customer care';
OPEN p_Output FOR
SELECT 1 FROM dual;
END;
答案 1 :(得分:0)
我建议您查看两个查询中的TO_CHAR(TO_DATE(C.DOB, 'DD-MON-YY'),'DD-MON-YY')=TO_CHAR(TO_DATE(P_Dob,'DD/MM/YYYY'),'DD-MON-YY'))
。
DATE
。TO_DATE(column,'column format')=TO_DATE(variable,'variable format')
column = TO_CHAR(TO_DATE(variable, 'variable format'),'column format')
一样。这里有两个可能的优点。首先,转换只会对提供的值发生一次,但查询永远不必对列值执行函数。如果表很大。此外,由于没有对列值执行任何功能,如果该值有一个索引,优化器可以使用它(尽管根据我对您的数据模型的猜测,这可能对您的示例没有帮助)。这里的性能改进取决于查询如何使用dob。如果Oracle按手机号码查询记录,然后按dob过滤,它应该没什么区别,但如果反过来,通过dob查找然后过滤手机号码,这可能会有很大帮助。 tl; dr将日期存储为日期,将日期作为日期进行比较,尽可能避免列值上的函数