I have the following stored procedure in mysql
DELIMITER $$
CREATE DEFINER=`user`#`%` PROCEDURE `sp_getJobs`()
BEGIN
SELECT * FROM jobs_table;
END$$
DELIMITER ;
and the following defined in hsqldb (for unit tests)
CREATE PROCEDURE sp_getJobs() READS SQL DATA
DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE result CURSOR WITH RETURN FOR SELECT * FROM jobs_table FOR READ ONLY;
OPEN result;
END
Spring framework code that executes stored procedure
query = "Call sp_getJobs"; //This is used when MySql is database
query = "Call sp_getJobs()"; //This is used when HsqlDb is used in testing
getJdbcTemplate().query(query, rs -> {
process(rs);
return null;
});
private void process(ResultSet rs) {
while (rs.next()) {
//do something
}
}
The spring code that executes mysql works fine, however, when I execute the same code against hsqldb I get an empty result set (rs.next() returns false).
Note - The createdata.sql file that I use for testing, creates the jobs_table and populates it with 6 rows of data too. So the table should have data.
The Spring code doesn't look right for HSQLDB procedures. It will probably work for a function that returns a table.
Change the procedure to FUNCTION and return a table containing the data.
Alternatively, use the procedure but after calling it, execute getMoreResults() prior to process(ResultSet rs) call.
While the code below didnt work for only hsqldb stored procedure listed in question
getJdbcTemplate().query(query, rs -> {
process(rs);
return null;
});
private void process(ResultSet rs) {
while (rs.next()) {
//do something
}
}
code below worked for all of them - mysql, sqlserver, informix & also hsqldb
SimpleJdbcCall simpleJdbcCall =
new SimpleJdbcCall(getJdbcTemplate().getDataSource())
.withCatalogName(catalog)
.withProcedureName(query);
where catalog is the package name. So, if your stored procedure is such as accounts.get_all_expired_accounts then catalog="accounts" & query="get_all_expired_accounts".
Related
I am using snowflake-jdbc-3.13.8.jar and jdk1.8.0_151 to implement snowflake stored procedure which has an OUT parameter. I am getting
net.snowflake.client.jdbc SnowflakeLoggedFeatureNotSupportedException
on the line where registerOutParameter is called.
‛‛‛
CallableStatement st = connection.prepareCall("call sp_poc(?)"); //Call proc
st.registerOutParameter(1,java.sql.Types.VARCHAR); //exception here
ResultSet rs= st.executeQuery(); //execute st
‛‛‛
Below is the procedure created on snowflake db
CREATE or Replace PROCEDURE sp_poc()
RETURNS VARCHAR
LANGUAGE javaScript
AS
$$
var rs="test";
return rs;
$$;
You cannot use the output of a Snowflake stored procedure directly. If you want to get its return output, you need to run another query. This is true whether it's running from the web UI or through a driver or connector:
call sp_poc();
select * from table(result_scan(last_query_id()));
If you don't want to depend on the last_query_id() function, you can capture the query ID in the JDBC call. You can refer to the getQueryId() method of the Snowflake JDBC driver here:
https://docs.snowflake.com/en/user-guide/jdbc-api.html#interface-snowflakecallablestatement
If you capture the query ID that way, you can then get the output results of the SP for up to 24 hours after its completion using:
select * from table(result_scan(?));
Where the bind variable is the query ID returned from the getQueryId() JDBC method.
while working on JDBC, I got an issue I have created a table in mysql which contains the employee info Employee_Id,Name,City,Salary and Year_of_joining and i also created a stored procedure to the same database which takes two inputs and update the salary of employees base on the year of joining. Here is the Stored Procedure:
CREATE PROCEDURE proc(IN var1, IN var2)
BEGIN
UPDATE "TABLE" SET Salary=var1+Salary WHERE Year_of_Joining= var2
END
Now i Created a database connection through java to mysql database (That connection is being established successfully)
But now, When i execute the query after creating the CallableStatement object and try to convert the current result of callable object to Result set i get null . Please help me with this.
Here is the Code:
// Creates connection with java:
Connection con= DriverManager.getConnection(url,username,pswrd);
// Now Calling the Stored procedure from mysql
CallableStatement col = con.prepareCall("{call proc(?,?)}");
// gave values to the procedure
col.setDouble(1,20000);
col.setInt(2,2012);
col.execute();
// Returning Result set=null
ResultSet rs = col.getResultSet();
Firstly, you have not set the output parameter in your stored procedure.
Like :
CREATE PROCEDURE proc(IN inputParam VARCHAR(255), OUT OutParam INT)...
Then, to retrieve the values of output parameters (parameters
specified as OUT or INOUT when you created the stored procedure), JDBC
requires that they be specified before statement execution using the
various registerOutputParameter() methods in the CallableStatement
interface.
col.registerOutParameter("OutParam", Types.INTEGER);
Secondly, UPDATE statements don't return a ResultSet! Only SELECT statements return a ResultSet to operate upon.
I am trying to insert into a db that I have, and I'd like to do so through parameters. I am connecting to a postgres db using java.
I can connect to the db just fine. I know that because I have various operations that I am using that are already working were I can see, and update existing rows in my db. I am having trouble with INSERT.
I have the following:
private String _update_rentals = "INSERT into rentals (cid, mid) values (?,?)";
private PreparedStatement _update_rentals_statement;
private String _update_movie_status = "UPDATE Movie SET checkedout = true WHERE mid = ?";
private PreparedStatement _update_movie_status_statement;
And I initialize them:
_update_movie_status_statement = _customer_db.prepareStatement(_update_movie_status);
_update_rentals_statement = _customer_db.prepareStatement(_update_rentals);
And
while (movieAvail.next()){
System.out.println(movieAvail.getBoolean(1));
if (movieAvail.getBoolean(1) == false){
//Do chekcout
_update_rentals_statement.clearParameters();
_update_rentals_statement.setInt(1, cid);
_update_rentals_statement.setInt(2, mid);
_update_rentals_statement.executeQuery();
_update_movie_status_statement.clearParameters();
_update_movie_status_statement.setInt(1, mid);
_update_movie_status_statement.executeQuery();
System.out.println("Enjoy your movie!");
}
}
I am getting an error with both of the executeQuery() calls. For some reason I am getting the following error with both:
Exception in thread "main" org.postgresql.util.PSQLException: No results were returned by the query.
I looked at other posts, and I believed that I was following syntax for both insert/ update correctly, so maybe I am overlooking some aspect of this.
This is all part of a larger code base, so I did not want to include the methods these pieces of code are in. But these are the isolated instances which play a part with this code.
In general, when you execute a query, you are willing to retrieve some kind of information from the database. This is usually the case when you are executing SELECT queries. However, with INSERT and UPDATE statements, you are not querying the database, you are simply executing an update or inserting new rows. In the documentation of PreparedStatement you can see in which cases an exception is being thrown when you try to call executeQuery:
Throws: SQLException - if a database access error occurs; this method
is called on a closed PreparedStatement or the SQL statement does not
return a ResultSet object
So in your case the problem is that your statements do not return a ResultSet. You should use execute or executeUpdate instead. The former simply executes the update, while the latter does the same, but also returns the number of affected rows.
I think the main issue is that you are calling executeQuery(), which expects a result to be returned, but Insert/Update are not queries and don't return a result. Try just calling execute().
How to make query like this in Java and get the results:
SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num
Or, I think will be better if I create procedure in Postgres from this query.
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS void AS
$$
BEGIN
SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num
end;
$$
LANGUAGE 'plpgsql'
and call it
Connection ce_proc= null;
ce_proc = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc = ce_proc.prepareCall("{get_geom_difference()}");
proc.execute();
proc.close();
ce_proc.close();
But how to get results from this procedure in Java?
UPDATE
I tried this SP
DROP FUNCTION get_geom_difference();
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS integer AS
$$
DECLARE
tt integer;
BEGIN
SELECT filedata.num INTO tt
FROM filedata
Where filedata.num=1;
RETURN tt;
END;
$$
LANGUAGE 'plpgsql'
and call
Class.forName("org.postgresql.Driver");
Connection connect= null;
connect = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc = connect.prepareCall("{?=call get_geom_difference()}");
proc.registerOutParameter(1, java.sql.Types.INTEGER);
proc.executeQuery();
ResultSet results = (ResultSet) proc.getObject(1);
and got an error:
org.apache.jasper.JasperException: An exception occurred processing
JSP page /commit_changes.jsp at line 25in lineproc.executeQuery();
root cause javax.servlet.ServletException:
org.postgresql.util.PSQLException: No results were returned by the
query
But query
SELECT filedata.num
FROM filedata
Where filedata.num=1;
returns 1.
Where is mistake?
You can largely simplify the function. (Keeping simplistic function for the sake of the question.)
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS integer AS
$BODY$
SELECT num
FROM filedata
WHERE num = 1
LIMIT 1; -- needed if there can be more than one rows with num = 1
$BODY$ LANGUAGE SQL;
Though, technically, what you have in the question would work, too - provided the data type matches. Does it? Is the column filedata.num of type integer? That's what I gather from the example. On your other question I was assumingnumeric for lack of information. At least one of them will fail.
If the return type of the function doesn't match the returned value you get an error from the PostgreSQL function. Properly configured, your PostgreSQL log would have detailed error messages in this case.
What do you see, when you create the above function in PostgreSQL and then call:
SELECT get_geom_difference(1);
from psql. (Preferably in the same session to rule out a mixup of databases, ports, servers or users.)
Calling a simple function taking one parameter and returning one scalar value seems pretty straight forward. Chapter 6.1 of the PostgreSQL JDBC manual has a full example which seems to agree perfectly with what you have in your question (My expertise is with Postgres rather than JDBC, though).
There are quite a few different CallableStatement constructors, but only two of them let you get results back.
A ResultSet is returned by CallableStatement.executeQuery(). There's a good complete example in the link above.
I don't know if getting a scalar result back from a CallableStatement is legal. I'd expect PgJDBC to translate it to a rowset of one row, though, so it should work.
Your query example is typical. So what you will need is
Java Database Connectivity (JDBC)
and everything needed to serv it, is in package java.sql
So at this point I recoemnd you to read some tutorial and if you have some particular problem write about it on SO.
You will need JDBC to do that. You should be able to find all JDBC related information here.
Take a look here for a more detailed tutorial on how to connect your Java application to your PostgreSQL.
works 100% java 7 and postgres pgadmin 2016, Use createNativeQuery In your transaction write this
and change myschema.mymethodThatReturnASelect
for the scheme and the name of your function.
#Override
public List<ViewFormulario> listarFormulario(Long idUsuario) {
List<ViewFormulario> list =null;
try {
Query q = em.createNativeQuery("SELECT * FROM myschema.mymethodThatReturnASelect(?);");
q.setParameter(1, idUsuario);
List<Object[]> listObject = (List<Object[]>) q.getResultList();
if (listObject != null && !listObject.isEmpty()) {
list = new ArrayList<>();
for (Object o[] : listObject) {
ViewFormulario c = new ViewFormulario();
c.setIdProyecto(o[0] != null ? Long.valueOf(o[0].toString()) : -1L);
...etc...etc.
I have a table named employee, which has his id, name, phone number. I am using MySQL as my database. I am using Java Swing for that. I am searching the employee table with name now using Java (I have used like clause in my Java page).
Now I need to implement that function in stored procedures. Is it possible? And how can we take that resultset in Java code, if it is possible??
Now I have written my stored procedure as follows
BEGIN
SELECT * FROM employee where empName like '%su%'
END
Sample code will be appreciated..
Thanks
First thing is you should write msql procedure that sends parameter for LIKE,
CREATE PROCEDURE simpleproc (param1 CHAR(20))
BEGIN
SELECT * FROM employee where empName like param1;
END
Then from java program you can use this code to use procedure,
CallableStatement cstmt = con.prepareCall("{call simpleproc(?)}");
cstmt.setString(1, "%su%");
ResultSet rs = cstmt.executeQuery();
When executing a stored procedure it may actually return multiple ResultSet objects and/or update counts if it does several statements.
You use CallableStatement to execute the proc and then getResultSet() or getUpdateCount() to get the right result. For multiple results sets/statements you call getMoreResults() to move through the results of the stored proc.
For a simple case like this you should just need to call getResultSet() once and process it.
Yes you can. A stored procedure can even return multiple resultsets.
DELIMITER $$ -- recognized by mysql client but not phpmyadmin
CREATE PROCEDURE prc_test()
BEGIN
SELECT *
FROM employee
WHERE empName LIKE '%su%';
END;
$$
DELIMITER ;
CALL prc_test(); -- to call