MySQL stored procedure troubles - mysql

Basically i'm going to run this procedure anytime a student enrolls/drops a course.
I'm trying to set student_total = # of students in a course, then update that corresponding section with (student_total + 1) i'm having trouble finding good documentation for stored procedures. I'm getting an error on my Declare student_total int; line. What am i not doing correct?
DELIMITER $$
CREATE PROCEDURE `mydb`.`update_seats` (IN section_ID varchar(20))
BEGIN
SET #section_id=section_id;
DECLARE student_total int;
-- count the number of students in the course --
SET student_total = SELECT count(student_ID) from course
WHERE section_ID = #section_id;
Update Section SET students_enrolled = (student_total + 1)
WHERE section_ID = #section_id;
END

Problems
Error 1
From MySql documentation:
DECLARE is permitted only inside a BEGIN ... END compound statement and must be at its start, before any other statements.
So, you should move DECLARE... statement before the SET #section_id... statement.
Error 2
You are trying to select a value into a variable using invalid snytax! You should use SELECT ... INTO instead of SET ... = SELECT ... (which is invalid syntax).
Removing Redundancy
No need to assign parameter (section_ID) to a global variable (#section_ID). You can simply change the parameter name to avoid name collision with section.section_ID column.
Solution
DELIMITER ;;
CREATE PROCEDURE `update_seats` (IN p_section_ID VARCHAR(20))
BEGIN
DECLARE student_total INT;
SELECT count(student_ID)
INTO student_total
FROM course
WHERE section_ID = p_section_ID;
UPDATE section
SET students_enrolled = (student_total + 1)
WHERE section_ID = p_section_ID;
END;;
DELIMITER ;

You're using the command line tool, yes?
It would be helpful to know the error message you received but based off the code you posted I don't see where you reset the delimiter command after the BEGIN...END block.
Taken from http://dev.mysql.com/doc/refman/5.1/en/stored-programs-defining.html

Related

Why won't MYSQL procedure properly iterate new ROWS in TABLE using WHILE statement?

I am creating this basic procedure using MySQL Workbench to accept a single input parameter.
The table "unique_days" has a single PRIMARY KEY column called "dayid" which currently has a single ROW with a value of 1.
DROP PROCEDURE IF EXISTS dayid_iteration;
DELIMITER $$
CREATE PROCEDURE dayid_iteration(maxdate_final INT)
BEGIN
DECLARE maxdate_current INT;
SET #maxdate_current = (SELECT (MAX(dayid) + 1) FROM unique_days);
DELETE FROM unique_days WHERE dayid > 1;
WHILE (maxdate_current > maxdate_final) DO
INSERT INTO unique_days (dayid) VALUES (maxdate_current);
SET maxdate_current = (maxdate_current+1);
END WHILE;
END$$
DELIMITER ;
The procedure is then called with an integer parameter.
CALL dayid_iteration(11);
The variables are setting properly because I can run a select statement with the variable and it shows the correct new value. The deletion of dayid > 1 also works (Tested by manually adding additional rows, and then running procedure). However, I can't seem to get the WHILE statement to insert new rows with the value provided.
Any help is much appreciated. I searched multiple other questions, and countless forums, but everything looks like it should be working.
I am expecting the code to CREATE 9 ROWS for a total of 10 ROWS.
The following is included just so you can see the starting values of the table.
SELECT * FROM unique_days;
For anyone who finds this question, the following code functions correctly. The input variable on the parameter was not setting properly. Once the parameter had "IN" placed in front of the variable name, it correctly received the parameter.
CREATE PROCEDURE dayid_iteration(IN maxdate_final INT)
DROP PROCEDURE IF EXISTS dayid_iteration;
DELIMITER $$
CREATE PROCEDURE dayid_iteration(IN maxdate_final INT)
BEGIN
DECLARE maxdate_current INT;
SET maxdate_current = (SELECT (MAX(dayid) + 1) FROM unique_days);
WHILE (maxdate_current <= maxdate_final) DO
INSERT INTO unique_days (dayid) VALUES (maxdate_current);
SET maxdate_current = (maxdate_current+1);
END WHILE;
END$$
DELIMITER ;
CALL dayid_iteration(1000);
This call procedure now properly works.
CALL dayid_iteration(1000);

Use cursor within stored procedure [duplicate]

This question already has answers here:
syntax error for mysql declaration of variable
(2 answers)
Closed 4 years ago.
I'm trying to make a stored procedure that include a cursor inside it and fill one of my tables based on another table's data , every day .
I think I'm doing something wrong with syntax , I already wrote a simple Stored procedure with cursor and it worked totally right , but when it get a little more complicated it does not work any more .
I'm getting
Error Code: 1064. You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use
near 'DECLARE brandId int ;' at line 1.
Please note that I'm using Mysql 5.7 and I'm creating this at phpmMyAdmin .
CREATE PROCEDURE ّFillCommentGrowth()
BEGIN
DECLARE brandId int;
DECLARE todayComment int ;
DECLARE brandCount int ;
DECLARE yesterdayComment int;
DECLARE crs CURSOR for SELECT id from brands;
SET brandCount = (SELECT count(*) from brands);
open crs;
WHILE brandCount > 0 DO
FETCH crs into brandId ;
set todayComment = (select IFNULL((select count(*) from comments as c where date(c.created_at) = date(subdate(NOW(),1)) and c.brand_id = brandId ),0));
set yesterdayComment = (select IFNULL((select commentAmount from commentsGrowth where moment = date(subdate(NOW(),2)) and brand_Ref= brandId),0));
INSERT INTO commentsGrowth
(
brand_Ref,
commentAmount,
diffrenceByYesterday,
degree,
AmountPercent,
moment)
VALUES
(brandId ,
todayComment,
(todayComment - yesterdayComment ) ,
(((ATAN(todayComment - yesterdayComment )*180))/PI()),
(degree*(1.1)),
date(subdate(NOW(),1)));
SET brandCount = brandCount - 1;
END WHILE;
close crs;
END
The error you are getting has nothing to do with cursor. You need to change the DELIMITER from standard semicolon (;). For example
DELIMITER //
CREATE PROCEDURE GetAllProducts()
BEGIN
SELECT * FROM products;
END //
DELIMITER ;
The DELIMITER statement changes the standard delimiter which is semicolon ( ; ) to another. In this case, the delimiter is changed from the semicolon( ; ) to double-slashes //. Why do we have to change the delimiter? Because we want to pass the stored procedure to the server as a whole rather than letting mysql tool interpret each statement at a time. Following the END keyword, we use the delimiter // to indicate the end of the stored procedure. The last command ( DELIMITER; ) changes the delimiter back to the semicolon (;).

Unable to create a cursor in a stored procedure from mysql

I want to create a Cursor in a stored procedure from mysql. The question is, it's giving a error when the Cursor is created after the variable initialization. Is there any solution for it.
DELIMITER //
Create procedure sp_JB_Securities_Second_row_Insert()
BEGIN
DECLARE Rw_Count int;
set Rw_Count = (select count(*) from JB_Security_Detials):
DECLARE cur1 CURSOR FOR select title from JB_Security_Detials limit 27, Rw_Count;
END //
DELIMITER ;
It has been pointed out by others (P.Salmon) that the order for DECLARING variables and the CURSOR is significant and it is very specific.
e.g.
Variable declarations must appear before cursor or handler
declarations.
and
Cursor declarations must appear before handler declarations and after
variable and condition declarations.
However, switching the order around is not going to help you here because you are looking to use RW_Count in your LIMIT clause and setting the variable before the CURSOR declaration is causing the error. This restriction also means that the only way you could use a variable in the LIMIT clause is if you pass it in as a parameter to the procedure (which you probably don't want to do).
Fortunately, none of that necessary as you don't really need to know the number of rows in the table to use OFFSET with LIMIT.
There's a nice example in the documentation for the SELECT statement
To retrieve all rows from a certain offset up to the end of the result
set, you can use some large number for the second parameter. This
statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
So, the solution here is to just remove the RW_Count variable completely and add a very BIG number instead.
try this
Create procedure sp_JB_Securities_Second_row_Insert()
BEGIN
DECLARE cur1 CURSOR FOR select title from JB_Security_Detials limit
27,(select count(*) from JB_Security_Detials);
END //
DELIMITER ;
Try this
DELIMITER //
DROP PROCEDURE IF EXISTS sp_JB_Securities_Second_row_Insert()
CREATE PROCEDURE sp_JB_Securities_Second_row_Insert()
BEGIN
DECLARE Rw_Count INT;
DECLARE exit_loop BOOLEAN;
SET Rw_Count = (SELECT COUNT(*) FROM JB_Security_Detials);
DECLARE Rw_Count_cursor CURSOR FOR
"Your Query .............. "
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN Rw_Count_cursor;
-- start looping
out_loop: LOOP
-- read the name from next row into the variables
FETCH Rw_Count_cursor INTO col1,cl2, ...;
"Your Query .............. "
IF exit_loop THEN
CLOSE Rw_Count_cursor;
LEAVE out_loop;
END IF;
END LOOP out_loop;
END//
DELIMITER ;

Dynamic add column with loop

I'd like to create a dynamic procedure wich will generate the columns for me automatically but somethings wrong. I have to do this a few times in my program and I don't really want to do it manually.
So thats the code that I used before
DELIMITER $$
DROP PROCEDURE IF EXISTS RepeatLoopProc$$
CREATE PROCEDURE RepeatLoopProc()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);
Declare #sql nvarchar(4000);
SET x = 0;
REPEAT
SET str = '';
SET str = CONCAT(str,'ossz_levon_het_',x);
SET x = x + 1;
set #sql='ALTER TABLE telephelyi_teszt ADD '+ str +'DOUBLE NULL';
execute #sql;
UNTIL x > 50
END REPEAT;
END$$
DELIMITER ;
I've got a syntax error near the Declare #sql nvarchar(4000); line any ideas?
When you use DECLARE to create local variables in a stored procedure, don't use the # prefix. Those are for session variables.
But you shouldn't DECLARE the variable anyway. Prepared statements don't work with local variables, only session variables. You don't have to declare session variables.
Your ALTER TABLE statement has an error. You didn't put a space after the column name and before DOUBLE. In other words, the statement will be like the following, which will cause a syntax error wen you execute it.
ALTER TABLE telephelyi_teszt ADD ossz_levon_het_1DOUBLE NULL
You didn't PREPARE the statement. You can't just EXECUTE a string as a statement. See examples in the manual on prepared statements.
It's probably bad design to create 50 columns in any table with identical content. Consider creating a second table, with one column ossz_levon_het and a reference back to your parent table telephelyi_teszt. This is the recommendation of First Normal Form to avoid repeating groups of columns.

MySQL Procedure random number generating

I'm writing my first MySQL procedure. I try to generate a random number and update a value in a table with this number, but only if it doesn't exists already (due to unique constraint). My procedure looks like this:
create procedure generaterc()
begin
declare _rc char;
declare _id int;
set _id = 1;
while _id < ((select count(*) from patient) - 1) do
begin
set _rc = cast(FLOOR(1000000000 + (RAND() * 8999999999)) AS char);
select _rc;
if not exists(select * from patient where patient.rc = _rc) then
update patient set rc=_rc where id=_id;
set _id=_id+1;
end if;
end;
end while;
end
I got this error when executing the procedure: Data truncation: Data too long for column '_rc' at row 8. My rc column is varchar(255), but I guess this isn't the core of the problem. Any suggestions?
Thank you very much.
Instead of
declare _rc char;
try:
declare _rc varchar(255);
Currently _rc can only hold a single character, which is not enough to store your number.
However, for your use case you may like to take a look at the uuid_short() function. It generates a large random number that is guaranteed to be unique (subject to some rules). This way you can replace your procedure with the single statement:
update patient set rc = uuid_short();