Having trouble with this stored procedure. Been at it for at least 4 hours, and still, no luck.
It creates the procedure no problem, but, when trying to call it, it throws a syntax error with no clues where to find the mistake. (Syntax error near '').
I'm using MySQL 5.6.39, and as client, HeidiSQL 9.5.0.5196
Edit: The purpose of this procedure, is to calculate the average time from another table, ignoring the outliers, that's why I used so many temp tables.
Thanks again!
Here's the code
DROP PROCEDURE IF EXISTS tiempoPromedioUsuarioP;
DELIMITER //
CREATE PROCEDURE tiempoPromedioUsuarioP (IN current_user_id INT, IN outliers FLOAT(4,3), OUT promedio_segundos INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
SET #s1 = CONCAT('CREATE TEMPORARY TABLE tp',current_user_id, ' (SELECT TIMESTAMPDIFF(SECOND, sesion_log.init_date, sesion_log.end_date) AS tiempoPromedio FROM sesion_log WHERE sesion_log.id_usuario = ', current_user_id, ' AND sesion_log.is_end = 1;');
PREPARE stmt1 FROM #s1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #s2 = CONCAT('CREATE TEMPORARY TABLE boundsA',current_user_id,' (SELECT (AVG(tp',current_user_id,'.tiempoPromedio) - STD(tp',current_user_id,'.tiempoPromedio)*',outliers,') AS lb FROM tp',current_user_id,');');
PREPARE stmt2 FROM #s2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
SET #s3 = CONCAT('CREATE TEMPORARY TABLE boundsB',current_user_id,' (SELECT (AVG(tp',current_user_id,'.tiempoPromedio) + STD(tp',current_user_id,'.tiempoPromedio)*',outliers,') AS ub FROM tp',current_user_id,');');
PREPARE stmt3 FROM #s3;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
SET #s4 = CONCAT('CREATE TEMPORARY TABLE res',current_user_id,' SELECT round(AVG(tp',current_user_id,'.tiempoPromedio)) as promedio FROM tp WHERE tp',current_user_id,'.tiempoPromedio BETWEEN (SELECT lb FROM boundsA',current_user_id,') AND (SELECT ub FROM boundsB',current_user_id,');');
PREPARE stmt4 FROM #s4;
EXECUTE stmt4;
DEALLOCATE PREPARE stmt4;
SET #s5 = CONCAT('
DECLARE promedioc CURSOR FOR SELECT * FROM res',current_user_id,';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN promedioc;
read_loop: LOOP
FETCH promedioc INTO promedio_segundos;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE promedioc;
');
PREPARE stmt5 FROM #s5;
EXECUTE stmt5;
DEALLOCATE PREPARE stmt5;
SET #s6 = CONCAT('DROP TEMPORARY TABLE tp',current_user_id);
PREPARE stmt6 FROM #s6;
EXECUTE stmt6;
DEALLOCATE PREPARE stmt6;
SET #s7 = CONCAT('DROP TEMPORARY TABLE boundsA',current_user_id);
PREPARE stmt7 FROM #s7;
EXECUTE stmt7;
DEALLOCATE PREPARE stmt7;
SET #s8 = CONCAT('DROP TEMPORARY TABLE boundsB',current_user_id);
PREPARE stmt8 FROM #s8;
EXECUTE stmt8;
DEALLOCATE PREPARE stmt8;
SET #s9 = CONCAT('DROP TEMPORARY TABLE res',current_user_id);
PREPARE stmt9 FROM #s9;
EXECUTE stmt9;
DEALLOCATE PREPARE stmt9;
END//
DELIMITER ;
Thanks for your help!
Related
How can I write this:
IF DB_ID('DB_NAME') IS NOT NULL DROP DATABASE MORPG1;
GO
CREATE DATABASE DB_NAME;
GO
USE DB_NAME
GO
All operations except USE can be performed with
CREATE PROCEDURE recreate_datebase (dbname VARCHAR(64))
BEGIN
IF EXISTS ( SELECT NULL
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = dbname ) THEN
SET #sql := CONCAT('DROP DATABASE ', dbname);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END IF;
SET #sql := CONCAT('CREATE DATABASE ', dbname);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
Making the database current one cannot be parametrized / executed dynamically.
In the procedure I'm writing I need to store the result of a dynamic SQL query into a local variable. Something like this:
DELIMITER //
CREATE PROCEDURE test_maxsum(uid varchar(25))
BEGIN
DECLARE maxsum int;
SET #SQL = CONCAT('SELECT MAX(sum_val) FROM ', uid);
PREPARE stmt FROM #SQL;
EXECUTE stmt INTO maxsum;
DEALLOCATE PREPARE stmt;
SELECT maxsum;
END//
DELIMITER ;
Local variables cannot be assigned in prepared statements. You can use user-defined variables though:
DELIMITER //
CREATE PROCEDURE test_maxsum(uid varchar(25))
BEGIN
SET #SQL = CONCAT('SELECT MAX(sum_val) INTO #maxsum FROM ', uid);
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT #maxsum;
END//
DELIMITER ;
i am trying to write a stored procedure which updates the field of a table as specified in the argument .i am getting syntax error in #sql statment.please help
create procedure new_upd1(ind int(3),attribute varchar(30),pk int(11),new_value varchar(30))
begin
set #att=attribute;
set #primk=pk;
set #updated=new_value;
if ind=1 then
set #sql='update department set ?=? where departmentid=?';
prepare stmt from #sql;
execute stmt using #att,#updated,#primk;
deallocate prepare stmt;
end if;
end
Parameters don't work for column or table names, only for values. Do it like this:
create procedure new_upd1(ind int(3),attribute varchar(30),pk int(11),new_value varchar(30))
begin
set #att=attribute;
set #primk=pk;
set #updated=new_value;
if ind=1 then
set #sql=CONCAT('update department set ', #att, '=? where departmentid=?;');
prepare stmt from #sql;
execute stmt using #updated,#primk;
deallocate prepare stmt;
end if;
end
1)Below is the code I'm trying for a procedure where I need to compare the count from two different tables. (tbl1 and tbl2 are in parameters to be passed).
But in the above code the values for 'a' and 'b' are set as statements. I need the resultant value(count) from the two statements to compare in the 'IF' condition.
declare a integer;
declare b integer;
set #a:=concat('select count(*) from ', tbl1);
/*PREPARE stmt1 FROM #a;
execute stmt1;
deallocate PREPARE stmt1;*/
set #b:= concat('select count(*) from ', tbl2);
/*PREPARE stmt2 FROM #b;
execute stmt2;
deallocate PREPARE stmt2;*/
if
#a=#b
then
select 1;
else
select 2;
end if;
2) Actually where I am facing a problem to set 'tbl1' and 'tbl2' as parameters in procedure.
The below code works fine if the table names are given directly, but i need them as parameters.
CREATE PROCEDURE myproc (in tbl1 varchar(50), in tbl2 varchar(50))
declare a integer;
declare b integer;
set #a:=(select count(*) from tbl1);
/*PREPARE stmt1 FROM #a;
execute stmt1;
deallocate PREPARE stmt1;*/
set #b:= (select count(*) from tbl2);
/*PREPARE stmt2 FROM #b;
execute stmt2;
deallocate PREPARE stmt2;*/
if
#a=#b
then
select 1;
else
select 2;
end if;
Hope anyone out there can help me with the solution.
As mentioned in the comments above, it is likely that you shouldn't be doing this at all... but, for what it's worth:
SET #sql := CONCAT('SELECT (
SELECT COUNT(*) FROM `',REPLACE('`','``',tbl1),'`
) = (
SELECT COUNT(*) FROM `',REPLACE('`','``',tbl2),'`
);');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql := NULL;
REPLACE() has been used to try and avoid SQL injection (it's somewhat crude, but it's the best one can do without further information).
My current code is :
DELIMITER \\
CREATE PROCEDURE sample (IN _car VARCHAR(15))
BEGIN
DECLARE _a INTEGER;
SET #s = CONCAT('SELECT COUNT(*) FROM train WHERE ', _car, '<=0;');
PREPARE stmt1 FROM #s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END\\
But I wanted to capture the answer of the SELECT statement to my _a variable.
I tried changing my code to
SET #s = CONCAT('SELECT COUNT(*) INTO', _a,' FROM train WHERE ', _car, '<=0;');
But that didn't work.
Help, please?
SOLVED!
DELIMITER \\
CREATE PROCEDURE sample (IN _car VARCHAR(15))
BEGIN
DECLARE _a INTEGER;
SET #var = NULL;
SET #s = CONCAT('SELECT COUNT(*) INTO #var FROM train WHERE ', _car, '<=0;');
PREPARE stmt1 FROM #s;
EXECUTE stmt1;
SELECT #var;
DEALLOCATE PREPARE stmt1;
END\\
:D
As stated here you need to include the variable assignment in the original statement declaration. So you statement would be something like:
SELECT COUNT(*) FROM train WHERE ?<=0 INTO _a
Then you you would execute it with:
EXECUTE stmt1 using _car;
And get the result with:
select _a;
Let me know if it works.