Select count return 0 mysql JDBC - mysql

I'm trying to store messages, so i create 2 tables in mysql with HeidiSql, the first one is msg and the second one is users. I wrote a store procedure to get the number of messages that have as sender the first parameter, as recipient the second parameter and viceversa, i stored this value in id variable. I need the variable to count the messages between 2 people. When i run the application from java, i always get id=0. I can't understand the mistake.
...
sql="call getIdMsg(?,?,?)";
sql2="call addRecord(?,?,?,?)";
try (Connection conn= DriverManager.getConnection(db_url,username,password);
CallableStatement statement = conn.prepareCall(sql);
CallableStatement statement2 = conn.prepareCall(sql2)){
statement.setInt(1,sender);
System.out.println(sender);
statement.setInt(2,recipient);
System.out.println(recipient);
statement.registerOutParameter(3, Types.INTEGER);
statement.execute();
id=statement.getInt(3);
System.out.println("ID is: "+id);
statement2.setInt(1,sender);
statement2.setInt(2,recipient);
statement2.setInt(3,id);
statement2.setString(4,msg);
statement2.execute();
System.out.println("The record is been added");
}
catch (SQLException sqle){sqle.printStackTrace();}
...
This is my sql code:
BEGIN
set #id = ((select count(*) from msg WHERE sender = #thisrecipient and recipient = #thissender)+(SELECT COUNT(*) FROM msg WHERE sender = #thissender and recipient = #thisrecipient));
END
These are my parameters:
thissender INT IN
thisrecipient INT IN
id INT OUT
Could you help me please?

Related

My SQL SELECT STATEMENT returns an empty table instead of an error

My SELECT count function returns the number of kids in a specific profile that has in id (secte = id_profile). When I input an invalid profile, the select statement returns an empty table insead of an error that I can solve. Any tips? (The tables are created by me);
CREATE OR REPLACE FUNCTION bursieri(sectie profile.id_profile%type)
return number IS
numar number(3) := 0;
BEGIN
select count(s.first_name) into numar
from student s, profile p,class c
where s.id_class = c.id_class and c.id_profile = p.id_profile
and p.id_profile=sectie;
return numar;
END bursieri;
/
--profilul 71
BEGIN
dbms_output.put_line('Exista ' || bursieri(9100) || ' studenti bursieri');
END;
I tried to give an invalid profile id and expected an error, but instead I got an empty table

Return value for mySql UPDATE

