SQL Query optimization

Query Optimization is very important while in development and also when project grows big we have optimize the existing scripts.

Below are some best practises to optimize the Query

  • Tables must have proper joins
  • Ensure the joins should be with primary key
  • Group by and Order by clause should be used only when needed
  • Use only IN clause and subquery when needed
  • Avoid Select DISTINCT
  • Avoid Select * from
  • Use Index when needed

Here we will demonstrate Index with a use case

explain plan for 
SELECT DISTINCT
        ooh.creation_date    order_creation_date,
        CASE
            WHEN wdd.source_header_type_name = 'INTERNAL' THEN
                'INTERNAL'
            ELSE
                'WHOLESALE'
        END                  order_type,
        ooh.order_number,
        ooh.cust_po_number,
        hp.party_name        customer_name,
        hl.address1
        || '-'
        || hl.address2
        || '-'
        || hl.address3       customer_site,
        ooh.booked_date      booked_date,
--        ooh.booked_date,
        ooh.flow_status_code order_status,
        CASE
            WHEN released_flag = 'Y' THEN
                'RELEASED'
            WHEN released_flag = 'N' THEN
                'HOLD'
            ELSE
                'OPEN'
        END                  hold_status,
        CASE
            WHEN released_flag = 'Y' THEN
                oohl.last_update_date
            ELSE
                NULL
        END                  hold_release_date,
        CASE
            WHEN wdd.released_status = 'C' THEN
                'INVOICED'
            WHEN wdd.released_status = 'R' THEN
                'READY TO RELEASE'
            WHEN wdd.released_status = 'Y' THEN
                'STAGED - AWAITING SHIP CONFIRM'
            ELSE
                'RELEASED TO WAREHOUSE'
        END                  ship_status,
        wnd.name             delivery_number,
        ool.ship_from_org_id organization_id,
        ooh.header_id,
        ooh.sold_to_org_id,
        hp.party_id
    FROM
        apps.oe_order_headers_all ooh,
        ar.hz_cust_accounts       hca,
        ar.hz_parties             hp,
        hz_party_sites            hps,
        hz_cust_acct_sites_all    hcasa,
        hz_cust_site_uses_all     hcsua,
        hz_locations              hl,
        (select header_id,  RELEASED_FLAG , max(LAST_UPDATE_DATE) LAST_UPDATE_DATE from oe_order_holds_all  group by header_id,  RELEASED_FLAG)   oohl, --Changes done by 4iapps on 02-May-2024 to restrict Line and Header Order hold Duplicates
        wsh_new_deliveries        wnd,
        wsh_delivery_assignments  wda,
        wsh_delivery_details      wdd,
        apps.oe_order_lines_all   ool
    WHERE
            1 = 1
        AND ooh.sold_to_org_id = hca.cust_account_id
        AND hca.party_id = hp.party_id
        AND oohl.header_id (+) = ooh.header_id
        AND hps.party_id = hp.party_id
        AND hcasa.party_site_id = hps.party_site_id
        AND hcsua.cust_acct_site_id = hcasa.cust_acct_site_id
        AND ooh.ship_to_org_id = hcsua.site_use_id
        AND hps.location_id = hl.location_id (+)
        AND ooh.header_id = wdd.source_header_id (+)
        AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
        AND ool.line_id = wdd.source_line_id (+)
        AND wdd.released_status NOT IN ( 'B', 'D' )
        AND wda.delivery_id = wnd.delivery_id (+)
        AND ooh.header_id = ool.header_id
        AND hps.location_id = hps.location_id
        AND hps.party_site_id = hps.party_site_id
        AND hps.party_site_number = hps.party_site_number
        AND ooh.header_id = ooh.header_id
    GROUP BY
        ooh.creation_date,
        wdd.source_header_type_name,
        ooh.order_number,
        ooh.cust_po_number,
        hp.party_name,
        hl.address1
        || '-'
        || hl.address2
        || '-'
        || hl.address3,
        ooh.booked_date,
        ooh.flow_status_code,
        released_flag,
        wnd.name,
        oohl.last_update_date,
        wdd.released_status,
        ool.ship_from_org_id,
        ooh.header_id,
        ooh.sold_to_org_id,
        hp.party_id
        order by ooh.header_id desc;


