Reading DBMS_Ouptut after Executing PLSQL from jdbc - java

I need to execute an Oralce PL/SQL statement using jdbc, but I'm struggling on how to extract the data.
Here is my statement
DECLARE
l_xmltype XMLTYPE;
l_ctx dbms_xmlgen.ctxhandle;
BEGIN
l_ctx := dbms_xmlgen.newcontext('select * from myTable where rownun < 10;);
dbms_xmlgen.setrowsettag(l_ctx, 'My_DATA');
dbms_xmlgen.setrowtag(l_ctx, 'My_Element');
l_xmltype := dbms_xmlgen.getXmlType(l_ctx) ;
dbms_xmlgen.closeContext(l_ctx);
dbms_output.put_line(l_xmltype.getClobVal);
dbms_output.get_lines(?, l_xmltype);
End;
And my code
CallableStatement cs = connection.prepareCall(plsql);
cs.registerOutParameter(1, Types.ARRAY,"DBMSOUTPUT_LINESARRAY");
cs.execute();
Array array = null;
array = cs.getArray(1);
Stream.of((Object[]) array.getArray())
.forEach(System.out::println);
And I'm getting the error
java.sql.SQLException: ORA-06550: line 1, column 380: PLS-00306: wrong
number or types of arguments in call to 'GET_LINES'
I'm not an expert in PL/SQL nor jdbc so I'm struggling to find a solution.

The second argument of GET_LINES is a number, not an XMLTYPE. Change your call to something like:
dbms_output.get_lines(?, 50);
I've also shown a more complete example on how to do this in a similar question. Note that you also have to add the following call first, to enable dbms_output collection:
dbms_output.enable();
Note that in case you're using jOOQ, you can automatically fetch server output on any statement.

Related

Execute multi-line PostgreSQL script containing stored procedure call with IN/INOUT Parameters using java

I have a special case, in which the following PostgreSQL script is required to be called from java:
do
$$
DECLARE
xx VARCHAR(200);
xy VARCHAR(200);
xz VARCHAR(200);
yy VARCHAR(200);
BEGIN
xx := ?;
xy := ?;
call database_procedure(yy, yz, xx, xy);
? := yy;
? := yz;
END;
$$
This script is passed to CallableStatement in the following way, and the Input/Output parameters are binded with the callable statement.
CallableStatement cs = pgConn.prepareCall(sqlScript);
cs.setString(1,"param1");
cs.setString(2,"value2");
cs.registerOutParameter(3, Types.VARCHAR);
cs.registerOutParameter(4, Types.VARCHAR);
I get the issue on the line
cs.setString(1,"param1");
Issue: org.postgresql.util.PSQLException: The column index is out of range: 1, number of columns: 0.
Upon research i have found that, this issue is because the cs.setString is unable to find question mark(or parameter place holder).
Also, When i try simple query as following, it works.
CallableStatement cs = pgConn.prepareCall("call database_procedure(?,?,?,?)");
But according to my current scenario, I need a solution to executing the whole script as i mentioned, instead of only one call, because in different scenarios we are assigning values to out parameters based on the data returned by the procedure and so on.
Kindly help, so that, somehow the IN/INOUT parameters are passed to the sql script mentioned above.

How to call procedure in mysql workbench

DELIMITER //
CREATE PROCEDURE temp ( empId INT)
BEGIN
DECLARE var_etype VARCHAR(36);
SELECT
emptype = QOUTE(emptype)
FROM
dms_document
WHERE
id = empid;
SELECT
emptype,
CASE
WHEN emptype = 'P' THEN doctype
ELSE 'No Documents required'
END
FROM
dms_report
WHERE
pilot = 1;
End//
DELIMITER ;
I have created this procedure successfully but when I try to call it, I am getting error 1305 the function database.temp does not exist. I am trying to call using this statement:
SET #increment = '1';
select temp( #increment)
but I get Error, please tell me where I made mistake.
This is how you call it, use use the keyword call and then procedure's name
call procedureName(params);
in call of making an string
String sqlString = "procedureName("+?+")"; //in case of Integers
String sqlString = "procedureName('"+?+"')";//in case of Integers
bring the parameter in prepared statement.
MySQL's documentation on Using JDBC CallableStatements to Execute Stored Procedures explains the necessary steps quite well.
This is what your java code needs to look like:
CallableStatement cStmt = conn.prepareCall("{call temp(?)}");
cStmt.setInt(1, 42); //set your input parameter, empId, to 42.
If you want to work with the rows returned by your stored procedure's query in your Java code, you're also going to need to create an OUT parameter as noted in MySql's documentation page titled, CALL Syntax:
CALL can pass back values to its caller using parameters that are
declared as OUT or INOUT parameters
In order to call your stored procedure from MySQL workbench, use the CALL command. You can call stored procedure by directly setting values for each of the parameters:
SET #increment = 1;
CALL temp(#increment)
Then you simply use the SELECT statement to return the value of your output parameter
SELECT #outParameter
With help setting your output parameters, please read the article MySQL Stored Procedure - SELECT - Example.
Your stored procedure is syntactically wrong, and as mentioned in the comments, you're not using the stored procedure functionality for it's intended use. It's intended to be used for data manipulation not for querying. You should instead consider turning your procedure into a series of prepared statements.
Please let me know if you have any questions!

Error with calling stored proc in Hibernate

I'm struck with an issue where am trying to call an Oracle stored procedure using Hibernate as in the below snippets.
My DAO class:
Query q = session.createSQLQuery(" {call PKG.PROC_GET_DATA_SET(?, :parameter1, :parameter2) }")
.setParameter(0, OracleTypes.CURSOR)
.setParameter("parameter1", "fDate")
.setParameter("parameter2", "tDate");
resultSet = q.list();
PROCEDURE:
CREATE OR REPLACE PACKAGE BODY schema.PKG
AS
PROCEDURE PROC_GET_DATA_SET(
P_CURSOR OUT SYS_REFCURSOR,
P_STRING1 IN VARCHAR2,
P_STRING2 IN VARCHAR2
)
AS
BEGIN
OPEN P_CURSOR FOR
.
.
.
But when i call the proc as in the DAO class, am getting an error as below.
Error:
PLS-00306: wrong number or types of arguments in call to 'PROC_GET_DATA_SET'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Struggling to spot the reason. Can someone throw some light here please?
TIA,
You cannot use this code to call a procedure using hibernate. See docs
The recommended call form is standard SQL92: { ? = call
functionName() } or { ? = call
procedureName(}. Native call syntax is not supported.
For Oracle the following rules apply:
A function must return a result set. The first parameter of a
procedure must be an OUT that returns a result set. This is done by
using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to
define a REF CURSOR type. See Oracle literature for further
information.
I suggest trying this:
{? = call PKG.PROC_GET_DATA_SET(?, ?) }
If this does not work, use session.connection()

Invalid column index : Callable statements

I have written a Stored proc which calculates size of a table.
create or replace PROCEDURE RETRIEVE_TABLE_SIZE (
p_segment_type in VARCHAR2,
p_segment_name in VARCHAR2,
P_table_size out INTEGER )
AS
BEGIN
SELECT bytes/(1048576*1024) as GB FROM DBA_SEGMENTS WHERE SEGMENT_NAME = p_segment_type AND SEGMENT_TYPE = p_segment_name ;
END ;
I am calling this Stored proc from my java class and my code is below
String sqlQuery = "{call RETRIEVE_TABLE_SIZE(?,?,?)}";
CallableStatement callableStatement = connection.prepareCall(sqlQuery);
callableStatement.setString("p_segment_type","TABLE");
callableStatement.setString("p_segment_name","SIM_HEADER");
callableStatement.registerOutParameter("P_table_size",java.sql.Types.INTEGER);
callableStatement.executeUpdate();
Integer size = callableStatement.getInt(1);
System.out.println("size is: "+size);
But I am getting error given below:
Exception in thread "main" java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'RETRIEVE_TABLE_SIZE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
This is first time I am writing Stored Proc. Please rectify me if I am doing something wrong.
A few notes, first check out this stackoverflow question that is essentially the same. Basically, from sqldeveloper command console you will be able to run the query, but the owner of the procedure probably doesn't have the proper permissions, or they are via a Role and not direct.
Second, from the Oracle documentation on the topic, you need to indicate within your stored procedure the value of the output parameter P_table_size, like so:
SELECT bytes/(1048576*1024) INTO P_table_size FROM DBA_SEGMENTS WHERE SEGMENT_NAME = p_segment_name AND SEGMENT_TYPE = p_segment_type ;
Also note that your use of p_segment_name and p_segment_type are reversed; you had SEGMENT_NAME = p_segment_type and SEGMENT_TYPE = p_segment_name which will cause no end of confusion when you resolve the permissions problem and get your query running.
One final note, although this is speculative: you may be able to use FROM USER_SEGMENTS instead of FROM DBA_SEGMENTS. According to the docs it has the same layout and data, but only returns data for the current user, which might bypass the permissions problem.

What is Ordinal binding and Named binding in JDBC

What is Ordinal binding and Named binding in JDBC?
while calling a PL/SQL procedure i am getting an exception
java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!
In Oracle, for example, you can write a stored procedure with PL/SQL code like:
CREATE PROCEDURE remove_emp (employee_id NUMBER) AS
tot_emps NUMBER;
BEGIN
DELETE FROM employees
WHERE employees.employee_id = remove_emp.employee_id;
tot_emps := tot_emps - 1;
END;
/
When you call this from Java, you use code like:
CallableStatement cs = conn.prepareCall("{call remove_emp(employee_id)}");
cs.setInt(1, 42); // ordinal binding, or
cs.setInt("employee_id", 42); // named binding
With only one argument, the choice doesn't matter. However, you can't mix techniques.
CallableStatement cs = conn.prepareCall("{call xyzzy(plugh, bedquilt)]");
cs.setInt(1, 42); // ordinal binding, and
cs.setInt("plugh", 1729); // named binding
cs.executeQuery(); // throws
Ordinal means by index. Named means by name.
Google search reveals that this could come up in a number of ways to misuse the API, so it's impossible to guess which one you fell into without seeing your code.

Categories

Resources