Hello Tom,
I am trying to inline a function when using a MERGE statement and I am not sure if it is working as no error is thrown.
Here is my code:
CREATE OR REPLACE PACKAGE my_pkg
IS
FUNCTION my_fnc ( p1 VARCHAR2
, p2 VARCHAR2) RETURN VARCHAR2;
END my_pkg;
/
CREATE OR REPLACE PACKAGE BODY my_pkg
IS
FUNCTION my_fnc ( p1 VARCHAR2
, p2 VARCHAR2) RETURN VARCHAR2
IS
BEGIN
RETURN p1 || '-' || p2;
END my_fnc;
END my_pkg;
/
CREATE OR REPACE PROCEURE my_prc
IS
TYPE t_type IS TABLE OF my_tab2%ROWTYPE;
v_nt t_type;
v_colx my_tab2.colx%TYPE;
BEGIN
-- version 1
PRAGMA INLINE (my_fnc, 'YES');
MERGE INTO my_tab1 a
USING (SELECT col1
, col2
, my_pkg.my_fnc(col3, col4) colx
, col5
, col6
FROM my_tab2
WHERE 1 = 1) b -- the condition doesn't mather
ON (a.col1 = b.col1 AND a.col2 = b.col2 AND a.colx = b.colx)
WHEN MATCHED THEN
UPDATE SET a.col5 = b.col5
, a.col6 = b.col6
WHEN NOT MATCHED THEN
INSERT ( col1
, col2
, colx
, col5
, col6);
COMMIT;
--
-- version 2
SELECT col1
, col2
, my_pkg.my_fnc(col3, col4) colx
, col5
, col6
BULK COLLECT INTO v_nt
FROM my_tab2;
FORALL i IN v_nt.FIRST .. v_nt.LAST
PRAGMA INLINE (my_fnc, 'YES');
v_colx := my_pkg.my_fnc(col3, col4);
MERGE INTO my_tab1 a
USING (SELECT v_nt(i).col1 col1
, v_nt(i).col2 col2
, v_colx
, v_nt(i).col5 col5
, v_nt(i).col6 col6
FROM dual) b -- the condition doesn't mather
ON (a.col1 = b.col1 AND a.col2 = b.col2 AND a.colx = b.colx)
WHEN MATCHED THEN
UPDATE SET a.col5 = b.col5
, a.col6 = b.col6
WHEN NOT MATCHED THEN
INSERT ( col1
, col2
, colx
, col5
, col6);
END my_prc;
Now, my questions are: can any version be inlinied?
Version 1 could not be inlined because it is not preceding any of the statements mention in ORacle documentation (
https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-optimization-and-tuning.html#GUID-2E78813E-CF29-409D-9F8B-AA24B294BFA2 )
Version 1 could not be inlined because, also the invoked and invoking subprograms are not in the same program unit
(it is not very clear what means "same program unit")
Version 2 could be inlined because it is using the assignment statement?
Version 2 could not be inlined because the invoked and invoking subprograms are not in the same program unit
Thank you,
Ionut Preda.
Inlining only happens to calls in PL/SQL. You're calling the function from SQL. So the calls can't be inlined.
This could be inlined:
PRAGMA INLINE (my_fnc, 'YES');
v_colx := my_pkg.my_fnc(col3, col4);
...if it wasn't inside a FORALL statement.
What exactly are you trying to achieve here and why?
If it's to avoid the PL/SQL<>SQL context switch you'll have to copy logic into the SQL statement itself.
Until you get to 23ai :)
This adds the automatic SQL transpiler. This can extract expressions from PL/SQL calls in SQL into the SQL statement itself.
To enable it set this parameter:
alter session set sql_transpiler = on;
This will then transpiler all eligible functions. Currently, functions will not get transpiled if they contain any PL/SQL (e.g. %type variables, function calls) or SQL statements.
For more details see our discuss of this in last month's SQL Office hours
Or you can read more in this post by Ulrike Schwinn
https://blogs.oracle.com/coretec/post/sql-transpiler-in-23c