Once the above code is run then execute the below query

SELECT * FROM TABLE(dbms_xplan.display);

The above query gives us the cost of the query and if we observe, on line 21 Table access is full.

So we first create a Index on OE_ORDER_HEADERS_all based on the joins. As joins are proper and required we are creating index.

create index ont.XX_OE_ORDER_HDRS_N1 on ont.OE_ORDER_HEADERS_all (header_id,ship_to_org_id,sold_to_org_id,booked_date) nologging;
explain plan for 
SELECT DISTINCT
        ooh.creation_date    order_creation_date,
        CASE
            WHEN wdd.source_header_type_name = 'INTERNAL' THEN
                'INTERNAL'
            ELSE
                'WHOLESALE'
        END                  order_type,
        ooh.order_number,
        ooh.cust_po_number,
        hp.party_name        customer_name,
        hl.address1
        || '-'
        || hl.address2
        || '-'
        || hl.address3       customer_site,
        ooh.booked_date      booked_date,
--        ooh.booked_date,
        ooh.flow_status_code order_status,
        CASE
            WHEN released_flag = 'Y' THEN
                'RELEASED'
            WHEN released_flag = 'N' THEN
                'HOLD'
            ELSE
                'OPEN'
        END                  hold_status,
        CASE
            WHEN released_flag = 'Y' THEN
                oohl.last_update_date
            ELSE
                NULL
        END                  hold_release_date,
        CASE
            WHEN wdd.released_status = 'C' THEN
                'INVOICED'
            WHEN wdd.released_status = 'R' THEN
                'READY TO RELEASE'
            WHEN wdd.released_status = 'Y' THEN
                'STAGED - AWAITING SHIP CONFIRM'
            ELSE
                'RELEASED TO WAREHOUSE'
        END                  ship_status,
        wnd.name             delivery_number,
        ool.ship_from_org_id organization_id,
        ooh.header_id,
        ooh.sold_to_org_id,
        hp.party_id
    FROM
        apps.oe_order_headers_all ooh,
        ar.hz_cust_accounts       hca,
        ar.hz_parties             hp,
        hz_party_sites            hps,
        hz_cust_acct_sites_all    hcasa,
        hz_cust_site_uses_all     hcsua,
        hz_locations              hl,
        (select header_id,  RELEASED_FLAG , max(LAST_UPDATE_DATE) LAST_UPDATE_DATE from oe_order_holds_all  group by header_id,  RELEASED_FLAG)   oohl, --Changes done by 4iapps on 02-May-2024 to restrict Line and Header Order hold Duplicates
        wsh_new_deliveries        wnd,
        wsh_delivery_assignments  wda,
        wsh_delivery_details      wdd,
        apps.oe_order_lines_all   ool
    WHERE
            1 = 1
        AND ooh.sold_to_org_id = hca.cust_account_id
        and hca.cust_account_id = hca.cust_account_id+0
        AND hca.party_id = hp.party_id
        and hp.party_id=hp.party_id+0
        AND oohl.header_id (+) = ooh.header_id
        AND hps.party_id = hp.party_id
        AND hcasa.party_site_id = hps.party_site_id
        AND hcsua.cust_acct_site_id = hcasa.cust_acct_site_id
        AND ooh.ship_to_org_id = hcsua.site_use_id
        AND hps.location_id = hl.location_id (+)
        AND ooh.header_id = wdd.source_header_id (+)
        AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
        AND ool.line_id = wdd.source_line_id (+)
        AND wdd.released_status NOT IN ( 'B', 'D' )
        AND wda.delivery_id = wnd.delivery_id (+)
        AND ooh.header_id = ool.header_id
        AND hps.location_id = hps.location_id
        AND hps.party_site_id = hps.party_site_id
        AND hps.party_site_number = hps.party_site_number
        AND ooh.header_id = ooh.header_id
    GROUP BY
        ooh.creation_date,
        wdd.source_header_type_name,
        ooh.order_number,
        ooh.cust_po_number,
        hp.party_name,
        hl.address1
        || '-'
        || hl.address2
        || '-'
        || hl.address3,
        ooh.booked_date,
        ooh.flow_status_code,
        released_flag,
        wnd.name,
        oohl.last_update_date,
        wdd.released_status,
        ool.ship_from_org_id,
        ooh.header_id,
        ooh.sold_to_org_id,
        hp.party_id
        order by ooh.header_id desc;

