Summary: in this tutorial, you will learn how to use the Cursor.callfunc()
to call a PL/SQL stored function from a Python program.
Setting up a PL/SQL function #
The following statement creates a new stored function called get_revenue()
that returns the sales revenue by a salesman in a specific year.
CREATE OR REPLACE FUNCTION get_revenue(
salesman_code NUMBER,
year NUMBER)
RETURN NUMBER
IS
l_revenue NUMBER;
BEGIN
SELECT
SUM(quantity*unit_price)
INTO l_revenue
FROM
orders
INNER JOIN
order_items USING (order_id)
WHERE
salesman_id = salesman_code AND
EXTRACT(YEAR FROM order_date) = YEAR;
RETURN l_revenue;
END;
Code language: SQL (Structured Query Language) (sql)
This anonymous block tests the stored function get_revenue()
that get the sales revenue of the salesman id 54 in the year 2017:
SET SERVEROUTPUT ON;
DECLARE
l_revenue NUMBER;
BEGIN
l_revenue := get_revenue(54, 2017);
dbms_output.put_line(l_revenue);
END;
Code language: SQL (Structured Query Language) (sql)
Here is the output:
1160350.79
Code language: Python (python)
Calling a PL/SQL stored function example #
To execute a PL/SQL stored function, you use the Cursor.callproc()
method.
The following code illustrates how to call the stored function get_revenue()
and display the revenue of salesman 54 in the year 2017:
import oracledb
import logging
from connect import connect
def get_revenue(salesman_id: int, year: int) -> float | None:
revenue = None
try:
with connect() as connection:
with connection.cursor() as cursor:
# Call the stored function. oracledb can directly map Oracle NUMBER to Python float.
revenue = cursor.callfunc(
'get_revenue',
oracledb.NUMBER,
[salesman_id, year]
)
return revenue
except oracledb.Error as e:
error_message = f"Oracle database error while getting revenue for salesman_id {salesman_id}, year {year}: {e}"
logging.error(error_message)
return None
except Exception as e:
error_message = f"An unexpected error occurred while getting revenue for salesman_id {salesman_id}, year {year}: {e}"
logging.critical(error_message)
return None
if __name__ == '__main__':
sales_revenue = get_revenue(54, 2017)
if sales_revenue is not None:
print(f"The sales revenue for salesman 54 in 2017 is: {sales_revenue}")
else:
print("Failed to retrieve sales revenue for salesman 54 in 2017.")
sales_revenue_invalid = get_revenue(99999, 2023)
if sales_revenue_invalid is not None:
print(f"The sales revenue for salesman 99999 in 2023 is: {sales_revenue_invalid}")
else:
print("Failed to retrieve sales revenue for salesman 99999 in 2023 (as expected or due to error).")
Code language: Python (python)
In this example:
First, establish a connection to the Oracle Database by calling the cx_Oracle.connect()
method with the parameters provided by the config
module.
Second, create a new Cursor
object using the Connection.cursor()
method.
Third, call the stored function get_revenue()
using the Cursor.callfunc()
method:
cursor.callfunc('get_revenue', float, [salesman_id, year])
Code language: Python (python)
In the Cursor.callfunc()
method: the first argument is the stored function’s name, the second argument is the type of the returned value, and the third argument is a list of arguments passed to the stored function.
The following code tests the get_revenue()
function with the salesman 54 and the year 2017:
sales_revenue = get_revenue(54, 2017)
print(sales_revenue) # 1160350.79
Code language: Python (python)
In this tutorial, you have learned how to use the Cursor.callfunc()
method to call a PL/SQL stored function in Python.