I am trying to call a stored procedure.
A stored procedure is proven by tests in the database and executed
CREATE OR REPLACE FUNCTION statapi.pui_src_ter(p_src_ter_id id_t, p_aname name_t, p_adesc desc_t, p_sortord sortord_t)
RETURNS integer AS
$BODY$
DECLARE
afected_rows integer := 0;
BEGIN
update statdwh.src_ter
set aname = p_aname,
adesc = p_adesc,
sortord = p_sortord,
actdt = current_timestamp
where src_ter_id = p_src_ter_id;
get diagnostics afected_rows = row_count;
if (afected_rows = 0) then
insert into statdwh.src_ter(src_ter_id, aname, adesc, sortord, actdt)
values (p_src_ter_id, p_aname, p_adesc, p_sortord, current_timestamp)
returning src_ter_id into p_src_ter_id;
get diagnostics afected_rows = row_count;
end if;
return afected_rows;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION statapi.pui_src_ter(id_t, name_t, desc_t, sortord_t)
OWNER TO postgres;
the call itself
public void storedProcedureCall() throws ClassNotFoundException, SQLException {
CallableStatement cst = connection.prepareCall("{call statapi.pui_src_ter(?,?,?,?)}");
cst.setInt(1, 11);
cst.setString(2, "aname_att");
cst.setString(3, "adesc_att");
cst.setInt(4, 222);
ResultSet result3 = cst.executeQuery();
while (result3.next()){
System.out.println(result3.getString(1));
}
cst.execute();
}
returns "1" as expected, since modified one record, but in the database (I look through pgAdmin) record does not appear
What am I doing wrong?
Senior fellow replied simply "add connection.commit();"
Related
I am calling postgreSQL function from Java using SimpleJdbcCall and extracting the output in ResultSet, while the function returns data when run in postgre but in Java it is giving null result.
Here is my postgre function that I am calling:
CREATE OR REPLACE FUNCTION package.getdemojob(create_user_id character varying)
RETURNS TABLE(batch_id bigint, content_id character varying, start_date timestamp without time zone,
end_date timestamp without time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query
SELECT MY_TABLE.BATCH_ID, MY_TABLE.CONTENT_ID, MY_TABLE.START_DATE, MY_TABLE.END_DATE
FROM MY_TABLE
WHERE MY_TABLE.CREATE_USER = create_user_id
ORDER BY BATCH_ID;
END;
$function$
;
Java code that I am using to call this function is:
this.demoGetJob = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("package")
.withProcedureName("getdemojob")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("create_user_id")
.declareParameters(
new SqlParameter("create_user_id", Types.VARCHAR)
);
SqlParameterSource in = new MapSqlParameterSource().addValue("create_user_id", userId);
ResultSet rs = demoGetJob.executeFunction(ResultSet.class, in);
while(rs.next()){
System.out.println(rs.getInt("batch_id"));
}
On line rs.next() I am getting nullPointerException though there is data present in MY_TABLE with the given create_user_id
What wrong am I doing?
Thanks in advance.
drop PROCEDURE if exists insert_poo;
DELIMITER $$
CREATE PROCEDURE insert_poo(IN barcode varchar(250),IN qty float,IN amount float,IN vat float,IN
description varchar(250),IN clrk_code varchar(20),IN mechno varchar(20),IN bill_date datetime)
BEGIN
DECLARE unit_pric float;
DECLARE itemcode varchar(150);
SET unit_pric =(select retail1 FROM `mytable` WHERE `mytable`.barcode = barcode);
SET itemcode =(select prod_id FROM `mytable` WHERE `mytable`.barcode = barcode);
INSERT into mytable2(clrk_code,tran_code,tran_desc,tran_qty,unit_price,tran_amt,bill_date,tax)values(clrk_code,barcode,description,qty, unit_pric,amount,bill_date,vat)
END $$
DELIMITER ;
Kindly help with any solution on how to create and call it. thanks in advance
Probably you can use the following example as a reference:
The below one is the Store Procedure itself:
connect anyDbName/anyDbName
CREATE OR REPLACE PROCEDURE any_storeProcedure_name
-- Following are some example parameters you may use in your SP
(
id varchar2,
name_param varchar2,
-- The control status of the operation
statusOperation_out OUT VARCHAR2
)
AS
BEGIN
statusOperation_out := 'in_proccess';
insert into property_name values('Name', id, name_param);
COMMIT;
statusOperation_out := 'ok';
EXCEPTION
WHEN OTHERS THEN
statusOperation_out := 'error';
ROLLBACK;
END;
/
And the following is the Java method call that is using the previous SP:
public long addProperties(String id, String name) {
//The string sql syntax for calling the store procedure
String sql = "{CALL any_storeProcedure_name("
+ "id => ?, "
+ "name => ?)}";
try (Connection conn = CreateConnection.getDSConnection();
CallableStatement cs = conn.prepareCall(sql)) {
//The following are the parameters for the store procedure
cs.setString (1, id);
cs.setString (2, name);
//Following are the parameters to get some outputs from the store procedure
cs.registerOutParameter(3, Types.VARCHAR);
cs.executeQuery();
//The return varible from the store procedure is the one
//that is being used for feedback on whether the SP ran fine.
if (cs.getString(3).equalsIgnoreCase("ok")) {
System.out.println("Feedback from SP is: " + cs.getString(3));
return 1;
} else {
return 0;
}
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
}
So hope this can give some reference, by the way the DB I'm using is Oracle 11g. But I recall it's very similar to MySQL DB.
I have my Oracle DB Stored Function as below:
CREATE OR REPLACE FUNCTION FN_EMP_CNT (EMP_ID NUMBER) RETURN NUMBER
IS
OLD_COUNT NUMBER(5) DEFAULT 0;
NEW_COUNT NUMBER(5) DEFAULT 0;
BEGIN
SELECT
COUNT(EMP_ID) INTO OLD_COUNT
FROM
OLD_DEPT
WHERE
EID = EMP_ID
AND DEPT_STAT='Closed';
SELECT
COUNT(EMP_ID) INTO NEW_COUNT
FROM
NEW_DEPT
WHERE
EID = EMP_ID
AND DEPT_STAT='Closed'
RETURN (NEW_COUNT + OLD_COUNT);
END;
When I use the below sql query directly it returns the correct number as 2:
SELECT FN_EMP_CNT(123) FROM DUAL;
But when I use Spring JDBC Template for retrieving the data it returns null.
int noOfEmps = jdbcTemplate.queryForObject("SELECT FN_EMP_CNT(?) FROM DUAL", new Object[] { empID}, Integer.class);
The most probable cause is that you use a wrong order of parameters, see Javadoc queryForObject
queryForObject(java.lang.String sql, java.lang.Class<T> requiredType, java.lang.Object... args)
Query given SQL to create a prepared statement from SQL and a list of
arguments to bind to the query, expecting a result object.
So use first the required return type followed by the parameter
This works for my fine
sql = 'SELECT FN_EMP_CNT(?) FROM DUAL'
res = jdbcTemplate.queryForObject(sql, Integer.class, 4)
HTH
Iam trying to send an integer value from mysql Procedure which must be recieved by Java class. this i'hv done
CREATE DEFINER=`root`#`localhost` PROCEDURE `updateCountry`(o_name varchar(35), u_name varchar(50),m_by varchar(35),out msg int)
BEGIN
if not exists (select country from country where country = u_name) then
UPDATE country SET country= u_name, modify_date=now(), modify_by=m_by where country = o_name;
end if;
if exists (select country from country where country = u_name) then
set msg := '1';
end if;
END
and my java class is :
public void modifyCountry(String mod, String real, String crby)throws Exception {
Date d = new Date(System.currentTimeMillis());
System.out.print(d);
CallableStatement cs = conn
.prepareCall("{ call updateCountry(?,?,?,?)}");
cs.setString(1, real);
cs.setString(2, mod);
// cs.setDate(3, d);
cs.setString(3, crby);
cs.registerOutParameter(4, Types.INTEGER);
int check = cs.getInt(4);
System.out.print(check);
cs.execute();
}
And this is the error which im getting
No output parameters returned by procedure.
Try to execute the statement first then read the output parameter
I have written a function that I would like to call in Java. But I don't think it is able to do anything with the query that I passed. Following is my code from java:
String QUERY_LOCATION = "select (license_plate) as test from carInst( (select category_name from reservation where rid = ?) , (select lname from reservation where rid = ?))";
//PreparedStatement check_location = null;
PreparedStatement check_location = connection.prepareStatement(QUERY_LOCATION);
check_location.setInt(1, rid);
check_location.setInt(2, rid);
rs = check_location.executeQuery();
if (rs.next()) {
System.out.print("Car found: "+rs.getString("test")+"\n");
license_plate = rs.getString("test");
update_reservation.setString(5, license_plate);
bool = false;
} else {
System.out
.print("There is no car available\n");
}
And following is my stored procedure written in PL/pgSQL (PostgreSQL):
CREATE OR REPLACE FUNCTION carInst(cname varchar(20), loc varchar(20) )
RETURNS TABLE (license_plate varchar(6) ) AS $$
BEGIN
DECLARE cur CURSOR
FOR SELECT carinstance.license_plate, carmodel.category_name, carinstance.lname FROM carinstance,carmodel
WHERE carinstance.mid = carmodel.mid ;
BEGIN
FOR rec IN cur LOOP
RETURN QUERY SELECT distinct carinstance.license_plate FROM Carinstance
WHERE rec.category_name = cname
AND rec.lname = loc
AND rec.license_plate=carinstance.license_plate;
END LOOP;
END;
END;
$$ LANGUAGE plpgsql;
When I run the code in Java, the print statement prints a null value for Car found. I would really appreciate some help here.
Problems
Most importantly, the query in the LOOP is nonsense. You select rows from carinstance, but all conditions are on rec. This select all rows multiple times.
One END too many. FOR has no END, only LOOP has.
Whenever you feel the temptation to work with an explicit cursor in plpgsql, stop right there. Chances are, you are doing it wrong. A FOR loop has an implicit cursor anyway.
Don't mess with mixed case identifiers without double quotes. I converted all identifiers to lower case.
You use one simple query, spread out over a cursor and another query. This can all be much simpler.
Solution
Try this simple SQL function instead:
CREATE OR REPLACE FUNCTION car_inst(_cname text, _loc text)
RETURNS TABLE (license_plate text)
LANGUAGE sql AS
$func$
SELECT DISTINCT ci.license_plate
FROM carmodel cm
JOIN carinstance ci USING (mid)
WHERE cm.category_name = $1
AND ci.lname = $2
$func$;
Call:
SELECT license_plate AS test FROM car_inst(
(SELECT category_name FROM reservation WHERE rid = ?)
, (SELECT lname FROM reservation WHERE rid = ?)
);
Or build it all into your function:
CREATE OR REPLACE FUNCTION car_inst(_cname text, _loc text)
RETURNS TABLE (license_plate text)
LANGUAGE sql AS
$func$
SELECT DISTINCT ci.license_plate
FROM carmodel cm
JOIN carinstance ci USING (mid)
JOIN reservation r1 ON r1.category_name = cm.category_name
JOIN reservation r2 ON r2.lname = ci.lname
WHERE r1.rid = $1
AND r2.rid = $2;
$func$;
Call:
"SELECT license_plate AS test FROM car_inst(? , ?)";
Remember: The OUT parameter license_plate is visible anywhere in the body of the function. Therefore you must table-qualify the column of the same name at all times to prevent a naming collision.
DISTINCT may or may not be redundant.