After creating Index and forcing Index as attached in the above query now while running plan gives the below result.

SELECT * FROM TABLE(dbms_xplan.display);

We observe a drastic change in costing. But this way the query can be optmized

Query to get Scheduled Request Set and Scheduled Concurrent Programs

Scheduled Request Set

SELECT DISTINCT r.request_id
      , u.user_name requestor
      , u.description requested_by
      , CASE
           WHEN pt.user_concurrent_program_name = 'Report Set'
              THEN DECODE(
                  r.description
                   , NULL, pt.user_concurrent_program_name
                   ,    r.description
                     || ' ('
                     || pt.user_concurrent_program_name
                     || ')'
                  )
           ELSE pt.user_concurrent_program_name
        END job_name
      , u.email_address
      , frt.responsibility_name requested_by_resp
      , r.request_date
      , r.

requested_start_date
      , DECODE(
           r.hold_flag
         , 'Y', 'Yes'
         , 'N', 'No'
        ) on_hold
      , r.printer
      , r.number_of_copies print_count
      , r.argument_text PARAMETERS
      , r.resubmit_interval resubmit_every
      , r.resubmit_interval_unit_code resubmit_time_period
      , TO_CHAR((r.requested_start_date), 'HH24:MI:SS') start_time,
        NVL2(
           r.resubmit_interval
         , 'Periodically'
         , NVL2(
              r.release_class_id
            , 'On specific days'
            , 'Once'
           )
        ) AS schedule_type
   FROM apps.fnd_user u
      , apps.fnd_printer_styles_tl s
      , apps.fnd_concurrent_requests r
      , apps.fnd_responsibility_tl frt
      , apps.fnd_concurrent_programs_tl pt
      , apps.fnd_concurrent_programs pb
  WHERE pb.application_id = r.program_application_id
    AND r.responsibility_id = frt.responsibility_id
    AND pb.concurrent_program_id = pt.concurrent_program_id
    AND u.user_id = r.requested_by
    AND s.printer_style_name(+) = r.print_style
    AND r.phase_code = 'P'
    AND pb.concurrent_program_id = r.concurrent_program_id
    AND pb.application_id = pt.application_id
    AND pt.user_concurrent_program_name = 'Report Set'

Scheduled Concurrent Program

