I am using the below code in google apps script to insert employee record from a Google Sheet into a mysql database.
The stored procedure [dbo].[insertemployee] accepts "#empname" parameter.
var empname = 'test';
var mysqldbconn = Jdbc.getConnection(url,username,password);
var mysqlquery = mysqldbconn.createStatement();
callstoredprocedure = "{call [dbo].[testemployee](?)}";
mysqlquery = mysqldbconn.prepareCall(callstoredprocedure);
mysqlquery.setString(1, empname);
mysqlquery.executeUpdate();
This gives me this error "Must declare the scalar variable "#empname"".
Perhaps reading this might help you:
Calling MySQL Stored Procedures from JDBC
This is where you go wrong:
mysqlquery = mysqldbconn.prepareCall(vstrSQLStatement);
You don't use the declared 'callstoredprocedure'.
Read example below:
public static void getSkills(int candidateId) {
//
String query = "{ call get_candidate_skill(?) }";
ResultSet rs;
try (Connection conn = MySQLJDBCUtil.getConnection();
CallableStatement stmt = conn.prepareCall(query)) {
stmt.setInt(1, candidateId);
rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(String.format("%s - %s",
rs.getString("first_name") + " "
+ rs.getString("last_name"),
rs.getString("skill")));
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
Let me explain:
The query is defined, similar to your call accepting 1 parameter returning no value. Then it is used in the: conn.prepareCall() , and then the parameter is set to the statement and then it is executed.
As I mentioned, you should do this:
mysqlquery = mysqldbconn.prepareCall(callstoredprocedure);
Please let me know, if this fixed your problem.
Related
I am getting errors when I try to send string parameters using EF Core in ASP.NET Core 5 and use EF MySQL 5.0.8. The error is Input string was not in a correct format.
I am using this EF Core Library:
https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework60.html
If I send int parameters the solution below works fine.
MYSQL Procedure
CREATE DEFINER=`MYUSER`#`%` PROCEDURE `test_sp`(
IN param1 int,
IN param2 text
#I tried type text, varchar, char
)
BEGIN
SELECT 1 as id, param1 as parameter, 'this is Parameter 1 INT' as text
UNION
SELECT 2 as id, param2 as parameter, 'this is Parameter 2 VARCHAR' as text;
END
ASP.NET CORE 5 CLASS
public async Task<List<T>> ExecuteStoredProcedure(string nameProcedure, List<MySqlParameter> parameters = null)
{
try
{
using (var data = new ContextBase(_optionBuilder))
{
//Add Space to separate sp name of the parameters
nameProcedure += "(";
var count = parameters.Count;
int i = 0;
//Insert the parameters in the procedure name
for (i = 0; i < count; i++)
{
nameProcedure += parameters[i].ParameterName;
if(i + 1 < count)
{
nameProcedure += ", ";
}
else
{
nameProcedure += ")";
}
}
//Remove the last Comma from the query
var responseData = await data.Set<T>().FromSqlRaw<T>("CALL " + nameProcedure, parameters.ToArray()).AsNoTracking().ToListAsync();
return responseData;
}
}
catch (Exception ex)
{
ErrorLog error = new ErrorLog();
error.Error = ex.Message;
error.Description = "Error encountered DB Procedure Execute ***. Message:" + ex.Message + " when getting the Generic Procedure Execute";
error.Section = "RepositoryProcedureGenerics.cs";
error.Layer = "Infra";
error.Date = DateTime.Now;
await this.CreateError(error);
return null;
}
}
ASP.NET CORE CONTROLLER
public async Task<IActionResult> ExecProcedure([FromQuery(Name = "param1")] int param1, [FromQuery(Name = "param2")] string param2)
{
//Create the list of Parameters
List<MySqlParameter> listParameters = new List<MySqlParameter>();
//int par = 1;
//string par2 = "XXX";
listParameters.Add(new MySqlParameter("#param1", MySqlDbType.Int32));
//I TRIED MySqlDbType.Text, MySqlDbType.VarChar and MySqlDbType.VarString
listParameters.Add(new MySqlParameter("#param2", MySqlDbType.Text));
listParameters[0].Value = param1;
listParameters[1].Value = param2;
string sp_name = "test_sp";
//Execute the Procedures
List<Test> test = await _procedureExecutor.ExecuteStoredProcedure(sp_name, listParameters.ToList());
return Ok();
}
Does someone knows where is my mistake?
I have the following query to select a list of vocabulary from a Japanese dictionary.
SELECT * FROM dictionary
WHERE from_local = 1
AND (word like '%後%' or reading like '%後%')
Running this program in HeidiSQL, it works as expected. I feel like it could be a charset issue but I don't think it would work at all if this were the case. (See screenshot)
My problem occours when I try to run this query in my Node.js app. The results return empty.
I am using npm's mysql library. The dbQuery method is a helper function I made (Pastebin link)
import { dbQuery } from '../db'
const search = async(query) => {
try {
let sql = 'SELECT * FROM dictionary WHERE'
sql += ' from_local = ? AND'
sql += ' (word = ? OR reading = ?)'
const params = [1, '%'+query+'%', '%'+query+'%']
console.log('dictionary DB', {query, sql, params})
return await dbQuery(sql, params)
}
catch(err) {
console.log('search Error', err)
}
}
Soultion I was being stupid
I had forgot to change the = to LIKE in my query
I want to use datepicker to select range of dates. This range of dates is then queried in the database where the sum is counted...
My attempt:
public static int dateRange(){
int value = 0;
PreparedStatement stmt = null;
try {
Connection connection = DriverManager.getConnection("", "", "");
stmt = connection.prepareStatement("SELECT SUM(cost) FROM Items WHERE expiration_date between '" + Budget.datePicker1.getValue() + "' and '" + Budget.datePicker2.getValue() + "'");
ResultSet result = stmt.executeQuery();
result.next();
String sum = result.getString(1);
value = Integer.parseInt(sum);
} catch (Exception e){
value += 0;
}
return value;
}
It works. It returns the total if the days are there so to speak. If there are no days in the database as selected in the DatePicker then 0 pops up... But it looks messed up (catch block) and I was wondering if anyone could help me with an alternative solution?
First, since the value returned by the query is an integer value, there is no need to read it as a string and parse it. Just use result.getInt(...).
Second, if you are going to use a PreparedStatement, use it to properly set parameters, instead of building the query out of concatenated strings. Doing the latter exposes your application to SQL injection attacks.
If none of your dates are in range, then the SQL query will return NULL. Calling getInt() on column in a result set that is NULL will return 0, so you will get the result you want in that case anyway. If the previous value you got from a result set was SQL NULL, then calling result.wasNull() will return true, so if you really did need to handle that case separately, you could use that mechanism to do so.
You can do:
public static int dateRange(){
int value = 0;
// Use try-with-resources to make sure resources are released:
try (
Connection connection = DriverManager.getConnection("", "", "");
PreparedStatement stmt = connection.prepareStatement(
"SELECT SUM(cost) FROM Items WHERE expiration_date between ? and ?");
) {
stmt.setDate(1, Date.valueOf(Budget.datePicker1.getValue()));
stmt.setDate(2, Date.valueOf(Budget.datePicker2.getValue()));
ResultSet result = stmt.executeQuery();
result.next();
// Note that if there are no values in range, the SQL result will be NULL
// and getInt() will return 0 anyway.
value = result.getInt(1);
// however, if you need to explicitly check this and do something different
// if nothing is in range, do:
if (result.wasNull()) {
// nothing was in range...
}
} catch (SQLException e){
// this actually indicates something went wrong. Handle it properly.
Logger.getGlobal().log(Level.SEVERE, "Error accessing database", e);
// inform user there was a db error, etc...
}
return value;
}
i just wander if there is away to check MySql asp Table if its Cells has Values or Not .
i'v used this to return if Database has Row/Record there
string ConnectionString = #"Server=MYSQL5011.Smarterasp.net;Database=db_9d6c52_ahmed;Uid=9d6c52_ahmed;Pwd=******;";
MySqlConnection GetConnection = new MySqlConnection(ConnectionString);
GetConnection.Open();
string VoiceorScreenSearch = "Select User_Voice ,User_Screen From User where User_Stat=#UserStat";
MySqlCommand Comand = new MySqlCommand(VoiceorScreenSearch, GetConnection);
Comand.Parameters.AddWithValue(#"UserStat", key);
MySqlDataReader ReadData = Comand.ExecuteReader();
if (ReadData.HasRows)
{
hasrowsornot = true;
}
but i need it to return if Cell[1] is null or Has data !, My Cells Datatype is BLOB
and tips of doing this ? , will be helpful
Thanks
You can try like this:
if (!ReadData.IsDbNull(yourfield)) {
var value = ReadData.GetString(yourfield);
// some code
}
I have this sql statement:
selectAllUsersByCriteria = connection.prepareStatement(
"SELECT * FROM Users WHERE ? = ?" );
And the follow method running the statement:
public ArrayList<User> getUsersByCriteria(String 1criteria, String 2criteria)
{
ArrayList<User> results = null;
ResultSet resultSet = null;
try
{
selectAllUsersByCriteria.setString( 1, 1criteria);
selectAllUsersByCriteria.setString( 2, 2criteria);
// executeQuery returns ResultSet containing matching entries
resultSet = selectAllUsersByCriteria.executeQuery();
results = new ArrayList< User >();
while ( resultSet.next() )
{
results.add( new User( resultSet.getString( "userName" ),
resultSet.getString( "Password" ),
resultSet.getBoolean( "AdminRights" ),
resultSet.getDouble( "Balance" )
) );
} // end while
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch
finally
{
try
{
resultSet.close();
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
close();
} // end catch
} // end finally
return results;
}
It doesn't work. I figure it is the first ? that is the issue. Isn't it possible to set the WHERE ? as a ?. Can it be solved in another way.
It is a table I want to show, but it should only be show the users follow it meet the two criteria.
You would need to inject the column name directly into the string. That would open you up to a SQL injection attack, so I'd recommend querying (and probably caching) the table's schema info (specifically found in INFORMATION_SCHEMA.COLUMNS).
This way you can make sure that your user-submitted column name matches one of the column names in your table before injecting it into the script by seeing if it's in your list of available columns.