As The Oracle Developer-Don't Be A Target For Slow Performance
As The Oracle Developer-Don't Be A Target For Slow Performance
2
(1) Basic trouble spots for sql queries
3
(1) Basic trouble spots for sql queries
When processing a query, Oracle ranks the indexes, and determines which one
to use. When setting a column equal to a literal string, this is the highest ranking,
And chances are that the index to that column will be used.
The next highest ranking is greater than or less than (>, <)
A literal.
There are several factors in THE WHERE CLAUSE of a query that can cause
An index not to be used:
1. Using a function on the left side.
Substr(plant_code,1,5) = ‘AP05A’, Since there is a function around the column,
the index will not be used. This includes Oracle functions such as to_char,
to_number, ltrim, rtrim, instr, trunc, rpad , lpad
2. Comparing incompatible data.
Employee_num = ‘1’
There will be an implicit to_char conversion used.
plant_code = 1234
There will be an implicit to_num conversion used.
3. Using is null and is not null .
Select *
FROM s_emp 4
WHERE
Basic trouble spots for sql queries
(continued)
(4) Adding additional criteria in the where clause for a column name that is of a
different index
Select * from s_emp
where title= ‘Manager’
and Department = 500 Column title and department have
separate indexes on these columns.
5
Solutions to
Basic trouble spots for sql queries
Problem:
1. Using a function on the left side.
Select * from s_emp
Where substr(title,1,3) = ‘Man’;
Solution:
Use like
Select * from s_emp
Where title like ‘Man%’;
Solution:
Select * from s_emp
Where employee_number = 3;
7
Solutions to
Basic trouble spots for sql queries
continued)
Problem:
. Using null and not null
Select * from s_emp
Where title is not null;
olution:
Select * from s_emp
where title >= ‘ ‘;
9
(2) Explain plan:
Explain plan is a utility that will show you what indexes are being used
In the table AND what type of scan is being done on the table
(full table scan, index range scan etc..)
(1) Make sure you have the plan_table
desc plan_table.
(2) If you do not – run the explain plan utility
go to the
/usr/oracle/product/8.1.6.64/rdbms/admin
or
/$oracle_home/rdbms/admin
(3) Run utlxplan.sql in sql (I.e. @ utlxplan.sql )
10
(2) Explain plan: (continued)
Example 1:
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_VEHICLE_1
SORT AGGREGATE
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_VEHICLE_1
EXECUTION_PATH
--------------------------------------------------------------------------------
SORT AGGREGATE
TABLE ACCESS FULL VEHICLE
SORT AGGREGATE
SORT AGGREGATE
TABLE ACCESS FULL VEHICLE --> NOTICE A FULL TABLE SCAN
12
(3) Tuning of SQL queries
1. Find out what indexes are on the tables
2. Run explain plan
3. Make sure most restrictive indexes are being used by avoiding SQL trouble spots.
4. Make sure most restrictive indexes are being used by using Oracle hints.
5. For multi-table joins, join everything that can be joined together.
6. Use unions instead of outer joins
7. Use “exists” subquery if only selecting items from 1 table.
The query:
select count(*) from vehicle
Where assembly_location_code = 'AP24A'
and production_date = '06-apr-01';
13
(3) Tuning of SQL queries (cont)
(1) Find out what indexes are on this table--- CRUCIAL
Samle output:
Column_name Index name
Assembly_location_code FKI_VEHICLE_1
Production_date FK_PRODUCTION_DATE
Vehicle id FKI_PRODUCTION_DATE
Vehicle_id PK_VEHICLE
14
@explain.sql
@explain2.sql
(3) Tuning of SQL queries (cont)
Results of explain plan:
EXECUTION_PATH
--------------------------------------------------------------------------------
SORT AGGREGATE
TABLE ACCESS FULL VEHICLE
SORT AGGREGATE
SORT AGGREGATE
TABLE ACCESS FULL VEHICLE Notice that the full table scan is performed
15
(3) Tuning of SQL queries (cont)
(3) Enable indexes to be used – ELIMINATE “TABLE ACCESS FULL “ (continued)
Results of explain plan:
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_PRODUCTION_DATE
SORT AGGREGATE
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_PRODUCTION_DATE
16
(3) Tuning of SQL queries (cont)
(3) Enable indexes to be used – ELIMINATE “TABLE ACCESS FULL “ (continued)
Results of explain plan:
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_VEHICLE_1
SORT AGGREGATE
TABLE ACCESS BY INDEX ROWID VEHICLE
INDEX RANGE SCAN FKI_VEHICLE_1 Notice that the most restrictive index is used now.
17
(3) Tuning of SQL queries (cont)
(3) Enable indexes to be used – ELIMINATE “TABLE ACCESS FULL “
(continued)
COUNT(*)
----------
787
18
CONTINUING ON about INDEXES:
This query takes a while because the proper index is NOT used on the vehicle table:
19
WE NEED AN INDEX that uses BOTH production date
And ASSEMBLY_LOCATION_CODE:
SQL> list
1 select column_name, index_name from all_ind_columns
2 where index_name = 'I_VEHICLE_5'
3* and table_name = 'VEHICLE'
SQL> /
COLUMN_NAME
--------------------------------------------------------------------------------
INDEX_NAME
------------------------------
PRODUCTION_DATE
I_VEHICLE_5
ASSEMBLY_LOCATION_CODE
I_VEHICLE_5
20
Now, if we use the proper index (I_VEHICLE_5) the query
Will be FAST
COUNT(*)
----------
1803
Elapsed: 00:00:00.46
21
(3) Tuning of SQL queries (cont)
MUTI-Table queries
1) Make sure everything that can be joined is joined (for 3 or more tables)
Instead of:
select * from t1, t2, t3
where t1.emp_id = t2.emp_id
and t2.emp_id = t3.emp_id
add:
select * from t1, t2, t3
where t1.emp_id = t2.emp_id
and t2.emp_id = t3.emp_id
and t1.emp_id = t3.temp_id;
22
(4) Tuning of SQL queries
Real life example
THE QUERY
SELECT mfal_vl_code,
mod_yr,
effective_out_date,
mfal_gvw_mkt_der_code,
mfal_market_code,
mfal_series_trim_code,
mfal_bs_code,mfal_eng_code,
mfal_trans_code,
mfal_drv_code,
mfal_feature_code,
sum(decode(ucc_qtrly_volume, 0, 0, (weight/ucc_qtrly_volume))) rate
from cpat_gvp_extract_main
where substr(mfal_feature_code, 1, 1) not in
( '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'P', 'X' )
and substr( mfal_feature_code, 1, 3) not in
( 'EN ', 'TR ', 'DR ', 'MD ', 'SE ', 'BS ', 'CA ', 'VS ', 'AAA', 'AAG',
'AAF', 'AAH' )
and substr( mfal_feature_code, 1, 2) not in ( 'WA', 'WS' )
and mfal_feat_family_code not like 'PTR%'
and ( mfal_series_trim_code like 'AAA%'
or mfal_series_trim_code like 'VS %' )
and ( substr( mfal_feature_code, 4, 1) not in
( '1', '2', '3', '4', '5', '6', '7', '8', '9')
or substr( mfal_feature_code, 5, 1) not in
( '1', '2', '3', '4', '5', '6', '7', '8', '9')
)
Group by mfal_vl_code,
mod_yr,
effective_out_date,
mfal_gvw_mkt_der_code,
mfal_market_code,
mfal_series_trim_code,
mfal_bs_code,
mfal_eng_code,
mfal_trans_code,
mfal_drv_code, 23
mfal_feature_code ;
(4) Tuning of SQL queries
Real life example (continued)
1) The indexes are:
Select column_name, index_name from all_ind_columns
Where table_name =‘CPAT_GVP_EXTRACT_MAIN ’;
Samle output:
Column_name Index name
MFAL_FEATURE_CODE CGEM_CFC_IND_X
MFAL_VL_CODE CGEM_VL_IND_X
MOD_YR CGEM_VL_IND_X
MFAL_FEAT_FAMILY_CODE CGEM_VL_IND_X
MFAL_VL_CODE CGEM_VL_IND_X
MOD_YR CGEM_VL_IND_X
24
(4) Tuning of SQL queries
Real life example (continued)
The tuned query:
set timing on
SELECT
/*+ index (cpat_gvp_extract_main CGEM_CFC_IND_X) */ -> Notice index hint
mod_yr,
effective_out_date,
mfal_gvw_mkt_der_code,
mfal_market_code,
mfal_series_trim_code,
mfal_bs_code,mfal_eng_code,
mfal_trans_code,
mfal_drv_code,
mfal_feature_code,
sum(decode(ucc_qtrly_volume, 0, 0, (weight/ucc_qtrly_volume))) rate
from cpat_gvp_extract_main
where mfal_feature_code not like '1%'
and mfal_feature_code not like '2%'
and mfal_feature_code not like '3%'
and mfal_feature_code not like '4%'
and mfal_feature_code not like '5%‘ Notice the use of like instead of substr.
and mfal_feature_code not like '6%'
and mfal_feature_code not like '7%'
and mfal_feature_code not like '8%'
and mfal_Feature_code not like '9%'
and mfal_feature_code not like '0%'
and mfal_feature_code not like 'P%'
and mfal_feature_code not like 'X%'
25
(4) Tuning of SQL queries
Real life example (continued)
and mfal_feature_code not like 'EN%'
and mfal_feature_code not like 'TR%'
and mfal_Feature_code not like 'DR%'
and mfal_feature_code not like 'MD%'
and mfal_feature_code not like 'SE%'
and mfal_feature_code not like 'BS%'
and mfal_Feature_code not like 'CA%'
and mfal_feature_code not like 'VS%'
and mfal_Feature_code not like 'AAA%'
and mfal_feature_code not like 'AAG%'
and mfal_feature_code not like 'AAF%'
and mfal_Feature_code not like 'AAH%'
and mfal_feature_code not like 'WA%'
and mfal_feature_code not like 'WS%'
and mfal_feat_family_code not like 'PTR%'
and (( mfal_series_trim_code like 'AAA%'
or mfal_series_trim_code like 'VS %' )
and (mfal_feature_code not like '___1%'
and mfal_feature_code not like '___2%'
and mfal_feature_code not like '___3%'
and mfal_feature_code not like '___4%'
and mfal_feature_code not like '___5%'
and mfal_feature_code not like '___6%'
and mfal_feature_code not like '___7%'
and mfal_feature_code not like '___8%'
and mfal_feature_code not like '___9%')
26
(4) Tuning of SQL queries
Real life example (continued)
OR (
mfal_feature_code not like '___1%'
and mfal_feature_code not like '____2%'
and mfal_feature_code not like '____3%'
and mfal_feature_code not like '____4%'
and mfal_feature_code not like '____5%'
and mfal_feature_code not like '____6%'
and mfal_feature_code not like '____7%'
and mfal_feature_code not like '____8%'
and mfal_feature_code not like '____9%'))
Group by mfal_vl_code,
mod_yr,
effective_out_date,
mfal_gvw_mkt_der_code,
mfal_market_code,
mfal_series_trim_code,
mfal_bs_code,
mfal_eng_code,
mfal_trans_code,
mfal_drv_code,
mfal_feature_code ;
27
(4) Tuning of SQL queries
Real life example (continued)
Multi-table join example:
SELECT raw_part_number, price_type_code, IB.BOM_RECNO RECNO,vV.VEHICLE_ID,IB.PART_ID,IB.PARENT_PART_ID,
BOM_LEVEL PART_LEVEL,IB.PART_USING_LOCATION_CODE,IB.SHIP_FROM_LOCATION_CODE,
LPAD(' ',2*(BOM_LEVEL-1)) || PART_PREFIX || '-' ||PART_BASE || '-'
|| PART_SUFFIX || '-' || PART_CONTROL_NUMBER INDENTED_PART_NUMBER,
IB.FORD_AFFILIATE_CODE,IB.MISSING_STRUCTURE_CODE,IB.BOM_ID VIN,
IB.EFFECTIVE_DATE PRODUCTION_DATE,IB.CPSC_CODE,IB.TOP_CPSC_CODE,PART_BASE,
PART_PREFIX,PART_SUFFIX,PART_CONTROL_NUMBER,ULP.PART_DESCRIPTION,
ULP.PART_TYPE,PI.COMMODITY_CODE,L.LOCATION_NAME SUPPLIER_NAME,
ULP.PART_UNIT_OF_MEASURE,IB.USAGE_QUANTITY,IB.WEIGHT,
IB.NOTES,IB.ALTERNATE_PART_PERCENT, IB.NEXT_AVAIL_BURDEN_DEPT,
IB.PERCENT_OF_BUSINESS,IB.RAW_PERCENT_OF_BUSINESS,
ULP.PSEUDO_ALTERNATE_PART_CODE, ULP.WAREHOUSE_PART_FLAG,
ULP.BURDEN_DEPARTMENT_NUMBER, IB.SUPPLIER_TYPE, IB.MANUFACTURING_PLANT_CODE,
PO.PRICE PO_PRICE,
PO.CURRENCY_CODE PO_CURRENCY_CODE,
PO.PO_EFFECTIVE_DATE, PO.CHARGE_FROM_DATE PO_CHARGE_FROM_DATE,
PO.PURCHASING_MANAGER_CODE PO_PURCHASING_MANAGER_CODE,
PO.PURCHASING_MANAGER_CDSID PO_PURCHASING_MANAGER_CDSID,
PO.BUYER_CODE PO_BUYER_CODE,
PO.BUYER_CDSID PO_BUYER_CDSID,
PO.RETURN_CODE PO_RETURN_CODE,
PO.PRICING_RULE PO_PRICING_RULE,PO.PRICING_SUBRULE PO_PRICING_SUBRULE,
ICS.TRANSFER_PRICE_EFFECTIVE_DATE,
ICS.TRANSFER_PRICE ICS_PRICE,ICS.CURRENCY_CODE ICS_CURRENCY_CODE,
ICS.RETURN_CODE ICS_RETURN_CODE,
IB.ROLLED_UP_COST ROLLED_UP_PRICE, 28
(4) Tuning of SQL queries
Real life example (continued)
Multi-table join example (continued):
29
(4) Tuning of SQL queries
Real life example (continued)
RESULTS OF Explain plan:
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS FULL LOCATION
HASH JOIN OUTER
HASH JOIN OUTER
HASH JOIN
TABLE ACCESS FULL PART_INFO
HASH JOIN OUTER
HASH JOIN
TABLE ACCESS FULL USING_LOCATION_PART
TABLE ACCESS FULL INDENTED_BOM
TABLE ACCESS FULL VEHICLE_VIN
TABLE ACCESS FULL INTERCOMPANY_SETTLEMENT NOTICE FULL
TABLE SCANS
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS FULL PURCHASE_ORDER
HASH JOIN
TABLE ACCESS FULL LOCATION
HASH JOIN OUTER
HASH JOIN OUTER
HASH JOIN
TABLE ACCESS FULL PART_INFO
HASH JOIN OUTER
HASH JOIN
TABLE ACCESS FULL USING_LOCATION_PART
TABLE ACCESS FULL INDENTED_BOM
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS FULL VEHICLE_VIN
TABLE ACCESS FULL INTERCOMPANY_SETTLEMENT 30
TABLE ACCESS FULL PURCHASE_ORDER
(4) Tuning of SQL queries
Real life example (continued)
Modify multi table join in the where clause:
WHERE IB.PART_ID=PI.PART_ID AND
ulp.part_id=pi.part_id add this part to the where clause
and
IB.PART_ID=ULP.PART_ID AND
IB.PART_USING_LOCATION_CODE=ULP.PART_USING_LOCATION_CODE AND
IB.SHIP_FROM_LOCATION_CODE=L.LOCATION_CODE AND
IB.PART_ID=PO.PART_ID(+) AND
IB.PART_USING_LOCATION_CODE=PO.PART_USING_LOCATION_CODE(+) AND
IB.SHIP_FROM_LOCATION_CODE=PO.SHIP_FROM_LOCATION_CODE(+) AND
IB.PO_EFFECTIVE_DATE=PO.PO_EFFECTIVE_DATE(+) AND
IB.PO_CHARGE_FROM_DATE=PO.CHARGE_FROM_DATE(+) AND
IB.PART_ID=ICS.PART_ID(+) AND
IB.PART_USING_LOCATION_CODE=ICS.PART_USING_LOCATION_CODE(+) AND
IB.SHIP_FROM_LOCATION_CODE=ICS.SHIP_FROM_LOCATION_CODE(+) AND
IB.TRANSFER_PRICE_EFFECTIVE_DATE=ICS.TRANSFER_PRICE_EFFECTIVE_DATE(+) AND
IB.BOM_ID=vV.VIN(+)
31
(4) Tuning of SQL queries
Real life
RESULTS OF Explain plan:
example (continued)
EXECUTION_PATH
--------------------------------------------------------------------------------
NESTED LOOPS
NESTED LOOPS OUTER
NESTED LOOPS OUTER
NESTED LOOPS
HASH JOIN
TABLE ACCESS FULL PART_INFO
TABLE ACCESS FULL INDENTED_BOM
TABLE ACCESS BY INDEX ROWID LOCATION
INDEX UNIQUE SCAN PK_LOCATION
TABLE ACCESS BY INDEX ROWID INTERCOMPANY_SETTLEMENT
INDEX UNIQUE SCAN PK_INTERCOMPANY_SETTLEMENT
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS BY INDEX ROWID PURCHASE_ORDER
INDEX UNIQUE SCAN PK_PURCHASE_ORDER
TABLE ACCESS BY INDEX ROWID USING_LOCATION_PART NOTICE INDEXES USED
INDEX UNIQUE SCAN PK_USING_LOCATION_PART
TABLE ACCESS BY INDEX ROWID VEHICLE_VIN
INDEX RANGE SCAN UK_VEHICLE_VIN
NESTED LOOPS OUTER
NESTED LOOPS
NESTED LOOPS OUTER
NESTED LOOPS OUTER
NESTED LOOPS
32
(4) Tuning of SQL queries
Real life example (continued)
RESULTS OF Explain plan continued:
EXECUTION_PATH
--------------------------------------------------------------------------------
HASH JOIN
TABLE ACCESS FULL PART_INFO
TABLE ACCESS FULL INDENTED_BOM
TABLE ACCESS BY INDEX ROWID LOCATION
INDEX UNIQUE SCAN PK_LOCATION
TABLE ACCESS BY INDEX ROWID INTERCOMPANY_SETTLEMENT
INDEX UNIQUE SCAN PK_INTERCOMPANY_SETTLEMENT
TABLE ACCESS BY INDEX ROWID PURCHASE_ORDER
INDEX UNIQUE SCAN PK_PURCHASE_ORDER
TABLE ACCESS BY INDEX ROWID USING_LOCATION_PART NOTICE INDEXES USED
EXECUTION_PATH
--------------------------------------------------------------------------------
TABLE ACCESS BY INDEX ROWID VEHICLE_VIN
INDEX RANGE SCAN UK_VEHICLE_VIN
33
Real life example (continued)
Suppose you have to select all of the employee’s that are
Not account representatives
Table 1: Table2:
S_emp s_account_rep
Soc_number soc_number
last_name last_name
first_name first_name
salary region
34
Real life example (continued)
Suppose you have to select all of the employee’s that are
Not account representatives
Table 1: Table2:
S_emp s_account_rep
Soc_number soc_number
last_name last_name
first_name first_name
salary region
35
(5) Tuning of PL SQL code:
Everything said about tuning SQL queries holds with the addition of
(1) Using explicit instead of implicit cursors
(2) Eliminating cursors where ever possible
(3) Using rowid to update
(4) Use truncate instead of delete IF you want to delete ALL of the
data from the table.
(5) Use PL/SQL tables for iterations.
(6) Eliminate excessive use of execute immediate (Oracle 8i).
36
5) Tuning of PL SQL code (continued)
1) Using explicit instead of implicit cursors
Implicit cursors always take longer than explicit cursors because they are doing
an extra to make sure that there is no more data.
stead of:
select count(*) into tot from s_emp
where emp_id = v_emp_id;
37
(5) Tuning of PL SQL code (continued)
nating cursors where ever possible
:
TEMP_PARTSOURCE_DIFFER(PART_ID,PART_USING_LOCATION_CODE,
SHIP_FROM_LOCATION_CODE,PART_SOURCE_EFFECTIVE_DATE)
(SELECT A.PART_ID, A.PART_USING_LOCATION_CODE,
A.SHIP_FROM_LOCATION_CODE,A.PART_SOURCE_EFFECTIVE_DATE
FROM PART_SOURCE A
WHERE A.PART_USING_LOCATION_CODE=V_PLANT
AND A.PART_ID =V_PART_ID
AND A.PERCENT_OF_BUSINESS>0
AND A.PART_SOURCE_EFFECTIVE_DATE=
(SELECT MAX(PART_SOURCE_EFFECTIVE_DATE)
FROM PART_SOURCE B
WHERE B.PART_ID=A.PART_ID
AND B.PART_USING_LOCATION_CODE=
A.PART_USING_LOCATION_CODE AND
MINUS
(SELECT PART_ID, PART_USING_LOCATION_CODE,
SHIP_FROM_LOCATION_CODE,PART_SOURCE_EFFECTIVE_DATE
FROM TEMP_PARTSOURCE
WHERE PART_ID=V_PART_ID AND PART_USING_LOCATION_CODE=V_PLANT);
39
The PL/SQL code
40
CURSOR c_iterate_veh_lines IS
SELECT DISTINCT WERS_9270_CODE FROM VEHICLE V, MKT_MDL MM WHERE
ASSEMBLY_LOCATION_CODE=v_plant AND PRODUCTION_DATE >= v_start_date AND
PRODUCTION_DATE <= v_end_date AND
mm.mkt_mdl_sakey >= 0 and
MM.MKT_MDL_SAKEY=V.MKT_MDL_SAKEY AND
MM.WERS_9270_CODE IS NOT NULL;
cursor max_bulk (v_plant varchar2, vehicle_line_code varchar2, v_start_date date) is
select max(bulk_material_cost) bulkmat from bulk_material_cost t1
where
assembly_location_code=v_plant
and vehicle_line_code=v_vehicle
and effective_date= (select max(effective_date) from bulk_material_cost t2
where t1.assembly_location_code = t2.assembly_location_code
and t1.vehicle_line_code = t2.vehicle_line_code
and t2.vehicle_line_code = v_vehicle
and t2.assembly_location_code= v_plant
and effective_date <= v_start_date);
cursor sum1(v_curr_start_date date, v_plant varchar2, v_vehicle varchar2 , v_exchange_date date) is
select sum(part_currency_cost*(rate_mult/rate_div)) summ from vehicle
where
V.production_date = v_curr_start_date and
V.assembly_location_code=v_plant and
vmc.vehicle_id=v.vehicle_id and
MM.mkt_mdl_sakey=V.mkt_mdl_sakey and
mm.wers_9270_code=v_vehicle and
from_cur=vmc.currency_code and
to_cur='USD' and
rt_type='CRRNT' and
41
er.effdt=v_exchange_date; Notice we are replacing
implicit with explicit
sum1rec sum1%rowtype;
max_bulk_rec max_bulk%rowtype;
begin
v_plant_table(1):='AP01A';
v_plant_table(2):='AP02A';
v_plant_table(3):='AP03A';
v_plant_table(4):='AP04A';
v_plant_table(5):='AP05A';
v_plant_table(6):='AP06A';
v_plant_table(7):='AP07A';
v_plant_table(8):='AP09A';
v_plant_table(9):='AP10A';
v_plant_table(10):='AP11A';
v_plant_table(11):='AP12A';
v_plant_table(12):='AP13A';
v_plant_table(13):='AP14A';
v_plant_table(14):='AP15A';
v_plant_table(15):='AP16A';
v_plant_table(16):='AP17A';
v_plant_table(17):='AP20A';
v_plant_table(18):='AP21A';
v_plant_table(19):='AP22A';
v_plant_table(20):='AP23A';
v_plant_table(21):='AP24A';
v_plant_table(22):='0096A';
v_plant_table(23):='0097A';
v_plant_table(24):='0118A';
v_plant_table(25):='0128A';
v_plant_table(26):='0129A';
v_plant_table(27):='0134A';
v_plant_table(28):='0145A';
v_plant_table(29):='0264F';
v_plant_table(30):='0264A';
v_plant_table(31):='02641';
dbms_output.put_line('Plant,Veh Line,Bulk Matl Cost,Date,Straight,All,VIN,(VIN-All)%,(VIN-Straight)%,Total VINs,Cost Per VIN');
for v_plant_index in 1..31 loop
v_plant:=v_plant_table(v_plant_index);
v_veh_line_count:=0;
for v_veh_rec in c_iterate_veh_lines loop
v_veh_line_count:=v_veh_line_count+1;
v_curr_start_date:=v_start_date; 42
v_vehicle:=v_veh_rec.wers_9270_code;
for v_plant_index in 1..31 loop
v_plant:=v_plant_table(v_plant_index);
v_veh_line_count:=0;
for v_veh_rec in c_iterate_veh_lines loop
v_veh_line_count:=v_veh_line_count+1;
v_curr_start_date:=v_start_date;
v_vehicle:=v_veh_rec.wers_9270_code;
v_bulk_material:= max_bulk_rec.bulkmat;
close max_bulk;
IF v_bulk_material is null then
v_bulk_material:=0;
end if;
dbms_output.put_line('-');
dbms_output.put_line('-');
loop
exit when v_curr_start_date > v_end_date;
open sum1 (v_curr_start_date , v_plant , v_vehicle , v_exchange_date );
fetch sum1 into sum1rec;
v_vin1 := sum1rec.summ;
close sum1;
select sum(part_currency_cost *(rate_mult/rate_div)) into v_vin2 from vehicle_material_cost vmc, ps_rt_rate_tbl_mv er, vehicle v, mkt_mdl MM,
vehicle_vin VV, vehicle_suspense VS
where
V.production_date = v_curr_start_date and
43
V.assembly_location_code=v_plant and
vv.vehicle_id=v.vehicle_id and
MM.mkt_mdl_sakey(+)=V.mkt_mdl_sakey and
MM.wers_9270_code is null and
vmc.vehicle_id=v.vehicle_id AND
vv.vehicle_id = vmc.vehicle_id
and vs.plant_code = v.assembly_location_code
and vs.plant_code= v_plant
and
vs.vin=vv.vin and Notice making all joins possible
vs.record_id=(SELECT MAX(RECORD_ID) FROM VEHICLE_SUSPENSE vss
where vin=vv.vin
and vss.plant_code = v.assembly_location_code and
plant_code = v_plant
and vss.vehicle_line_code = v_vehicle) and
vs.vehicle_line_code=v_vehicle and
from_cur=vmc.currency_code and
to_cur='USD' and
rt_type='CRRNT' and
er.effdt=v_exchange_date;
v_vin:=nvl(v_vin1,0)+nvl(v_vin2,0);
select count(*) into v_count from (select distinct v.vehicle_id from vehicle_material_cost
vmc, ps_rt_rate_tbl_mv er, vehicle v, mkt_mdl MM,
vehicle_vin VV, vehicle_suspense VS
where
V.production_date = v_curr_start_date and
V.assembly_location_code=v_plant and
MM.mkt_mdl_sakey(+)=V.mkt_mdl_sakey and
(MM.wers_9270_code is null or (mm.wers_9270_code=v_vehicle)) and
vmc.vehicle_id=v.vehicle_id AND
44
vv.vehicle_id=v.vehicle_id and
vs.vin(+)=vv.vin and
(vs.vehicle_line_code is null or (vs.vehicle_line_code=v_vehicle and
vs.record_id=(SELECT MAX(RECORD_ID)
FROM VEHICLE_SUSPENSE where vin=vv.vin))) and
(vs.vehicle_line_code is not null or MM.wers_9270_code is not null) and
from_cur=vmc.currency_code and
to_cur='USD' and
rt_type='CRRNT' and
er.effdt=v_exchange_date);
v_vin:=v_vin-(v_count*v_bulk_material);
select sum(price *(rate_mult/rate_div) *accumulated_supplier_quantity) into v_st_line_bom
from daily_flat_bom dfb, ps_rt_rate_tbl_mv er where
production_date = v_curr_start_date and
assembly_location_code=v_plant and vehicle_line_code=v_vehicle and
er.from_cur=dfb.currency_code and
er.to_cur='USD' and
rt_type='CRRNT' and
er.effdt=v_exchange_date;
select sum(ext_purc_material_cost*accumulated_supplier_quantity) into
v_all_parts_bom from daily_assembly_end_item_bom where
production_date = v_curr_start_date and
assembly_location_code=v_plant and vehicle_line_code=v_vehicle;
v_st_line_bom:=nvl(v_st_line_bom,0);
v_all_parts_bom:=nvl(v_all_parts_bom,0);
v_vin:=nvl(v_vin,0);
IF v_vin=0 THEN
v_vin_all_perc_diff:=0;
45
ELSE
v_vin_all_perc_diff:=abs((v_vin-v_all_parts_bom)/(v_vin));
END IF;
IF v_vin=0 THEN
v_vin_st_perc_diff:=0;
ELSE
v_vin_st_perc_diff:=abs((v_vin-v_st_line_bom)/(v_vin));
END IF;
IF v_count > 0 THEN
dbms_output.put_line(v_plant||','||v_vehicle||','||v_bulk_material||','||
v_curr_start_date||
',' ||v_st_line_bom|| ',' ||v_all_parts_bom||','||v_vin||','||v_vin_all_perc_diff||
','||v_vin_st_perc_diff||','||v_count||','||v_vin/v_count);
v_curr_start_date:=v_curr_start_date+1;
ELSE
dbms_output.put_line(v_plant||','||v_vehicle||','||v_bulk_material||','||
v_curr_start_date||
',' ||v_st_line_bom|| ',' ||v_all_parts_bom||','||v_vin||','||v_vin_all_perc_diff||
','||v_vin_st_perc_diff||','||v_count||','||v_count);
v_curr_start_date:=v_curr_start_date+1;
END IF;
end loop;
end loop;
IF v_veh_line_count=0 THEN
dbms_output.put_line('No vehicles with vehicle lines found for plant '||v_plant);
END IF;
end loop;
end;
/
spool off
set feedback on
set termout on
46
We need to extract DISTINCT plant, plant description,
, vehicle line (TAURUS),
Vehicle line description, assembly plant 0096A, assembly plant description
(Genk), commodity code (B100), commodity code description ,
Market code , market code description (Australia)
(batteries) from a table of data (called TVM_market_flat_bom).
This is used for a WEB screen drop down
COMMODITY_CODE
Snapshot ASSEMBLY_LOCATION_CODE
TVM_MARKET_FLAT_BOM
43
DESC TVM_MARKET_FLAT_BOM
50
CREATE INDEX I_MV_TMLL on
MV_TVM_MKT_LOC_LOOKUP(part_using_location_code, wers_9270_code,
assembly_location_code, commodity_code , wers_market_code);
51
Solution: (1) Create a global temporary
table and bring information
over to it, then update
groups of records. Then put this
information into a separate table for the lookup screens
Elapsed: 00:05:53.74
SQL> list
1 insert into gl_t1
2 (part_using_location_code,
3 wers_9270_code,
4 assembly_location_code,
5 commodity_code,
6 wers_market_code
7 )
8 SELECT PART_uSING_LOCATION_CODE ,
9 wers_9270_code,
10 assembly_location_code,
11 commodity_code,
12 wers_market_code
13* from tvm_market_flat_bom@toread
53
• The procedure
•
• create or replace procedure updatenames3
• is
• vwers9270_desc varchar2(200);
• vplant_desc varchar2(200);
• vcomm_code_desc varchar2(200);
• vwersmktcode varchar2(200);
• i number := 0;
• cursor cs_gl
• is
• select distinct wers_9270_code from gl_t1;
Set up a cursor
• cs_gl_rec cs_gl%rowtype; For each
• begin Distinct
• open cs_gl; Vehicle line
• loop
• fetch cs_gl into cs_gl_rec;
• exit when cs_gl%notfound;
• vwers9270_desc := fn_wers9270_description(cs_gl_rec.wers_9270_code);
54
• update gl_t1
• set wers_9270_name = vwers9270_desc
• where wers_9270_code = cs_gl_rec.wers_9270_code;
• commit;
• end loop;
• close cs_gl;
• end;
• / Update the table
• SQL> exec updatenames3 With the wers_9270_description
55