Using temporary table in stored procedure of mysql, looks like that data in temporary table are added any procedure calling without clearing the data :
DROP procedure IF EXISTS sp_fillUserTasksReport;
create procedure sp_fillUserTasksReport(
OUT out_returnCode bigint unsigned
)
BEGIN
DECLARE userId int unsigned;
DECLARE userName varchar(100);
DECLARE userEmail varchar(100);
DECLARE activeTasksCount int unsigned;
DECLARE completedTasksCount int unsigned;
DECLARE hasActiveTeamLeadTasks int unsigned;
DECLARE taskJson json;
DECLARE done INT DEFAULT FALSE;
DECLARE usersCursor cursor
for SELECT users.id, users.name, users.email
FROM users
ORDER BY users.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE IF NOT EXISTS tempUserTasksReport
(
user_id bigint unsigned,
user_name varchar(100),
user_email varchar(100),
active_tasks_count int unsigned,
completed_tasks_count int unsigned,
has_active_team_lead_tasks int unsigned,
assigned_tasks json DEFAULT NULL
);
-- DELETE FROM tempUserTasksReport;
-- I HAD TO UNCOMMENT ROW ABOVE TO CLEAR DATA - BUT THAT SEEMS not very good decision
SET out_returnCode := 0;
open usersCursor;
usersLoop:
loop
-- get all children of in_taskId and check them
fetch usersCursor into userId, userName, userEmail;
IF done THEN
LEAVE usersLoop;
END IF;
select count(*)
into activeTasksCount
from users
where userId in (select distinct task_user.user_id
from task_user,
tasks
where tasks.status = 'T'
and task_user.task_id = tasks.id);
select count(*)
into completedTasksCount
from users
where userId in (select distinct task_user.user_id
from task_user,
tasks
where tasks.status = 'D'
and task_user.task_id = tasks.id);
select count(*)
into hasActiveTeamLeadTasks
from users
where userId in (select distinct task_user.user_id
from task_user,
tasks
where tasks.status = 'T'
and task_user.task_id = tasks.id
and task_user.team_lead = 1);
SELECT JSON_ARRAYAGG(JSON_OBJECT('id', task_user.task_id, 'title', tasks.title))
INTO taskJson
FROM task_user,
tasks
WHERE task_user.user_id = userId
AND task_user.task_id = tasks.id;
-- Insert into the temporary table
INSERT INTO tempUserTasksReport (user_id, user_name, user_email, active_tasks_count, completed_tasks_count,
has_active_team_lead_tasks, assigned_tasks)
VALUES (userId, userName, userEmail, activeTasksCount, completedTasksCount, hasActiveTeamLeadTasks, taskJson);
SET out_returnCode := out_returnCode + 1;
end loop usersLoop;
close usersCursor;
INSERT INTO user_tasks_report (user_id, user_name, user_email, active_tasks, completed_tasks, has_active_team_lead_tasks, assigned_tasks, created_at)
select user_id, user_name, user_email, active_tasks_count, completed_tasks_count, has_active_team_lead_tasks, assigned_tasks, NOW() from tempUserTasksReport;
END;
Not sure, if deleting the table data in the beginning of the procedure is good decision ?
8.0.34-0ubuntu0.22.04.1
Thanks in advance!
2
Answers
The docs explain how temporary tables work.
A session is a connection, so you would need to close the connection for mysql to remove the table. Or alternatively, as you mentioned, to drop the table if it exists at the start of the script if the connection is reused.
Augusto has already answered your question about the lifespan of a temporary table, so this addresses the other issues with your current approach.
You should steer clear of the very old comma separated tables list in favour of the more explicit join syntax.
As already pointed out by Shadow in the comments, you appear to be overcomplicating things. Furthermore, unless I am completing misunderstanding what is going on, your count queries are incorrect.
For each user, your are counting all users if current
userId
is in the subquery result. Let’s take your first count query as an example:The outer query is assigning the count of all users to the variable
activeTasksCount
ifuserId
(current loop iterationuserId
var) has at least 1 active task. Surely, you want the count of active tasks assigned touserId
?As Shadow pointed out, your separate count queries can be combined using conditional aggregation, something like:
Here’s a db<>fiddle.