Skip to content

Select *

Often, it is necessary to select columns from either views or tables when cursors are written inside the PLSQL logic. One option would be to do a SELECT * instead of selecting necessary columns in the SELECT list. This may introduce a performance bottleneck which is discussed through the examples below.

Select * from Views

Views may contain embedded method calls as columns in the SELECT list. Often, all columns defined in the view is not required for the method implementation, rather it is a subset of columns. If a SELECT * is done in a cursor then, there will be a context switch between SQL, PLSQL engines for each column with a method call. Additionally oracle need to parse all the columns used in the cursor. It is always better to select only the required columns in the SELECT list.

Below is an extract from an ordinary view definition in ORDER. Note the columns with comments Method call n. If a select * is performed, oracle has to do extra context switches for each of the method calls . As in the example below, most likely, it is not necessary to fetch client values from the view to perform server logic.

CREATE OR REPLACE VIEW CUSTOMER_ORDER_PICK_LIST AS
SELECT
    pick_list_no                                                  pick_list_no,
    order_no                                                      order_no,
    create_date                                                   create_date,
    Pick_List_Printed_API.Decode(printed_flag)                    printed_flag, -- Method call 1
    printed_flag                                                  printed_flag_db,
    Picking_Confirmed_API.Decode(picking_confirmed)               picking_confirmed, -- Method call 2
    picking_confirmed                                             picking_confirmed_db,
    source                                                        source,
    Consolidated_Pick_List_API.Decode(consolidated_flag)          consolidated_flag, -- Method call 3
    consolidated_flag                                             consolidated_flag_db,
    consolidated_orders                                           consolidated_orders,
    contract                                                      contract,
    sel_order                                                     sel_order,
    sel_customer                                                  sel_customer,
    sel_route                                                     sel_route,
    sel_ship_period                                               sel_ship_period,
    sel_forward_agent                                             sel_forward_agent,
    sel_location_group                                            sel_location_group,
    Pick_List_Consolidation_API.Decode(consolidation)             consolidation, -- Method call 4
    consolidation                                                 consolidation_db,
    Pick_Inventory_Type_API.Decode(pick_inventory_type)           pick_inventory_type, -- Method call 5
    pick_inventory_type                                           pick_inventory_type_db,
    sel_due_date                                                  sel_due_date,
    Consol_Pick_Incl_Cust_Ord_API.Decode(sel_include_cust_orders) sel_include_cust_orders, -- Method call 6
    sel_include_cust_orders                                       sel_include_cust_orders_db,
    rowkey                                                        objkey,
    to_char(rowversion,'YYYYMMDDHH24MISS')                        objversion,
    rowid                                                         objid
FROM customer_order_pick_list_tab
WHERE (contract IS NULL OR EXISTS (SELECT 1 FROM user_allowed_site_pub WHERE customer_order_pick_list_tab.contract = site))
WITH READ ONLY;

Select * from Tables

There are scenarios where all columns in the table are selected unnecessary for a particular row even though only a few columns are accessed. Because of this, there could be additional table/full_table scans instead of index_range/index_unique /Index full scans to retrieve these unwanted values. Therefore, the clever way is to retrieve only the required columns instead of SELECT *.

Example

PROCEDURE New_Note_Text_All (
   note_text_ IN OUT VARCHAR2,
   note_id_ IN NUMBER,
   output_type_ IN VARCHAR2 )
IS
   CURSOR source IS
      SELECT *
      FROM document_text_tab
      WHERE note_id     = note_id_
      AND   output_type = output_type_;
BEGIN
   OPEN source;
   FETCH source INTO test_rec_;
   IF source%FOUND THEN
      DO_SOMETING;
   ELSE
      DO_SOMETING;
   END IF;
END New_Note_Text_All;

Solution

The purpose of this cursor is to check the availability of the record. So, it's not needed to do a SELECT * from the table. Instead, use SELECT 1.

PROCEDURE New_Note_Text_One (
   note_text_ IN OUT VARCHAR2,
   note_id_ IN NUMBER,
   output_type_ IN VARCHAR2 )
IS
   CURSOR source IS
      SELECT 1
      FROM document_text_tab
      WHERE note_id     = note_id_
      AND   output_type = output_type_;
BEGIN
   OPEN source;
   FETCH source INTO test_rec_;
   IF source%FOUND THEN
      DO_SOMETING;
   ELSE
      DO_SOMETING;
   END IF;
END New_Note_Text_One;