select r.request_id, 
       p.user_concurrent_program_name ||
       case
          when p.user_concurrent_program_name = 'Report Set' then
            (select ' - ' || s.user_request_set_name 
              from apps.fnd_request_sets_tl s 
             where s.application_id = r.argument1 
               and s.request_set_id = r.argument2 
               and language = 'US'
            ) 
          when p.user_concurrent_program_name = 'Check Periodic Alert' then
            (select ' - ' || a.alert_name 
              from apps.alr_alerts a 
             where a.application_id = r.argument1 
               and a.alert_id = r.argument2 
               and language = 'US'
            ) 
       end concurrent_program_name, 
       decode(c.class_type, 
              'P', 'Periodic', 
              'S', 'On Specific Days', 
              'X', 'Advanced', 
              c.class_type
             ) schedule_type,  
       case
          when c.class_type = 'P' then
            'Repeat every ' || 
            substr(c.class_info, 1, instr(c.class_info, ':') - 1) || 
            decode(substr(c.class_info, instr(c.class_info, ':', 1, 1) + 1, 1), 
                   'N', ' minutes', 
                   'M', ' months', 
                   'H', ' hours', 
                   'D', ' days') || 
            decode(substr(c.class_info, instr(c.class_info, ':', 1, 2) + 1, 1), 
                  'S', ' from the start of the prior run', 
                  'C', ' from the completion of the prior run') 
          when c.class_type = 'S' then
             nvl2(dates.dates, 'Dates: ' || dates.dates || '. ', null) || 
             decode(substr(c.class_info, 32, 1), '1', 'Last day of month ') || 
             decode(sign(to_number(substr(c.class_info, 33))), 
                    '1',  'Days of week: ' || 
                    decode(substr(c.class_info, 33, 1), '1', 'Su ') || 
                    decode(substr(c.class_info, 34, 1), '1', 'Mo ') || 
                    decode(substr(c.class_info, 35, 1), '1', 'Tu ') || 
                    decode(substr(c.class_info, 36, 1), '1', 'We ') || 
                    decode(substr(c.class_info, 37, 1), '1', 'Th ') || 
                    decode(substr(c.class_info, 38, 1), '1', 'Fr ') || 
                    decode(substr(c.class_info, 39, 1), '1', 'Sa ')) 
       end schedule, 
    r.requested_start_date next_run, 
       case
          when p.user_concurrent_program_name != 'Report Set' and
               p.user_concurrent_program_name != 'Check Periodic Alert' then
               r.argument_text 
       end argument_text, 
       r.hold_flag on_hold, 
       c.date1 start_date, 
       c.date2 end_date, 
       c.class_info, user_name
  from apps.fnd_concurrent_requests r, 
       applsys.fnd_conc_release_classes c, 
       apps.fnd_concurrent_programs_tl p, 
       apps.fnd_user                    usr,
       (SELECT release_class_id, 
               substr(max(SYS_CONNECT_BY_PATH(s, ' ')), 2) dates  ,a
          FROM (select release_class_id, 
                       rank() over(partition by release_class_id order by s) a, 
                       s 
                  from (select c.class_info, 
                               l, 
                               c.release_class_id, 
                               decode(substr(c.class_info, l, 1), '1', to_char(l)) s 
                          from (select level l
                                  from dual
                               connect by level <= 31), 
                               apps.fnd_conc_release_classes c 
                         where c.class_type = 'S') 
                  where s is not null) 
         CONNECT BY PRIOR
                     (a || release_class_id) = (a - 1) || release_class_id 
        group by release_class_id,a) dates
  where r.phase_code = 'P'
    and c.application_id = r.release_class_app_id 
    and c.release_class_id = r.release_class_id 
    and nvl(c.date2, sysdate + 1) > sysdate 
    and c.class_type is not null
    and p.concurrent_program_id = r.concurrent_program_id 
    and p.application_id = r.program_application_id 
    and p.language = 'US'
    and dates.release_class_id(+) = r.release_class_id 
    and usr.user_id = requested_by
  order by requested_by,on_hold, next_run;

Transfer files from Windows to Linux Using SSH

Currently I’m transferring files from Windows 11 to Debian Linux 12

Step 1: Ensure that ssh is installed and enabled

$ sudo apt install ssh
$ sudo systemctl enable --now ssh
$sudo ufw allow 22/tcp

Step 2: Get IP address from linux

$ ip addr

Step 3: Use a File transfer client in windows to transfer files. Here Im using WinSCP

Installing stumpwm in Debian 12 Standard/Minimal

Tried installing stumpwm in debian 12 standard and so sharing the steps

Step : 1 Update the System

sudo apt update && sudo apt upgrade

