Parameter index out of range when trying to retrieve the return value of a stored function - mysql

I have a function that takes a few parameters and is generating a unique varchar id to be returned to the application. When I call the function from my java application it executes (the data is inserted), but when I try to retrieve the outparam it throws SQL exception
Parameter index out of range (1 > number of parameters, which is 0).
java code:
String sql = "{?=call mytable.myFunction (?,?,?,?,?)}";
CallableStatement tmt = sqlConn.prepareCall(sql);
tmt.registerOutParameter(1, Types.VARCHAR);
tmt.setString(2, firstName);
tmt.setString(3, lastName);
tmt.setDate(4, new java.sql.Date(dob.getTime()));
tmt.setString(5, null);
tmt.setString(6, null);
tmt.execute();
String accountNumber = tmt.getString(1);
I'm using Navicat to work with MySQL, and the procedure executes in Navicat and shows the correct return value. However, when I call tmt.getString(1) from java app, it throws the above exception.
Please, help.
Thank you.

Related

ExecuteSqlCommand return -1?

I am trying to call a stored procedure from code , in ef core 2 i found that i can use context.database.ExecuteSqlCommand() function to execute any stored procedure in my database.
While the stored procedure works fine in my sql server instance :
calling it from my code , returns -1 result !?:
using (var context = new AZPDBDEMOGZContext(optionsBuilder.Options))
{
var existUser = context.Database.ExecuteSqlCommand("GetIdUsager_ByNomPrenomEmail #p0,#p1,#p2", parameters:new[] { "rouarouarouarouaroua", "wiem", "test#gmail.com" });
}
what m i doping wrong ?
ExecuteSqlCommand will only return a 'rows affected' integer for a DML query aka insert/update/delete. Your stored proc looks like its returning a result set so it returns -1 as you've not provided a statement that changes the data source. You'll need to create a POCO and use FromSql to populate it.

Why am I getting error 3078 on my SELECT query?

I've started to try and write some VBA to execute some queries and I've got stuck at the first hurdle. This is giving an error 3078 which apparently means it can't find the table or query. The table definitely exists and is spelt properly. Indeed the SQL runs fine - I tested it. What am I doing wrong?
Public Function Tester()
str_tbl = "tblGames_atp"
str_mkvrec = "SELECT * FROM " & str_tbl
dbl_fs_pct = DSum("FS", str_mkvrec)
End Function
Cannot reference SQL statement in domain aggregate function, not even a variable set to that statement. Must reference table or query object name. Could reference variable with name string but variable not really needed in this code. If you want function to return a value to calling source, then need to set function value.
Public Function Tester()
Tester = DSum("FS", "tblGames_atp")
End Function

SimpleJdbcCall for MySql Function yields "Can't set IN parameter for return value of stored function call"

Using the example from the Spring docs, I'm trying to return a value from a mySQL function. I keep getting the error Can't set IN parameter for return value of stored function call;.
I created a mySQL function that works fine (ran in MySQL Workbench). I've written a SimpleJdbcCall statement, set up the parameters as per Spring docs example but consistently get this error. If I turn the function into a procedure, the code works, I just have to retrieve the return value from the result set.
I used https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch13s05.html, section 13.5.8 as reference.
CREATE FUNCTION `ScenarioRegistration`(
environment VARCHAR(45),
username VARCHAR(15),
scenario_name VARCHAR(45)) RETURNS int(11)
A couple of SELECT statements followed by an INSERT then
RETURN scenario_id; // The inserted id
Java code:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess();
simpleJdbcCall.addDeclaredParameter(new SqlParameter("environment"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("username"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("scenario_name"
,Types.VARCHAR));
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
simpleJdbcCall.setReturnValueRequired(true);
Integer scenario_id = simpleJdbcCall.executeFunction(
Integer.class, parameters);
All I want the routine to do is give me back the id of the newly inserted scenario.
What I get is:
SQL [{? = call scenarioregistration(?, ?)}]; Can't set IN parameter for return value of stored function call.
I find it interesting that it's taken my THREE input values and changed them to an output and TWO input values.
Anyone enlighten me as to the problem and how to fix it?
Thanks,
Steven.
I would refer to the latest docs here for your answer. It appears Spring is trying to infer the output because you didn't explicity specify one.
Per the docs above there are two valid approaches on calling the desired function with the SimpleJdbcCall:
Inferred Parameters
Because you've specified withoutProcedureColumnMetaDataAccess, Spring isn't going to look and see what the ins/outs are to your function. If you want it easy, just don't specify that and you should be able to do:
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.executeFunction(Integer.class, parameters);
Explicit Parameters
If you want to keep withoutProcedureColumnMetaDataAccess turned off for whatever reason, you can do:
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate)
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("environment", "username", "scenario_name")
.declareParameters(
new SqlOutParameter("scenario_id", Types.NUMERIC),
new SqlParameter("environment", Types.VARCHAR),
new SqlParameter("username", Types.VARCHAR),
new SqlParameter("scenario_name", Types.VARCHAR)
).executeFunction(Integer.class, parameters);
Note: It appears that order is critical in this example. The output parameter should be declared first, and the subsequent named IN parameters come last. That is, the order of the parameters ? are ordinal in [{? = call scenarioregistration(?, ?, ?)}])
Alternative NamedParameterJdbcTemplate Solution
Another way to invoke your function is via an actual JDBC call. This could hypothetically save you the grief of using the fine tuning of the SimpleJdbcCall.
Integer scenarioId = namedParameterJdbcTemplate.queryForObject(
"SELECT ScenarioRegistration(:environment, :username, :scenario_name)",
parameters,
Integer.class);

