Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Francisco.

Asked: February 08, 2023 - 6:38 pm UTC

Last updated: March 09, 2023 - 4:37 pm UTC

Version: 12.1.0.2

Viewed 1000+ times

You Asked

Hello,

I am trying to implement a SQL profile for a sentence, which I think is not shared by the database, I am seeing a SQL sentence different only by one condition which is (file_id). It is displayed inside of the trace file as a different value for every execution.

The code of the package that is executing this sentence is as follow:

L_get_cost_change_rec := 'SELECT DISTINCT dt.item,
                     dt.supplier\_site as supplier,
                     il.loc,
                     il.loc\_type,
                     ROUND((1 - NVL( dt.' ||L\_discount\_1|| ' , 0) / 100) \*
                     (1 - NVL( dt.' || L\_discount\_2 || ', 0) / 100) \*
                     (1 - NVL( dt.' || L\_discount\_3 || ', 0) / 100) \*
                     (1 - NVL( dt.' || L\_discount\_4 || ', 0) / 100) \*
                     (1 - NVL( dt.' || L\_discount\_5 || ', 0) / 100)  \* dt.unit\_cost,2) unit\_cost
                    FROM fah\_supp\_publish\_upld\_head sh,
                       fah\_supp\_publish\_upld\_detail dt,
                       item\_loc il,
                       store s,
                       fah\_v\_store\_supp\_key\_region sskr
                    WHERE sh.file\_id = '|| I\_file\_id || '
                      AND sh.file\_id = dt.file\_id
                      AND dt.status = ''N'' -- valid records only
                      AND dt.unit\_cost > 0 -- only valid costs
                      AND dt.item    =  il.item
                      AND il.loc     = s.store
                      AND s.store\_close\_date IS NULL
                      AND EXISTS (SELECT 1
                             FROM fah\_rollout\_system\_matrix rol
                            WHERE rol.loc\_type = ''S''
                            AND rol.system = ''ORACLE''
                            AND rol.loc = s.store)
                      --
                      AND EXISTS (SELECT 1
                               FROM item\_supp\_country isc
                             WHERE isc.item              = dt.item
                               AND isc.supplier          = dt.supplier\_site
                               AND isc.origin\_country\_id = ''MX'')
                      --
                      AND EXISTS (SELECT 1
                              FROM item\_supp\_country\_loc iscl
                            WHERE iscl.item      =     dt.item
                              AND iscl.loc       =     il.loc
                              AND iscl.supplier  =     dt.supplier\_site
                              AND iscl.origin\_country\_id = ''MX''
                              AND iscl.unit\_cost != ROUND((1 - NVL( dt.' ||L\_discount\_1|| ' , 0) / 100) 
*
                                 (1 - NVL( dt.' || L\_discount\_2 || ', 0) / 100) \*
                                 (1 - NVL( dt.' || L\_discount\_3 || ', 0) / 100) \*
                                 (1 - NVL( dt.' || L\_discount\_4 || ', 0) / 100) \*
                                 (1 - NVL( dt.' || L\_discount\_5 || ', 0) / 100)  \* dt.unit\_cost,2))
                      AND sskr.region = sh.region
                      AND sskr.supplier\_key = sh.supplier\_key
                      AND sskr.store = s.store

' ;
This value is appearing with different value inside of the trace file:

WHERE sh.file_id = '|| I_file_id || '

Is there any way to use this value as bind variable inside of the package?

Thanks in advance.

Kind regards,

Francisco Mtz.

and Connor said...

Well, its easy to use a bind variable, but the calling application needs to know this and supply it.

ie, the package would need to change the SQL to be a bind and then pass in the value during execution, ie

L_get_cost_change_rec  := 'select ..... file_id = :file_id ... ';
open my_ref_cur for L_get_cost_change_rec  using l_file_id


Alternatively you could have the package flip to cursor sharing before and after the call, ie

execute immediate 'alter session set cursor_sharing = force';
open my_ref_cur for L_get_cost_change_rec ;
execute immediate 'alter session set cursor_sharing = exact';


I prefer the former because it will guard you from SQL injection

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

I really appreciate your help

Francisco Martinez, February 10, 2023 - 8:32 pm UTC

Thank you very much Sir Connor.

I really appreciate your help on this request.

Kind regards,

Francisco Mtz.
Connor McDonald
February 13, 2023 - 4:31 am UTC

thats why we're here :-)

Query

Francisco, March 08, 2023 - 9:52 pm UTC

Hello, AskTom's team.

I would like to know if dynamic columns can be changed by bind variables too?, This is the query that is not using bind variables:

L_get_cost_change_rec :=  'SELECT DISTINCT dt.item,
                         dt.supplier_site as supplier,
                         il.loc,
                         il.loc_type,
                         ROUND((1 - NVL( dt.' ||L_discount_1|| ' , 0) / 100) *
                         (1 - NVL( dt.' || L_discount_2 || ', 0) / 100) *
                         (1 - NVL( dt.' || L_discount_3 || ', 0) / 100) *
                         (1 - NVL( dt.' || L_discount_4 || ', 0) / 100) *
                         (1 - NVL( dt.' || L_discount_5 || ', 0) / 100)  * dt.unit_cost,2) unit_cost
                        FROM fah_supp_publish_upld_head sh,
                           fah_supp_publish_upld_detail dt,
                           item_loc il,
                           store s,
                           fah_v_store_supp_key_region sskr
                        WHERE sh.file_id = '|| I_file_id || '
                          AND sh.file_id = dt.file_id
                          AND dt.status = ''N'' -- valid records only
                          AND dt.unit_cost > 0 -- only valid costs
                          AND dt.item    =  il.item
                          AND il.loc     = s.store
                          AND s.store_close_date IS NULL
                          AND EXISTS (SELECT 1
                                 FROM fah_rollout_system_matrix rol
                                WHERE rol.loc_type = ''S''
                                AND rol.system = ''ORACLE''
                                AND rol.loc = s.store)
                          --
                          AND EXISTS (SELECT 1
                                   FROM item_supp_country isc
                                 WHERE isc.item              = dt.item
                                   AND isc.supplier          = dt.supplier_site
                                   AND isc.origin_country_id = ''MX'')
                          AND EXISTS (SELECT 1
                                  FROM item_supp_country_loc iscl
                                WHERE iscl.item      =     dt.item
                                  AND iscl.loc       =     il.loc
                                  AND iscl.supplier  =     dt.supplier_site
                                  AND iscl.origin_country_id = ''MX''
                                  AND iscl.unit_cost != ROUND((1 - NVL( dt.' ||L_discount_1|| ' , 0) / 100) *
                                     (1 - NVL( dt.' || L_discount_2 || ', 0) / 100) *
                                     (1 - NVL( dt.' || L_discount_3 || ', 0) / 100) *
                                     (1 - NVL( dt.' || L_discount_4 || ', 0) / 100) *
                                     (1 - NVL( dt.' || L_discount_5 || ', 0) / 100)  * dt.unit_cost,2))
                          AND sskr.region = sh.region
                          AND sskr.supplier_key = sh.supplier_key
                          AND sskr.store = s.store
                             ' ;


As you can see, L_discount_1 .. L_discount_5 are dynamic too.

Can they be changed to bind variables too?

Thanks in advance.

Kind regards,

Francisco Mtz.
Connor McDonald
March 09, 2023 - 4:10 am UTC

No - bind variables are solely for values not for columns.

In your SQL, the most likely candidate for a bind here is 'I_file_id"

So it would be:

L_get_cost_change_rec :=  'SELECT DISTINCT dt.item,
                         dt.supplier_site as supplier,
...
                           fah_v_store_supp_key_region sskr
                        WHERE sh.file_id = :I_file_id 
                          AND sh.file_id = dt.file_id
...




A reader, March 09, 2023 - 7:36 am UTC

I would like to know if dynamic columns can be changed by bind variables too?

Put an outer condition or or the result of this condition inside the query.
'... '||var_name||' ...'
 ==>
'... decode(:var_name, ''name1'', name1, ''name2'', name2, ...) ...'

Chris Saxon
March 09, 2023 - 4:37 pm UTC

Yep, that would work (though may be impractical if there are lots of possible columns - I'd question the use of dynamic SQL in this case though).

More to Explore

APEX

Keep your APEX skills fresh by attending their regular Office Hours sessions.