So I've got a function that checks how many cancellations are in my booking table:
CREATE OR REPLACE FUNCTION total_cancellations
RETURN number IS
t_canc number := 0;
BEGIN
SELECT count(*) into t_canc
FROM booking where status = 'CANCELLED';
RETURN t_canc;
END;
/
To execute his in sql I use:
set serveroutput on
DECLARE
c number;
BEGIN
c := total_cancellations();
dbms_output.put_line('Total no. of Cancellations: ' || c);
END;
/
My result is:
anonymous block completed
Total no. of Cancellations: 1
My question is can someone help me call the function in JAVA, I have tried but with no luck.
Java provides CallableStatements for such purposes .
CallableStatement cstmt = conn.prepareCall("{? = CALL total_cancellations()}");
cstmt.registerOutParameter(1, Types.INTEGER);
cstmt.setInt(2, acctNo);
cstmt.executeUpdate();
int cancel= cstmt.getInt(1);
System.out.print("Cancellation is "+cancel);
will print the same as you do in the pl/sql. As per docs Connection#prepareCall(),
Creates a CallableStatement object for calling database stored procedures. The CallableStatement object provides methods for setting up its IN and OUT parameters, and methods for executing the call to a stored procedure.
You can also pass parameters for the function . for ex ,
conn.prepareCall("{? = CALL total_cancellations(?)}");
cstmt.setInt(2, value);
will pass the values to the function as input parameter.
Hope this helps !
Prepare a Callable Statement
There are two formats available, the
familiar block syntax used by Oracle and the ANSI 92 standard syntax.
In the case of our sample program, the block syntax has the form:
CallableStatement vStatement =
vDatabaseConnection.prepareCall( "begin ? := javatest( ?, ? ); end;" );
The ANSI 92 syntax has the form:
CallableStatement vStatement =
vDatabaseConnection.prepareCall( "{ ? = call javatest( ?, ? )}");
source
If you receive the below error, you might want to use the first format.
total_cancellations is not a procedure or is undefined error.
Sample code.
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#xx.xxx.xx.xxx:1521:xxx", "user","pass");
CallableStatement cstmt = conn.prepareCall("begin ? := TEST_FUNC(?,?); end;");
cstmt.registerOutParameter(1, Types.INTEGER);
cstmt.setString(2, "Test");
cstmt.setInt(3, 1001);
cstmt.execute();
int result = cstmt.getInt(1);
System.out.print("Result: " + result);
cstmt.close();
conn.close();
Related
How should I call an Oracle function from Java? The function is supposed to return a number.
CallableStatement cstmt = mJConn.prepareCall("{? = call fnd_request.submit_request( application => 'FND', program => 'JAVACONINSERT', description => 'CSV to DB Insert via Java' ,start_time => sysdate ,sub_request => FALSE, argument1 => '/home/TEST/java/t1.txt')}");
cstmt.registerOutParameter(1, Types.INTEGER);
cstmt.executeUpdate();
int reqId = cstmt.getInt(1);
System.out.println(reqId);
Try replacing
String call = "{?= CALL Proc(?)}";
with
String call = "{CALL Proc(?, ?)}";
The former syntax is for calling a stored function, and the new one is for a stored procedure.
You can also to swap the order of the bind parameters :
cs.setString(1, "String");
cs.registerOutParameter(2, Types.INTEGER);
How to call oracle function from java?.
I have a oracle function aaa.fucntion(number,date);, this method returns true or false. how do call this from java and get the returned value?
I am using Hibernate
this is what i tried,
Session session = null;
String associateHistorySQL="";
try {
session = HibernateUtil.currentSession();
associateHistorySQL = "SELECT aa.myFunction(:aorId,:givenDate) from dual";
Query associateHistoryQuery = session.createQuery(associateHistorySQL);
associateHistoryQuery.setParameter("aorId", associateOfficeRecordId);
associateHistoryQuery.setParameter("givenDate", date);
List associateHistoryList = associateHistoryQuery.list();
if (associateHistoryList != null && associateHistoryList.size() > 0 && new Integer(associateHistoryQuery.uniqueResult().toString()) > 0)
return true;
else
return false;
} finally {
HibernateUtil.cleanUpHibernateFromDao(false);
}
This is the exception i get unexpected token: aa: line 1:1: unexpected token: aa
thanks
There are actually multiple ways of doing so. But the easiest of them all is firing a query.
Here's how to do it.
String sql="select myFunction('"+number+"','"+date"') from dual";
statement.execute(sql);
Set the input and output parameters if you are using JDBC.
If you are using hibernate use Named Queries something like this:
YourMapping.hbm.xml
<sql-query name="my_function" callable="true">
<return alias="demo" class="net.bean.Demo">
<return-property name="id" column="id"/>
<return-property name="fname" column="fname"/>
<return-property name="lname" column="lname"/>
</return>
{?=call demoFunc(:param1,:param2)}
</sql-query>
Now this will create a Named Query for the function
Next thing to do is simply call it using following code
Query query=session.getNamedQuery("my_function");
query.setParameter("parma1",date);
query.setParameter("parma2",number);
query.executeUpdate();
Note that in hbm.xml file the return class name and properties exists only apply if you have mapped the returning values if the function returning appropriate values.
Use session.doWork from hibernate.
How to call a Oracle function from hibernate with return parameter?
From Oracle documentation -
http://docs.oracle.com/cd/F49540_01/DOC/java.815/a64686/04_call5.htm
FUNCTION balance (acct_id NUMBER) RETURN NUMBER IS
acct_bal NUMBER;
BEGIN
SELECT bal INTO acct_bal FROM accts
WHERE acct_no = acct_id;
RETURN acct_bal;
END;
From a JDBC program, your call to the function balance might look like this:
CallableStatement cstmt = conn.prepareCall("{? = CALL balance(?)}");
cstmt.registerOutParameter(1, Types.FLOAT);
cstmt.setInt(2, acctNo);
cstmt.executeUpdate();
float acctBal = cstmt.getFloat(1);
oracle function:
FUNCTION ap_ch_get_acct_balances (VAR_PI_MOB_NO_ACCT_NO VARCHAR2,
VAR_REPLY_CODE OUT NUMBER, VAR_EXT_RESPONSE OUT VARCHAR2, VAR_PO_ACC_BAL OUT CHAR,
VAR_PO_ACCT_NO OUT CHAR)
call in java:
String call = "{ ? = call FCRLIVE.AP_CH_GET_ACCT_BALANCES(?, ?, ?, ?, ?) }";
You can use CallableStatement
String sql="begin ? := aaaa.fucntion(?,?); end;";
CallableStatement stmt = connection.prepareCall(sql);
stmt.registerOutParameter(1, OracleTypes.BOOLEAN);
stmt.setInt(2, number);
stmt.setTimestamp(3, date);
stmt.execute();
After that you can read the returned value with:
stmt.getBoolean(1)
// Oracle Function
create or replace function addtwono(a in number, b in number) return varchar2 is
Result varchar2(10);
begin
result:= a + b;
--c:= result;
return('SUCCESS');
end ;
// Java Code ==========================================
String query = "begin ? := user.addtwono(?,?); end;";
CallableStatement st = connection.prepareCall(query);
st.registerOutParameter(1, OracleTypes.VARCHAR);
st.setInt(2, 10);
st.setInt(3, 15);
st.execute();
String rtn = st.getString(1);
Before issuing this question, i have googled a while, however now result found. My code attempts to call a procedure in oracle package(i am not very familiar with oracle package), and always get "ORA-03115: 不支持的网络数据类型或表示法", in english it should be 'unsupported network data type or representation'.
Below is my packagke:
create or replace
PACKAGE PKG_ACTIVITY_REPORT
IS
TYPE activity_report_item_type IS RECORD
( emp_id MERCHANT.merchant_id%TYPE,
emp_name MERCHANT.MERCHANT_NAME%TYPE,
emp_gender MERCHANT.MERCHANT_CODE%TYPE );
TYPE activity_report_items_type IS TABLE OF activity_report_item_type INDEX BY BINARY_INTEGER;
-- Procedure to retrive the activity report of given operator
PROCEDURE enquiry_activity_report(activity_report_items OUT activity_report_items_type);
END PKG_ACTIVITY_REPORT;
create or replace
PACKAGE BODY PKG_ACTIVITY_REPORT
IS
PROCEDURE enquiry_activity_report (activity_report_items OUT activity_report_items_type)
IS
activity_report_item activity_report_item_type;
BEGIN
activity_report_item.emp_id := 300000000;
activity_report_item.emp_name := 'Barbara';
activity_report_item.emp_gender := 'Female';
activity_report_items(1) := activity_report_item;
activity_report_item.emp_id := 300000008;
activity_report_item.emp_name := 'Rick';
activity_report_item.emp_gender := 'Male';
activity_report_items(2) := activity_report_item;
FOR i IN 1..activity_report_items.count LOOP
DBMS_OUTPUT.PUT_LINE('i='||i||', emp_id ='||activity_report_items(i).emp_id||', emp_name ='
||activity_report_items(i).emp_name||', emp_gender = '||activity_report_items(i).emp_gender);
END LOOP;
END enquiry_activity_report;
END PKG_ACTIVITY_REPORT;
I wanna return a array from the procedure, and call this procedure from java:
conn = ds.getConnection();
String storedProc = "{call pkg_activity_report.enquiry_activity_report(?)}";
CallableStatement cs = conn.prepareCall(storedProc);
// register output parameter
cs.registerOutParameter(1, java.sql.Types.ARRAY);
cs.execute();
Array array = cs.getArray(1);
System.out.println(array);
cs.close();
when run it, the exception thrown out. How do I map the OUT parameter to a java type? Pls help.
NOTE: when run this procedure from oracle sqldeveloper, it works properly.
DECLARE
ACTIVITY_REPORT_ITEMS RAMON.PKG_ACTIVITY_REPORT.ACTIVITY_REPORT_ITEMS_TYPE;
BEGIN
PKG_ACTIVITY_REPORT.ENQUIRY_ACTIVITY_REPORT(
ACTIVITY_REPORT_ITEMS => ACTIVITY_REPORT_ITEMS
);
END;
DBMS outputs the result:
i=1, emp_id =300000000, emp_name =Barbara, emp_gender = Female
i=2, emp_id =300000008, emp_name =Rick, emp_gender = Male
Now I created 2 schema-level type:
CREATE OR REPLACE TYPE activity_report_item_type AS OBJECT(
emp_id NUMBER,
emp_name VARCHAR2(30),
emp_gender VARCHAR2(30)
);
CREATE OR REPLACE TYPE activity_report_items_type AS TABLE OF activity_report_item_type;
And move PROCEDURE enquiry_activity_report out of package, make it independently, then call it from java successfully.
conn = ds.getConnection();
String storedProc = "{call enquiry_activity_report(?)}";
CallableStatement cs = conn.prepareCall(storedProc);
// register output parameter
cs.registerOutParameter(1, OracleTypes.ARRAY, "ACTIVITY_REPORT_ITEMS_TYPE");
cs.execute();
Array array = cs.getArray(1);
ResultSet rs = array.getResultSet();
while (rs.next()) {
// why getObject(2) instead of getObject(1)?
Object elements[] = ((STRUCT) rs.getObject(2)).getAttributes();
System.out.println(elements[0]);
System.out.println(elements[1]);
System.out.println(elements[2]);
}
cs.close();
If I put type declaration and procedure in package, java code will throw exception inform that 'no type definition found of "ACTIVITY_REPORT_ITEMS_TYPE".
Im trying to write sample stored functions in postgresql and call them using the CallableStatement offered by JDBC.
Here's some my test code
Consumer bean =new Consumer();
CallableStatement pstmt = null;
try {
con.setAutoCommit(false);
String query = "{ ? = call getData( ? ) }";
pstmt = con.prepareCall(query);
pstmt.registerOutParameter(1, Types.OTHER);
pstmt.setInt(2,5);
pstmt.execute(); // execute update statement
bean=(Consumer)pstmt.getObject(1);
System.out.println("bean"+bean.getConsumer_name());
And my Stored function is of the form .
CREATE FUNCTION getData(int) RETURNS SETOF db_consumer AS $$
SELECT * FROM db_consumer WHERE consumer_id = $1;
$$ LANGUAGE SQL;
However, I'm getting the following error when I try to run the code .
org.postgresql.util.PSQLException: A CallableStatement was executed with an invalid number of parameters .
Any idea why this could be happening?
I don't think you need a CallableStatement as you should be able to run select * from getData(5) directly:
PreparedStatement pstmt = con.prepareStatement("select * from getData(?)")
pstmt.setInt(1,5);
ResultSet rs = pstmt.execute();
while (rs.next()) {
System.out.println(rs.getString(1));
}
You are trying to call a SETOFF function via a Callable Statement. That's not going to happen! You'll always get an error.
PostgreSQL's stored functions can return results in two different ways. The function may return either a refcursor value or a SETOF some datatype. Depending on which of these return methods are used determines how the function should be called.
Functions that return data as a set should not be called via the CallableStatement interface, but instead should use the normal Statement or PreparedStatement interfaces.
I'm going to call a function, and set some parameters by name, example:
Connection c = null;
ResultSet rs = null;
String query;
PreparedStatement ps;
CallableStatement cs = null;
try {
c = DbUtils.getConnection();
cs = c.prepareCall("{? = call get_proc_name(?, ?) }");
cs.registerOutParameter(1, OracleTypes.VARCHAR);
cs.setInt("in_proc_type", ProcTypes.SELECT);
cs.setLong("in_table_id", tableId);
// here I should use something like cs.registerOutParameter("result", OracleTypes.VARCHAR);
cs.execute();
PL/SQL function parameters are:
CREATE OR REPLACE FUNCTION get_proc_name
(
in_proc_type IN NUMBER, /*1 - insert, 2 - update, 3 - delete, 4 - select*/
in_table_name IN VARCHAR2 := NULL,
in_table_id IN NUMBER := NULL,
in_table_type_id IN NUMBER := NULL,
is_new IN NUMBER := 0
) RETURN VARCHAR2
The question is how to register result as an out parameter, and then get it from oracle to java?
I can register in/out parameters by name, because I know theirs names from function, but I don't know how go get function result, what variable name use for it.
Manuals describe only usage in/out params with procedures, not functions.
Oracle version: 11.1.0.6.0
Java version: 1.6.0_14
The solution is to use only indexes for settings parameters. Such code works as expected (mixing indexes and named parameters doesn't work; so, the problem of using named parameter for result variable could not be solved, imho):
c = DbUtils.getConnection();
cs = c.prepareCall("{? = call get_proc_name(in_proc_type => ?, in_table_id => ?) }");
cs.registerOutParameter(1, java.sql.Types.VARCHAR);
cs.setInt(2, ProcTypes.SELECT);
cs.setLong(3, tableId);
cs.execute();
String procName = cs.getString(1);
cs.close();
CallableStatement has a bunch of registerXXX methods that take index.
That's how you register the result. It is parameter number 1.
In your case,
cs.registerOutParameter( 1, java.sql.Types.VARCHAR);
<SPECULATION>
BTW, because you are using index for result, you may need to use index-oriented setXXX methods and provide a full parameter list.
</SPECULATION>
You register the function result as if it were the first parameter. Obviously, this shifts the numbering of the actual parameters.
Your already existing line
cs.registerOutParameter(1, OracleTypes.VARCHAR);
is all it takes. After the call, get your result like this:
String result = cs.getString(1);