Step : 2 Install Stumpwm

sudo apt-get install stumpwm xinit

Step : 3 Running Stumpwm

emacs .xinitrc

insert below line

exec /usr/bin/stumpwm

to make it executable

chmod +x .xinitrc

List and check the executable create in home directory

ls -lart

Now confirm if you have stumpwm.desktop file in /usr/share/xsessions. All is fine and now Issue startx command and see welcome to stumpwm. Thats it.

Adding a user as Superuser in Debian 12

Step 1: Log in as the Root User

Step 2: Add a New User in Debian

root@host# sudo adduser username

Step 3: Add User to the Sudo Group

root@host# sudo usermod -aG sudo username

Step 4. Adding the Username to the Sudoers File

Open /etc/sudoers file in nano editor

root@host# nano /etc/sudoers

In the file navigate to the below line with # User privilege specification and add your user

# User privilege specification
root	ALL=(ALL:ALL) ALL
username  ALL=(ALL:ALL) ALL

Save the file by ctrl+o and exit using ctrl+x

Oracle apps EBS Workflow Error Query

SELECT
            workflowitemeo.item_type,
            workflowitemeo.item_key,
            workflowitemeo.root_activity,
            activityeo.display_name process_name,
            workflowitemeo.root_activity_version,
            workflowitemeo.owner_role,
            workflowitemeo.parent_item_type,
            workflowitemeo.parent_item_key,
            workflowitemeo.parent_context,
            workflowitemeo.begin_date,
            workflowitemeo.end_date,
            workflowitemeo.user_key,
            workflowitemtypeeo.name,
            workflowitemtypeeo.display_name,
            wf_directory.getroledisplayname2(workflowitemeo.owner_role) AS role_name,
            wf_fwkmon.getitemstatus(workflowitemeo.item_type,workflowitemeo.item_key,workflowitemeo.end_date,workflowitemeo.root_activity,workflowitemeo
.root_activity_version) AS status_code,
            wf_fwkmon.getroleemailaddress(workflowitemeo.owner_role) AS role_email,
            DECODE( (
                SELECT
                    COUNT(0)
                FROM
                    wf_items wi2
                WHERE
                    workflowitemeo.item_type = wi2.parent_item_type
                    AND   workflowitemeo.item_key = wi2.parent_item_key
            ),0,'WfMonNoChildren','WfMonChildrenExist') AS child_switcher
        FROM
            wf_items workflowitemeo,
            wf_item_types_vl workflowitemtypeeo,
            wf_activities_vl activityeo
        WHERE
            workflowitemeo.item_type = workflowitemtypeeo.name
            AND   activityeo.item_type = workflowitemeo.item_type
            AND   activityeo.name = workflowitemeo.root_activity
            AND   activityeo.version = workflowitemeo.root_activity_version
            and workflowitemeo.BEGIN_DATE >= sysdate-60
            and workflowitemtypeeo.NAME = 'HRSSA'
            and  wf_fwkmon.getitemstatus(workflowitemeo.item_type,workflowitemeo.item_key,workflowitemeo.end_date,workflowitemeo.root_activity,workflowitemeo
.root_activity_version) like 'ERR%'
and activityeo.display_name = 'Business and Training Travel Request'
;

Find / Identify correct Jdeveloper version for EBS Oracle apps Version

We have to get the EBS application OA Framework version. Based on it we can download Jdeveloper version

Steps to identify EBS application OA Framework

  1. Open your Oracle Applications homepage
  2. At the bottom left you can see “About this Page”. Click on it.
  3. Click on “Technology Components” tab
  4. Check OA Framework version.

Open the below Oracle document ID and download the relevant Jdeveloper patch

 How to Find the Correct Version of JDeveloper to Use with E-Business Suite 11i or Release 12.x (Doc ID 416708.1)

Once downloaded follow the below steps