Call stored procedure with an output parameter using ExecuteDataset

I need to call a stored procedure in a MySQL (5.7) database from a VB.NET application. Said procedure makes a SELECT statement at the end which I need to retrieve in my app as a DataSet. Previously it worked fine, but I added an output parameter to the stored procedure, and I get the following error when I call it:
{"Incorrect number of arguments for PROCEDURE my_database.SP_MY_PROCEDURE; expected 3, got
2"}
Here's my current VB.NET code:
Public Shared Function CallStoredProcedure(ByVal stringParam As String,
ByVal intParam As Integer) As DataSet
Try
Dim ds As New DataSet
Dim params As New List(Of MySqlParameter)
Dim arrayParams() As MySqlParameter
params.Add(New MySqlParameter("#param1", stringParam))
params.Add(New MySqlParameter("#param2", intParam))
arrayParams = params.ToArray()
ds = MySqlHelper.ExecuteDataset(connString,
"CALL SP_MY_PROCEDURE(#param1, #param2);",
arrayParams)
Return ds
Catch objException As Exception
Return Nothing
End Try
End Function
I tried adding a third parameter to the CALL statement in the string, like this:
ds = MySqlHelper.ExecuteDataset(connString,
"CALL SP_MY_PROCEDURE(#param1, #param2, param3);",
arrayParams)
but that just returns a different error:
{"OUT or INOUT argument 3 for routine gw_my_database.SP_MY_PROCEDURE
is not a variable or NEW pseudo-variable in BEFORE trigger"}
How can I accomplish this? Maybe ExecuteDataset can't be used with output parameters; at least I haven't found examples or anything. It that's the case, what's a good alternative?
You can definitely use ExecuteDataset() with output parameter. You need to make sure all the mandatory parameters are added to your parameter list including output parameter. You need to confirm the type and size where applicable and set the direction of each parameter correctly. After executing ExecuteDataset() you can retrieve the value from our output parameter.
I could not see adding the third parameter in your code (or perhaps you haven't showed that part), setting direction/type/size.

How to pass an array of parameters to MySql select ... in

I wish to select an array of records with id 2, 4, 6 from a mysql database file. I am trying to pass an array of integers to a Mysql store procedure. But I fail to create a working stored procedure.
Would you help me compose one?
This is the C# code
public static List<PhotoComment> GetPhotos(int[] _ids)
{
MySqlConnection _con = Generals.GetConnnection();
List<PhotoComment> _comments = new List<PhotoComment>();
try
{
MySqlCommand _cmd = new MySqlCommand("Photos_GetPhotosByIDs", _con);
_cmd.CommandType = CommandType.StoredProcedure;
_cmd.Parameters.AddWithValue("#_ids", _ids);
_con.Open();
MySqlDataReader _reader = _cmd.ExecuteReader();
while (_reader.Read())
{
PhotoComment _comment = new PhotoComment(_reader.GetInt32("cID"), _reader.GetInt32("cFID"), _reader.GetString("cUser"), _reader.GetString("cContent"), _reader.GetDateTime("cDate"), _reader.GetBoolean("cChecked"));
_comments.Add(_comment);
}
_con.Close();
}
catch (Exception _ex)
{
_con.Close();
ReportMgr.ReportException(_ex.Message);
}
return _comments;
}
this is the mysql
CREATE DEFINER=root#localhost PROCEDURE Photos_GetPhotosByIDs(in _ids int[])
BEGIN
select * from tbl_photos where ID in _ids;
END
There are no array types in MySQL. You can use table (temporary table) instead. Fill the bale with id values and join tables to get desired result.
I'm not sure if I'm getting your question right but what I think you're asking is how to send multiple values into an input parameter of a stored procedure.
If that's what you're asking, the following link may help. Not sure if such a feature exists in MySql but in SQL Server, it's called "Table-Valued Parameters" - TVP in short.
TVP allows you to pass multiple values into a single input parameter. Hope this helps: https://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx