our system is quite big having around 100+ tables in schema. There was one business requirement for which we decided to handle it in stored procedures. In our application we have java as well but we chosen to use Stored Procedure. IN order to fulfill requirement created 3 functions.
These functions are part of SQL query which get fired to fetch count and display records. Now we have SQL timeout set in connection which is set to 60 seconds.
when we run this query for records of 40K, the operation gets timed out and we don't get any result.
I am pasting here actual implementation of all these 3 functions and below them is query who makes use of all these created function.
In query below have marked function calling in Bold letter.
I am looking at your expert advice by which i can tune this implementation to work on 100K of data.
we have oracle 11gR1.. Even this implementation is access from web in Ajax call.
Do let me know if you need anything else.
CREATE INDEX IDX_SNM_ENTITY_NAME
ON SML_NOTIFICATION_MAIN(ENTITY_NAME)
TABLESPACE CM_INDEX;
CREATE OR REPLACE FUNCTION is_Users_In_Same_Business_Unit
(UserMasterId varchar2,
CtoCode varchar2)
RETURN boolean
IS
v_count number(4);
BEGIN
if CtoCode is not null then
select count(*) into v_count
from sml_user u,
sml_team_member tm,
sml_usrprof_cto_map ctomap,
code_value cv
where u.status = 'ACTIVE'
and u.master_id is null
and u.id = tm.user_id
and tm.profile_id = ctomap.user_profile_id
and ctomap.cto_code_id = cv.id
and cv.code_value = CtoCode
and tm.team_id in
(select child_id
from vw_team_relation_master a
connect by prior a.child_id = a.parent_id
start with a.child_id =
(select child_id
from vw_team_relation_master c
where parent_id is null
start with c.child_id =
(select t.id
from sml_team t,
sml_team_member tm
where t.id = tm.team_id
and t.status = 'ACTIVE'
and t.master_id is null
and tm.user_id = UserMasterId)
connect by prior c.parent_id = c.child_id));
if v_count is not null and v_count > 0 then
return TRUE;
else
return FALSE;
end if;
end if;
return FALSE;
END;
CREATE OR REPLACE FUNCTION Can_User_Access_Customer(
NotificationDesc VARCHAR2,
UserId VARCHAR2,
NotificationType VARCHAR2,
UserRoleCode VARCHAR2,
UserMasterId VARCHAR2,
CtoCode VARCHAR2,
SecCtoCode VARCHAR2,
UserProfTempIdCommercialInd VARCHAR2,
UserProfTempIdCorporateInd VARCHAR2,
UserProfTempStcfInd VARCHAR2,
UserProfTempIdGsamInd VARCHAR2)
RETURN BOOLEAN
IS
-- function to test is user can access customer
regSearchCount number(2);
in_same_unit boolean;
count_v number(2);
BEGIN
in_same_unit := is_Users_In_Same_Business_Unit(UserMasterId, CtoCode);
-- Commercial
select count(*)
into regSearchCount
from dual
where regexp_like (CtoCode,'200[3-9]|20[1-4][0-9]|2[1-6][0-6][0-9]|29[0-6][0-9]|300[1-9]|30[1-6][0-9]|3[1-9][0-6][0-9]');
IF regSearchCount > 0 then -- user is commercial
-- check secondary cto code holder
select count(*)
into count_v
from dual
where SecCtoCode IN
(SELECT DISTINCT code_value
FROM sml_user,
sml_team_member,
sml_user_profile,
sml_usrprof_cto_map,
code_value
WHERE sml_user.id = sml_team_member.user_id
AND sml_team_member.profile_id = sml_user_profile.id
AND sml_user_profile.id = sml_usrprof_cto_map.user_profile_id
AND sml_usrprof_cto_map.cto_code_id = code_value.id
AND sml_user.login_id = UserId);
IF count_v is not null AND
count_v > 0
then
return TRUE;
END IF;
IF NotificationType='Collateral' AND
UserRoleCode is not null AND
UserRoleCode='RLOC'
then -- user is rloc
RETURN TRUE;
END IF;
IF in_same_unit AND
UserRoleCode is not null AND
UserRoleCode IN ('RMTL','GRPHD','SECHD')
then -- user belongs to GH, SH etc
RETURN TRUE;
END IF;
END IF;
-- corporate
select count(*)
into regSearchCount
from dual
where regexp_like (CtoCode,'1[0-9][0-6][0-9]');
IF regSearchCount > 0 then
IF in_same_unit and UserRoleCode is not null AND
UserRoleCode='GRPHD' AND
NotificationDesc!='0 days Due for expiry of Collateral'
THEN -- user belongs to GH
RETURN TRUE;
END IF;
IF in_same_unit AND
UserRoleCode is not null AND
UserRoleCode='RMTL' AND
NotificationDesc='0 days Due for expiry of Collateral'
THEN
RETURN TRUE;
END IF;
END IF;
-- STCF
select count(*)
into regSearchCount
from dual
where regexp_like (CtoCode, '20[5-6][0-9]');
IF regSearchCount > 0 then
IF in_same_unit AND
UserRoleCode is not null AND
UserRoleCode = 'RMTL'
then
RETURN TRUE;
END IF;
END IF;
RETURN FALSE ;
END;
create or replace FUNCTION IS_NOTIFICATION_ACCESS_PASSED(
NotificationDesc VARCHAR2,
UserId VARCHAR2,
NotificationType VARCHAR2,
UserMasterId VARCHAR2,
UserRoleCode VARCHAR2,
CtoCode VARCHAR2,
SecCtoCode VARCHAR2,
UserProfTempIdCommercialInd VARCHAR2,
UserProfTempIdCorporateInd VARCHAR2,
UserProfTempStcfInd VARCHAR2,
UserProfTempIdGsamInd VARCHAR2)
RETURN VARCHAR2 DETERMINISTIC
IS
-- functions to test, is instance of notification viewable for the logged in user, on the basis of notification type
-- and other user details etc, currently defined for only type 'Collateral' and 'Implementation Instruction'
regSearchCount NUMBER(2);
count_v NUMBER(2);
BEGIN
IF NotificationType = 'Implementation Instruction' THEN
IF Can_User_Access_Customer(NotificationDesc,UserId,
NotificationType
UserRoleCode,UserMasterId
CtoCode,SecCtoCode,
UserProfTempIdCommercialInd,
UserProfTempIdCorporateInd,
UserProfTempStcfInd,
UserProfTempIdGsamInd)
THEN
IF UserRoleCode = 'LDU' THEN
SELECT COUNT(*)
INTO regSearchCount
FROM dual
WHERE regexp_like (CtoCode,'1[0-9][0-6][0-9]');
IF regSearchCount >0 THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
ELSE
RETURN 'TRUE';
END IF;
END IF;
END IF;
IF NotificationType = 'Collateral' THEN
IF UserRoleCode ='WLOC' THEN
RETURN 'TRUE';
END IF;
-- check primary cto code holder
select count(*)
into count_v
from dual
where CtoCode IN
(SELECT DISTINCT code_value
FROM sml_user,
sml_team_member,
sml_user_profile,
sml_usrprof_cto_map,
code_value
WHERE sml_user.id = sml_team_member.user_id
AND sml_team_member.profile_id = sml_user_profile.id
AND sml_user_profile.id = sml_usrprof_cto_map.user_profile_id
AND sml_usrprof_cto_map.cto_code_id = code_value.id
AND sml_user.login_id = UserId);
IF count_v is not null and count_v > 0 then
return 'TRUE';
END IF;
-- check all other conditions
IF Can_User_Access_Customer(NotificationDesc,UserId,NotificationType,
UserRoleCode,UserMasterId,CtoCode,
SecCtoCode,UserProfTempIdCommercialInd,
UserProfTempIdCorporateInd,
UserProfTempStcfInd,
UserProfTempIdGsamInd) THEN
RETURN 'TRUE';
END IF;
ELSE
RETURN 'TRUE';
END IF;
RETURN 'FALSE';
END;
The query:
select *
FROM SML_NOTIFICATION_MAIN notification
where notification.DEPRECATED='N' and
(MAKER_ID = 'see_rm' OR
TO_CHAR(CTO_CODE) IN
(SELECT DISTINCT code_value
FROM sml_user,
sml_team_member,
sml_user_profile,
sml_usrprof_cto_map,
code_value
WHERE sml_user.id = sml_team_member.user_id AND
sml_team_member.profile_id = sml_user_profile.id AND
sml_user_profile.id = sml_usrprof_cto_map.user_profile_id AND
sml_usrprof_cto_map.cto_code_id = code_value.id AND
sml_user.login_id = 'see_rm' AND
Entity_Name != 'Collateral') OR
TO_CHAR(SEC_CTO_CODE) IN
(SELECT DISTINCT code_value
FROM sml_user,
sml_team_member,
sml_user_profile,
sml_usrprof_cto_map,
code_value
WHERE sml_user.id = sml_team_member.user_id AND
sml_team_member.profile_id = sml_user_profile.id AND
sml_user_profile.id = sml_usrprof_cto_map.user_profile_id AND
sml_usrprof_cto_map.cto_code_id = code_value.id AND
Entity_Name != 'Collateral' AND
sml_user.login_id ='see_rm') OR
ROLE_CODE in (select distinct CODE
from sml_user a,
code_value b
where a.role_id = b.id AND
login_id = 'see_rm') OR
SUBSTR(ROLE_CODE, 1, 4) in (select distinct CODE
from sml_user a,
code_value b
where a.role_id = b.id AND
login_id = 'see_rm') OR
SUBSTR(ROLE_CODE, 6, 4) IN (select distinct CODE
from sml_user a,
code_value b
where ENTITY_NAME = 'Insurance' OR
ENTITY_NAME = 'Collateral' AND
a.role_id = b.id AND
login_id = 'see_rm') OR
SUBSTR(ROLE_CODE, 11, 2) IN (select distinct CODE
from sml_user a,
code_value b
where a.role_id = b.id AND
login_id = 'see_rm') OR
TEAM_LEAD in (select to_char(a.id)
from sml_user a
where Entity_Name != 'Collateral' AND
a.login_id = 'see_rm') OR
RM_ID in (select to_char(a.id)
from sml_user a
where Entity_Name != 'Collateral' AND
ENTITY_NAME = 'PostApproval CP/Covnent' AND
DESCRIPTION != '30 days before due date' AND
a.login_id = 'see_rm') OR
(Entity_Name != 'Collateral' AND
RM_ID in (Select Rm_Id
From Vw_Sm_Rm_Team_Lead
Where Vw_Sm_Rm_Team_Lead.Rmtl_Id IN
(Select To_Char(A.Id)
From Sml_User A
Where A.Login_Id = 'see_rm'))) OR
(Entity_Name = 'Enquiry' AND
RM_ID IN (SELECT BCA_ID
FROM VW_SM_BCA_TEAM_LEAD
WHERE VW_SM_BCA_TEAM_LEAD.BCATL_ID IN
(SELECT TO_CHAR(A.Id)
FROM Sml_User A
WHERE A.Login_Id = 'see_rm'))) OR
GROUP_HEAD in (select to_char(a.id)
from sml_user a
where a.login_id = 'see_rm' AND
Entity_Name != 'Collateral') OR
(Entity_name != 'Collateral' AND
SECTOR_HEAD like ('%,'|| (select to_char(a.id) || ',' as ID
from sml_user a
where a.login_id = 'see_rm' AND
status='ACTIVE' AND
master_id is null) || '%')) OR
(Entity_Name = 'Collateral' AND
IS_NOTIFICATION_ACCESS_PASSED(DESCRIPTION,
'see_rm',
Entity_Name,
'1176',
'RM',
TO_CHAR(CTO_CODE),
TO_CHAR(SEC_CTO_CODE),
'N','N','N','N') = 'TRUE') OR
(RM_ID in (select rm_id
from VW_SM_RM_TEAM_LEAD
where rmtl_id IN (Select Distinct Su.Id As Rmtl_Id
FROM sml_user su
INNER JOIN sml_team_member MEMBER
ON su.id=member.user_id
Inner Join Sml_Team Team
On Member.Team_Id=Team.Id AND
Team.Team_Role_Id =
(SELECT ID
FROM code_value
WHERE code='RMTL' AND
status='ACTIVE' AND
master_id IS NOT NULL AND
code_set_value_id =
(SELECT ID
FROM code_set
WHERE CODE = 'TEAM_ROLE' AND
master_id IS NOT NULL))
Inner Join Sml_Team_Child PARENT
On Team.Id=Parent.Child_Id
INNER JOIN sml_team_member grop
ON grop.team_id=parent.parent_id
INNER JOIN sml_team st
ON st.id=grop.team_id
Where Su.Status = 'ACTIVE' AND
St.Status='ACTIVE' AND
grop.user_id =
(select to_char(a.id)
from sml_user a
where a.master_id is null AND
a.status='ACTIVE' AND
a.login_id = 'see_rm'))) AND
Entity_Name != 'Collateral' AND
((Entity_Name = 'Implementation Instruction' AND
IS_NOTIFICATION_ACCESS_PASSED(DESCRIPTION,
'see_rm',
Entity_Name,
'1176',
'RM',
TO_CHAR(CTO_CODE),
TO_CHAR(SEC_CTO_CODE),
'N','N','N','N') = 'TRUE') OR
(Entity_Name = 'Post Disbursement') OR
(ENTITY_NAME = 'PostApproval CP/Covnent' AND
DESCRIPTION = '7 days before due date') OR
(ENTITY_NAME = 'Facility' AND
DESCRIPTION != '2 Days Due for expiry of Facility') OR
(ENTITY_NAME = 'Insurance') OR
(ENTITY_NAME = 'Call Report' AND
DESCRIPTION = '2 days before exceeded by 11 months'))))
****************************************Execution plan of above query *****************
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=294 Card=17 K Bytes=3 M)
1 0 FILTER
2 1 TABLE ACCESS FULL UOBCM.SML_NOTIFICATION_MAIN (Cost=294 Card=37 K Bytes=6 M)
3 1 FILTER
4 3 NESTED LOOPS
5 4 NESTED LOOPS (Cost=47 Card=1 Bytes=80)
6 5 HASH JOIN (Cost=23 Card=24 Bytes=1 K)
7 6 NESTED LOOPS (Cost=8 Card=12 Bytes=432)
8 7 HASH JOIN (Cost=8 Card=12 Bytes=384)
9 8 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=3 Bytes=72)
10 9 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
11 8 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=1 K Bytes=8 K)
12 7 INDEX UNIQUE SCAN UOBCM.PK_SML_USER_PROFILE (Cost=0 Card=1 Bytes=4)
13 6 VIEW UOBCM.index$_join$_005 (Cost=15 Card=1 K Bytes=14 K)
14 13 HASH JOIN
15 14 INDEX FAST FULL SCAN UOBCM.IDX_USRPROFCTO_USRPROF (Cost=6 Card=1 K Bytes=14 K)
16 14 INDEX FAST FULL SCAN UOBCM.IDX_USRPROFCTO_CTO (Cost=11 Card=1 K Bytes=14 K)
17 5 INDEX UNIQUE SCAN UOBCM.PK_CODE_VALUE (Cost=0 Card=1)
18 4 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=1 Card=1 Bytes=36)
19 1 FILTER
20 19 NESTED LOOPS
21 20 NESTED LOOPS (Cost=47 Card=1 Bytes=80)
22 21 HASH JOIN (Cost=23 Card=24 Bytes=1 K)
23 22 NESTED LOOPS (Cost=8 Card=12 Bytes=432)
24 23 HASH JOIN (Cost=8 Card=12 Bytes=384)
25 24 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=3 Bytes=72)
26 25 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
27 24 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=1 K Bytes=8 K)
28 23 INDEX UNIQUE SCAN UOBCM.PK_SML_USER_PROFILE (Cost=0 Card=1 Bytes=4)
29 22 VIEW UOBCM.index$_join$_010 (Cost=15 Card=1 K Bytes=14 K)
30 29 HASH JOIN
31 30 INDEX FAST FULL SCAN UOBCM.IDX_USRPROFCTO_USRPROF (Cost=6 Card=1 K Bytes=14 K)
32 30 INDEX FAST FULL SCAN UOBCM.IDX_USRPROFCTO_CTO (Cost=11 Card=1 K Bytes=14 K)
33 21 INDEX UNIQUE SCAN UOBCM.PK_CODE_VALUE (Cost=0 Card=1)
34 20 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=1 Card=1 Bytes=36)
35 1 NESTED LOOPS
36 35 NESTED LOOPS (Cost=5 Card=1 Bytes=39)
37 36 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=3 Card=3 Bytes=75)
38 37 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
39 36 INDEX UNIQUE SCAN UOBCM.PK_CODE_VALUE (Cost=0 Card=1)
40 35 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=1 Card=1 Bytes=14)
41 1 NESTED LOOPS
42 41 NESTED LOOPS (Cost=5 Card=1 Bytes=39)
43 42 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=3 Card=3 Bytes=75)
44 43 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
45 42 INDEX UNIQUE SCAN UOBCM.PK_CODE_VALUE (Cost=0 Card=1)
46 41 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=1 Card=1 Bytes=14)
47 1 NESTED LOOPS (Cost=9 Card=3 Bytes=117)
48 47 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=4 Card=4 Bytes=56)
49 48 INDEX RANGE SCAN UOBCM.IDX_CV_CDSTATUSID (Cost=2 Card=4)
50 47 TABLE ACCESS FULL UOBCM.SML_USER (Cost=5 Card=2 Bytes=50)
51 1 NESTED LOOPS
52 51 NESTED LOOPS (Cost=5 Card=1 Bytes=39)
53 52 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=3 Card=3 Bytes=75)
54 53 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
55 52 INDEX UNIQUE SCAN UOBCM.PK_CODE_VALUE (Cost=0 Card=1)
56 51 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=1 Card=1 Bytes=14)
57 1 FILTER
58 57 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=1 Bytes=24)
59 58 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
60 1 FILTER
61 60 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=1 Bytes=24)
62 61 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
63 1 FILTER
64 63 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=1 Bytes=24)
65 64 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
66 1 NESTED LOOPS
67 66 NESTED LOOPS (Cost=28 Card=1 Bytes=95)
68 67 HASH JOIN (Cost=27 Card=1 Bytes=76)
69 68 NESTED LOOPS
70 69 NESTED LOOPS (Cost=24 Card=7 Bytes=476)
71 70 NESTED LOOPS (Cost=16 Card=8 Bytes=472)
72 71 HASH JOIN (Cost=10 Card=12 Bytes=612)
73 72 NESTED LOOPS (Cost=6 Card=3 Bytes=129)
74 73 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=2 Card=1 Bytes=19)
75 74 INDEX UNIQUE SCAN UOBCM.PK_SML_USER (Cost=1 Card=1)
76 73 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=3 Bytes=72)
77 76 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
78 72 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=1 K Bytes=8 K)
79 71 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM_CHILD (Cost=1 Card=1 Bytes=8)
80 79 INDEX RANGE SCAN UOBCM.IDX_TCHILD_TEAM (Cost=0 Card=1)
81 70 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
82 69 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=9)
83 82 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=3 Card=1 Bytes=35)
84 83 INDEX RANGE SCAN UOBCM.IDX_CV_CS (Cost=1 Card=19)
85 84 TABLE ACCESS FULL UOBCM.CODE_SET (Cost=18 Card=1 Bytes=38)
86 68 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=4 Bytes=32)
87 67 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
88 66 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=19)
89 1 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=1 Bytes=43)
90 89 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
91 1 NESTED LOOPS
92 91 NESTED LOOPS (Cost=31 Card=1 Bytes=142)
93 92 NESTED LOOPS (Cost=30 Card=1 Bytes=123)
94 93 NESTED LOOPS (Cost=29 Card=1 Bytes=104)
95 94 NESTED LOOPS (Cost=26 Card=3 Bytes=288)
96 95 NESTED LOOPS (Cost=22 Card=4 Bytes=348)
97 96 HASH JOIN (Cost=20 Card=5 Bytes=395)
98 97 NESTED LOOPS
99 98 NESTED LOOPS (Cost=16 Card=4 Bytes=284)
100 99 NESTED LOOPS (Cost=12 Card=4 Bytes=208)
101 100 NESTED LOOPS (Cost=10 Card=2 Bytes=88)
102 101 NESTED LOOPS (Cost=7 Card=3 Bytes=105)
103 102 NESTED LOOPS (Cost=5 Card=4 Bytes=108)
104 103 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=2 Card=1 Bytes=19)
105 104 INDEX UNIQUE SCAN UOBCM.PK_SML_USER (Cost=1 Card=1)
106 103 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=4 Bytes=32)
107 106 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=4 Card=1 Bytes=43)
108 107 INDEX RANGE SCAN UOBCM.IDX_USR_LOGINID (Cost=1 Card=3)
109 102 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM_CHILD (Cost=1 Card=1 Bytes=8)
110 109 INDEX RANGE SCAN UOBCM.IDX_TCHILD_TEAM (Cost=0 Card=1)
111 101 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=9)
112 111 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
113 111 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=3 Card=1 Bytes=35)
114 113 INDEX RANGE SCAN UOBCM.IDX_CV_CS (Cost=1 Card=19)
115 114 TABLE ACCESS FULL UOBCM.CODE_SET (Cost=18 Card=1 Bytes=38)
116 100 INDEX RANGE SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=1 Card=2 Bytes=16)
117 99 INDEX UNIQUE SCAN UOBCM.PK_SML_USER (Cost=0 Card=1)
118 98 TABLE ACCESS BY INDEX ROWID UOBCM.SML_USER (Cost=1 Card=1 Bytes=19)
119 97 INDEX FAST FULL SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=3 Card=1 K Bytes=8 K)
120 96 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM_CHILD (Cost=1 Card=1 Bytes=8)
121 120 INDEX RANGE SCAN UOBCM.IDX_TCHILD_TEAM (Cost=0 Card=1)
122 95 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=9)
123 122 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
124 122 TABLE ACCESS BY INDEX ROWID UOBCM.CODE_VALUE (Cost=3 Card=1 Bytes=35)
125 124 INDEX RANGE SCAN UOBCM.IDX_CV_CS (Cost=1 Card=19)
126 125 TABLE ACCESS FULL UOBCM.CODE_SET (Cost=18 Card=1 Bytes=38)
127 94 INDEX RANGE SCAN UOBCM.IDX_TMBR_TMUSERPF (Cost=1 Card=1 Bytes=8)
128 93 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=19)
129 128 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
130 92 INDEX UNIQUE SCAN UOBCM.PK_SML_TEAM (Cost=0 Card=1)
131 91 TABLE ACCESS BY INDEX ROWID UOBCM.SML_TEAM (Cost=1 Card=1 Bytes=19)
132 1 NESTED LOOPS
133 132 NESTED LOOPS (Cost=28 Card=1 Bytes=95)
134 133 HASH JOIN (Cost=27 Card=1 Bytes=76)
135 134 NESTED LOOPS
136 135 NESTED LOOPS (Cost=24 Card=7 Bytes=476)
137 136 NESTED LOOPS (
This is a reasonably large query with lots of sub queries, you'd need to do an explain plan on it and then start chipping away at the "slow" bits. It may be query to extract the logic from your stored procedure and embed it in your query. 100,000 rows is not much, you should be able to tune this a lot.
Related
I'm trying to write a PLSQL query that will in two separate columns print random integers.
It will print 1000 numbers total (random 1 - 50 in each row).
What I need to figure out is how I after this has been done, replace the second column with either "yes" or "no" if it matches the first column
Such as:
Col A Col B
10 NO(42)
32 NO(12)
25 YES(25)
And so on.
This is my code:
CREATE TABLE table
(random_num INTEGER NOT NULL,
match INTEGER NOT NULL);
Declare
CURSOR cur_ IS
(Select
random_num,
match
from table);
Begin
FOR rec_ IN 1..1000
LOOP
INSERT INTO "table" (random_num,match) VALUES (DBMS_RANDOM.VALUE(1,50),DBMS_RANDOM.VALUE(1,50));
END LOOP;
END;
Now this works as I get two 1000 rows of each column with random numbers, but I need to implement this select:
SELECT random_num, CASE WHEN random_num = match THEN 'yes' ELSE 'no' END as match
FROM table
Into the loop so. Any takers on how I can do?
There's something wrong in what you said. You can't put yes (string) into an INTEGER datatype column.
This makes more sense:
Sample table:
SQL> CREATE TABLE test
2 (
3 random_num_1 INTEGER NOT NULL,
4 random_num_2 INTEGER NOT NULL,
5 match VARCHAR2 (3) NOT NULL
6 );
Table created.
Procedure: use local variables to store random numbers; then it is easy to compare them.
SQL> DECLARE
2 val1 NUMBER;
3 val2 NUMBER;
4 BEGIN
5 FOR i IN 1 .. 10 --> change it to 1000
6 LOOP
7 val1 := DBMS_RANDOM.VALUE (1, 50);
8 val2 := DBMS_RANDOM.VALUE (1, 50);
9
10 INSERT INTO test (random_num_1, random_num_2, match)
11 VALUES (val1,
12 val2,
13 CASE WHEN val1 = val2 THEN 'yes' ELSE 'no' END);
14 END LOOP;
15 END;
16 /
PL/SQL procedure successfully completed.
Result:
SQL> SELECT * FROM test;
RANDOM_NUM_1 RANDOM_NUM_2 MAT
------------ ------------ ---
45 31 no
40 48 no
43 27 no
49 41 no
6 38 no
5 18 no
18 35 no
15 34 no
11 19 no
37 39 no
10 rows selected.
SQL>
First if you want to produce random integers from 1 to 50 that are equaly distributed, you must be carefull.
[DBMS_RANDOM.VALUE (1, 50)][1] returns a decimal number greater than or equal than 1 and less than 50.
example
select DBMS_RANDOM.VALUE (1, 50) col from dual;
COL
----------
30,4901593
You cast the result in INTEGER type that performs rounding, so you will see all numbers, but the 1 and 50 will appear only half frequenty as other numbers.
So a better way to get random integers 1 .. 50 is 1 + trunc(50*DBMS_RANDOM.VALUE)
VALUE without parameters returns [0,1)
Also typically if you do not need to use PL/SQL do not use it
create table tab1 as
select 1 + trunc(50*DBMS_RANDOM.VALUE) col1, 1 + trunc(50*DBMS_RANDOM.VALUE) col2
from dual connect by level <= 10 /* increase as much rows are needed */
and add the MATCH column as virtual
alter table tab1
add (match varchar2(3) generated always as (
case when col1 = col2 then 'YES' else 'NO' end ) virtual);
COL1 COL2 MAT
---------- ---------- ---
33 6 NO
26 28 NO
35 22 NO
30 27 NO
17 45 NO
31 4 NO
11 21 NO
2 48 NO
35 25 NO
39 15 NO
Hi Guys How can i split a parameter in plsql purun_kod is like 100,150,255,777 and i wanna split it and assign to v_urun_kod
thanks for your help.
My code is somewhat like:
function police_ara( purun_kod in acente.levha_no%type,
ppolice_no in varchar2) return sys_refcursor is
vret sys_refcursor;
v_urun_kod varchar(1000);
begin
v_urun_kod := purun_kod;
open vret for
with policeler as
(select distinct ph.police_hareket_id ph_police_hareket_id,
p.urun_kod
(select max(pho.police_hareket_id) from police_hareket_otr pho
where pho.police_hareket_id = ph.police_hareket_id
and (pho.durum_kod1 = 0 or pho.durum_kod2 = 0 or pho.durum_kod3 = 0 or pho.durum_kod4 = 0)) pho_police_hareket_id,
ph.odeme_arac_kod,
ph.police_id
from police p
inner join police_hareket ph
and (ph.ekbelge_no>0 or (select count(1)
from police_kotasyon pk
where pk.police_hareket_id = ph.police_hareket_id
and pk.kotasyon_seviyesi = 3
and rownum = 1)>0)
left join police_prim pp
on (pp.police_hareket_id = ph.police_hareket_id and pp.para_birim_kod = ph.para_birim_kod)
left join musteri_rol mr
on (mr.musteri_rol_id = pa.acente_id)
where (p.urun_kod = purun_kod or purun_kod is null)
and(p.police_no = ppolice_no or ppolice_no is null)
select urun_kod,
acente_kod,
brut_prim
from policeler
left join police_musteri pm_sg
on pm_sg.police_hareket_id = ph_police_hareket_id
and pm_sg.rol_id = pck_const_rol.sigortali
and pm_sg.sira_no = 1
left join musteri m_sg
on (m_sg.musteri_id = pm_sg.musteri_id)
order by police_id;
return vret;
end;
This is how to split a comma-separated values string into rows. It is a SQL*Plus example, just to show how it works:
SQL> var purun_kod varchar2(100);
SQL> exec :purun_kod := '100,150,255,777';
PL/SQL procedure successfully completed.
SQL> select regexp_substr(:purun_kod, '[^,]+', 1, level) urun_kod
2 from dual
3 connect by level <= regexp_count(:purun_kod, ',') + 1;
URUN_KOD
----------------------------------------------------------------------
100
150
255
777
SQL>
Currently, code you posted doesn't make much sense as you never use v_urun_kod. As the function returns ref cursor, there's no much sense in running that code for each separate value; you might do that in a loop, but that wouldn't work as you'd want it to (at least, I think so).
Looking at it, I guess that something like this might do what you're looking for:
SQL> create or replace
2 function police_ara( purun_kod in varchar2,
3 ppolice_no in varchar2)
4 return sys_refcursor is
5 vret sys_refcursor;
6 -- v_urun_kod varchar(1000); --> no need for that variable any more
7 begin
8 open vret for
9 with policeler as
10 (select distinct ph.police_hareket_id ph_police_hareket_id,
11 p.urun_kod,
12 (select max(pho.police_hareket_id)
13 from police_hareket_otr pho
14 where pho.police_hareket_id = ph.police_hareket_id
15 and ( pho.durum_kod1 = 0
16 or pho.durum_kod2 = 0
17 or pho.durum_kod3 = 0
18 or pho.durum_kod4 = 0
19 )
20 ) pho_police_hareket_id,
21 --
22 ph.odeme_arac_kod,
23 ph.police_id
24 from police p
25 --> this is new
26 join (select regexp_substr(purun_kod, '[^,]+', 1, level) urun_kod
27 from dual
28 connect by level <= regexp_count(purun_kod, ',') + 1
29 ) x on x.urun_kod = p.urun_kod
30 --> end of "this is new"
31 inner join police_hareket ph on 1 = 1 --> you're missing join condition here
32 and ( ph.ekbelge_no > 0
33 or (select count(1)
34 from police_kotasyon pk
35 where pk.police_hareket_id = ph.police_hareket_id
36 and pk.kotasyon_seviyesi = 3
37 and rownum = 1
38 ) > 0
39 )
40 left join police_prim pp
41 on ( pp.police_hareket_id = ph.police_hareket_id
42 and pp.para_birim_kod = ph.para_birim_kod
43 )
44 left join musteri_rol mr
45 on (mr.musteri_rol_id = pa.acente_id)
46 where ( p.urun_kod = purun_kod
47 or purun_kod is null
48 )
49 and ( p.police_no = ppolice_no
50 or ppolice_no is null
51 )
52 )
53 select urun_kod,
54 acente_kod,
55 brut_prim
56 from policeler
57 left join police_musteri pm_sg
58 on pm_sg.police_hareket_id = ph_police_hareket_id
59 and pm_sg.rol_id = pck_const_rol.sigortali
60 and pm_sg.sira_no = 1
61 left join musteri m_sg
62 on (m_sg.musteri_id = pm_sg.musteri_id)
63 order by police_id;
64 return vret;
65 end;
66 /
Warning: Function created with compilation errors.
Pay attention to the following:
line 6: there's no need for v_urun_kod variable any more
lines 25 - 30: this is a new piece of code which utilizes the above posted example. That SELECT is used as an inline view and joined with the police table's urun_kod column (at least, that's what I think you should do)
line 31: you're missing the ON clause here; fix it yourself, I don't know what should that be
the function is created with compilation errors as I don't have your tables; other than that, it might be OK:
SQL> show err
Errors for FUNCTION POLICE_ARA:
LINE/COL ERROR
-------- -----------------------------------------------------------------
8/5 PL/SQL: SQL Statement ignored
43/21 PL/SQL: ORA-00942: table or view does not exist
SQL>
I have tableA:
id colA colB(Chained)
1 11 17
2 22 41
3 44 42
4 82 43
5 17 13
6 20 85
7 26 90
8 13 19
9 19 82
I want result set of chained data like below from hive query:
id ChainedCol(from colA) colB
1 11 17
5 17 13
8 13 19
9 19 82
4 82 43
I used a common table expression and do a join to itself based on colA and colB. Then use union to remove duplicates.
with tmp as
( select a.id id_a, a.colA colA_a, a.colB colB_a, b.id id_b, b.colA colA_b, b.colB colB_b
from tbl a
join tbl b
on a.colA=b.colB
)
select id_b id,colA_b colA,colB_b colB
from tmp
union
select id_a,colA_a,colB_a
from tmp;
I have a table structure
ID Col_1 col_2 col_3 col_4
1 34 23 45 32
2 20 19 67 18
3 40 10 76 86
I here want the max value from col_1,col_,col_3,col_4 so my output looks like
ID Col_1 col_2 col_3 col_4 max
1 34 23 45 32 45
2 20 19 67 18 67
3 40 10 76 86 86
any help would be much appreciated.
Use a Modified Java Script Value step with the following code:
var max = Math.max(col_1,col_2,col_3,col_4);
You can use Memory Group By or Group By steps in Pentaho. Use the aggregation method as "Maximum" based on your grouping id.
I have a table with a column varchar2(4000), where I got a problem inserting data, such that:
ORA-12899: value too large for column "XXX"."YYY"."ZZZ" (actual: 2132, maximum: 2048)
When I run
select * from user_tab_columns where table_name = 'YYY'
I can see a CHAR_LENGTH column of size 2048, but other than that I have no trace why it would preempt itself?
CHARACTER_SET_NAME is CHAR_CS, but content is mostly base64 encoded.. Any clues how to overcome this problem ?
Regards
Update:
Here's the full user_tab_columns, sorry for the indentation.
TABLE_NAME COLUMN_NAME DATA_TYPE DATA_TYPE_MOD DATA_TYPE_OWNER DATA_LENGTH DATA_PRECISION DATA_SCALE NULLABLE COLUMN_ID DEFAULT_LENGTH DATA_DEFAULT NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS NUM_BUCKETS LAST_ANALYZED SAMPLE_SIZE CHARACTER_SET_NAME CHAR_COL_DECL_LENGTH GLOBAL_STATS USER_STATS AVG_COL_LEN CHAR_LENGTH CHAR_USED V80_FMT_IMAGE DATA_UPGRADED HISTOGRAM
YYY ZZZ VARCHAR2 <null> <null> 4,000 <null> <null> Y 7 <null> <null> 15 41 42 43 44 45 46 47 4d 49 49 46 75 7a 43 43 42 4b 4f 67 41 77 49 42 41 67 49 45 54 41 4c 4d 68 6a 41 4e 42 67 6b 71 0.06667 662 1 2013-06-03 929 CHAR_CS 4,000 NO NO 1,394 2,048 C NO YES NONE
The 2048 mark comes from the CHAR_LENGTH column, and CHAR_USED is C..
Update:
Managed to get the initial DDL
CREATE TABLE "XXX", "YYY"
(
...
"ZZZ" VARCHAR2 (2048 CHAR)
...
)
But I still have no clue as to how to adjust that figure?
Would it help with a simple alter table and set the varchar2(3192 CHAR)?
Your column is limited to both 2048 characters and 4000 bytes. Regardless of your character length semantics, ALL_TAB_COLUMNS.DATA_LENGTH is "Length of the column (in bytes)". AL32UTF8 can use up to 4 bytes per character, so DATA_LENGTH will be the number of characters * 4. Except it will never be larger than the Oracle limit of 4000.
For example:
create table test1(a varchar2(1 char));
create table test2(a varchar2(2 char));
create table test3(a varchar2(1000 char));
create table test4(a varchar2(4000 char));
select table_name, data_length
from all_tab_columns
where table_name like 'TEST_';
TABLE_NAME DATA_LENGTH
---------- -----------
TEST1 4
TEST2 8
TEST3 4000
TEST4 4000
You can fix your problem with alter table xxx.yyy modify zzz varchar2(4000 char);.