I'm working on a springboot app and have this update function in my Mapper class that updates the field groupId if groupId exists in the DB.
#Update("UPDATE user SET groupId = " +
"IF(EXISTS(SELECT * FROM allGroup WHERE groupId = #{groupId}) is true, #{groupId}, groupId) " +
"WHERE email = #{email}")
int updateUserGroup(#Param("groupId") Integer groupId, #Param("email") String email);
This function returns 1 regardless of whether groupId was really updated. Is there a way to tell if that field was changed? Having the function return 0 or something when no changes were made for example. Thank you!

How to get RowsAffected in Go-Gorm's Association Mode

I insert a relation by the following code:
db.Where(exercise).FirstOrCreate(&exercise).Model(&User{ID: userID}).Association("Exercises").Append(&exercise)
Corresponding SQL printed by debug console to the code is:
INSERT INTO `user_exercise` (`user_id`,`exercise_id`) SELECT 1,1 FROM DUAL WHERE NOT EXISTS (SELECT * FROM `user_exercise` WHERE `user_id` = 1 AND `exercise_id` = 1)
I want know if there are new record created in user_exercise, but due to the generated SQL, if a relation in user_exercise already exists, it won't insert and produce no error.
Go-Gorm's Association object doesn't have a RowsAffected attribute, so I can't get RowsAffected from the query to confirm if a new record is created.
Though I can get RowsAffected from the first db object, like
db.Where(exercise).FirstOrCreate(&exercise).Model(&User{ID: userID}).Association("Exercises").Append(&exercise)
if db.RowsAffected == 1 {
// do something
}
I wonder since the db is shared by all queries, if another query executed at the same time and affected rows > 0, is it safe to get RowsAffected from the global db object?
Assuming that the user_execise table has an unique constraint (user_id, exercise_id) the insert should return an error if you try to do it to an already created record. (Exactly what you want)
So just do something like this...
db.Where(exercise).FirstOrCreate(&exercise)
ue := struct {
UserID uint
ExerciseID uint
}{
UserID: userID,
ExerciseID exercise.ID
}
if err := db.Table("user_exercise").Create(&ue).Error; err != nil {
// will enter here if it wasn't created
}
If it doesn't returns an Error means that a new record was created

MVC with no Entity Framework

From the below source tutorials:
https://www.youtube.com/watch?v=Jt9vSY802mM
http://www.dotnetawesome.com/2017/07/curd-operation-on-fullcalendar-in-aspnet-mvc.html
How do I do the above code samples without Entity Framework, by just using SQL queries?
For example in the above source code, instead of
var v = dc.Events.Where(a => a.EventID == eventID).FirstOrDefault();
if (v != null)
{
dc.Events.Remove(v);
dc.SaveChanges();
status = true;
}
I want to do
DELETE FROM Even WHERE EventID = {0}
FirstOrDefault() in LINQ is equivalent to LIMIT 1 in MySQL, hence the LINQ function can be converted to SQL commands using IF or CASE WHEN like this (assumed commands are running inside a stored procedure):
DELIMITER //
-- 'Events' is a DbSet name by common convention,
-- therefore table name should be 'Event'
CREATE PROCEDURE procedure_name (IN eventID INT)
BEGIN
DECLARE v INT;
SET v = SELECT EventID FROM Event WHERE EventID = eventID LIMIT 1;
CASE WHEN v IS NOT NULL
THEN DELETE FROM Event WHERE EventID = v
ELSE -- do something else
END
-- alternative:
-- IF(v IS NOT NULL, DELETE FROM Event WHERE eventID = v, 0)
-- other stuff here
END//
DELIMITER ;
Note: If EventID is a primary key column, you can remove LIMIT 1 because query result only return single value.
Then, use CALL procedure_name(eventID) or include procedure_name in MySqlCommand to execute it.
Couple of ways:
using raw query in Entity Framework:
Open connection string via SqlConnection and execute:
Pseudo code for method 1:
string sqlDeleteStatement = "DELETE FROM Even WHERE EventID = #id";
List<SqlParameter> parameterList = new List<SqlParameter>();
parameterList.Add(new SqlParameter("#id", 1)); delete id = 1
_context.Database.SqlQuery(sqlDeleteStatement, parameterList);
Pseudo code for method 2:
using(SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = "Server=[server_name];Database=[database_name];Trusted_Connection=true";
string sqlDeleteStatement = "DELETE FROM Even WHERE EventID = #id";
SqlCommand command = new SqlCommand(sqlDeleteStatement , conn);
command.Parameters.Add(new SqlParameter("#id", 1)); //delete id = 1
command.ExecuteNonQuery();
}

SimpleJDBCCall handle out paramater with resultset

I am using spring jdbc. I want result set with out param. separately i done but together i am not able to do.
CREATE DEFINER=`xxx`#`%` PROCEDURE `client_xxxx`(
IN p_xxxx TINYINT(1) UNSIGNED,
IN p_result SMALLINT(2) UNSIGNED,
OUT p_result BIT ) BEGIN
IF EXISTS(SELECT 1 FROM xxx WHERE xxx = 1 AND xxx = 1) THEN
SELECT ...;
SET p_result = 0;
ELSE
SELECT ...;
SET p_result = 1;
END IF;
END
spring jdbc code
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource).withProcedureName(sp);
List<Map<String, Object>> list = (List<Map<String, Object>>) jdbcCall.execute(paramsArray).get("#result-set-1");
list get the result set with result set how can i get p_result with that.
I find it in simple way that i miss.
public Map<String, Object> xxx(String sp, Object... paramsArray) {
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource).withProcedureName(sp);
return jdbcCall.execute(paramsArray);
}
execute() gives two parameters default
i.e.
1) #result-set-1
2) #update-count-1
#result-set-1 result set i.e. select record
and #update-count-1 returns update count. If we want to access result with select statement with out parameter. we just have to declare out parameter. execute() gives all the things in Map<String, Object> type.
So from map we can get all the multiple values that stored procedure returns.
For example my SP like
PROCEDURE xxx(
IN xxxxTINYINT(1) UNSIGNED,
IN xxxSMALLINT(2) UNSIGNED,
OUT p_isconfig BIT
)
BEGIN
SELECT....
SET p_isconfig = 1;
END
So in #result-set-1 i get select result.
and p_isconfig gives me result to. If you have any confusion then you can iterate map and identify that how get return parameters.
Iterator i = map.keySet().iterator();
while ( i.hasNext() ) {
String key = (String) i.next();
String value = params.get( key );
System.out.println("key: " + key + " --- value: " + value) ;
}
This way i found solution after reading many things. If any one have other option for this solution then please share with me.
You can try morejdbc (available in maven central) to call your procedure, it's more laconic and it's type safe:
import static org.morejdbc.SqlTypes.BIGINT;
import static org.morejdbc.NamedJdbcCall.call;
import org.morejdbc.*;
...
private JdbcTemplate jdbcTemplate;
...
Out<Integer> out = Out.of(INTEGER);
jdbcTemplate.execute(call("client_xxxx")
.in("p_xxxx", pValue)
.out("p_result", out));
System.out.println("Result is " + out.get());
For ref_cursor out parameter and Oracle database you can use
Out<List<Record>> out = Out.of(OracleSqlTypes.cursor((rs, idx) -> new Record(rs)));
jdbcTemplate.execute(call("client_xxxx")
.in("p_xxxx", pValue)
.out("p_result", out)); // will auto-close ref-cursor
System.out.println("Got result records: " + out.get());