Installation/Deploying Steps:

  1. Unzip the downloaded Patch (Say in D:).
  2. Rename the folder (Say OAF)
  3. You can see 3 folders under it(D:\OAF). They are jdevbin, jdevdoc, jdevhome
  4. Place the dbc file in D:\OAF\jdevhome\jdev\dbc_files\secure
    Location of dbc file in 11i
    $FND_TOP/secure OR $FND_SECURE
    Location of dbc file in R12
    $INST_TOP/appl/fnd/12.0.0/secure
  5. Set the Environment Variables
    Right click on My Computer > Click on Properties > Click on Advanced System Settings > Click on Environment Variables > Click on New > Give the following
    Variable Name: JDEV_USER_HOME
    Variable Value: D:\OAF\jdevhome\jdev
    Finally click on OK
  6. Create a shortcut on your Desktop. Goto D:\OAF\jdevbin\jdev\bin
    Right click on jdevW > Send to > Desktop (Shortcut) [For Windows]
  7. Double click on the Desktop Shortcut to open JDeveloper

Query to find all responsibility assigned to multiple users in Oracle apps/EBS

SELECT distinct
    fu.user_name "" user name"",
    frt.responsibility_name ""Responsibility Name"",
    furg.start_date ""Start Date"",
    furg.end_date ""End Date"",
    fr.responsibility_key ""Responsibility Key""
    ,papf.full_name
    --    ,fa.application_short_name ""Application Short Name""
    , haou.NAME org_name
    ,pp.NAME position_name
FROM
    fnd_user_resp_groups_direct furg,
    applsys.fnd_user fu,
    applsys.fnd_responsibility_tl frt,
    applsys.fnd_responsibility fr,
    applsys.fnd_application_tl fat,
    applsys.fnd_application fa
    ,(select * from per_all_people_f where trunc(sysdate) between effective_start_date and Effective_end_date and current_employee_flag = 'Y') papf
    ,(select * from per_all_assignments_f where trunc(sysdate) between effective_start_date and Effective_end_date ) paaf
    ,hr_all_organization_units haou
    ,per_positions pp
WHERE
    furg.user_id = fu.user_id
    AND   furg.responsibility_id = frt.responsibility_id
    AND   fr.responsibility_id = frt.responsibility_id
    AND   fa.application_id = fat.application_id
    AND   fr.application_id = fat.application_id
    AND   frt.language = userenv('LANG')
    --    AND   upper(fu.user_name) = upper('SYSADMIN')  -- <change it>
    and frt.responsibility_name = 'XX Purchasing Requestor'            -- <change it>
    -- AND (furg.end_date IS NULL OR furg.end_date >= TRUNC(SYSDATE))      --<For Active Resposibility>
    and papf.person_id(+) = fu.employee_id
    and paaf.person_id(+) = papf.person_id
    and paaf.ORGANIZATION_ID = haou.ORGANIZATION_ID(+)
    and paaf.position_id = pp.position_id (+) 
    order by fu.user_name;

Applications getting crashing in Windows – Increase Virtual RAM

My applications were crashing once I started to open 3 or 4 applications and I have contacted our SYSADMIN. Then they said to follow the below steps

  1. Press Windows key + I to open the Settings app.
  2. Head to System > About.
  3. Select Advanced system settings.
  4. Under Performance, select Settings.
  5. Open the Advanced tab. Under Virtual memory, select Change. Here are your Virtual Memory options. Change as per in the screenshot above shown.

Restricting the output of specific Concurrent Reports in Oracle apps EBS

The requirement can be achieved by Forms Personalization.

Ensure the forms personalization is enabled in the Instance. Once it is enabled do as the below steps as per the Screenshot.

Navigation : <Your> Responsibility –> View –> Requests –> Help –> Diagnostics –> Custom Code –> Personalize

Add a New record with below details

Now once the Conditions and Actions are completed test the functionality by submitting the report. Here as shown in the below screenshot format cannot be changed