MySQL Procedure unable to perform as expected - mysql

CREATE PROCEDURE `userCredentialsWeight`(IN data1 varchar(50), IN data2 varchar(250))
BEGIN
/* all declaration */
IF (SELECT field1 FROM user_credentials WHERE field1 = data1 LIMIT 1 )
THEN
SET DATA_WEIGHT = 75;
ELSE
SET DATA_WEIGHT = 100;
END IF;
/* More calculations here */ ---> this block contains all the calculation,
actually i am new to procedure, i have done this using
direct query from application but it requires 4 database requests
which I want to minimize here
END
Now my issue is the condition after WHERE is not getting a value of data1.
Platform - Mysql (i am using MYSQL Workbench)

Test
SELECT CASE WHEN COUNT(*) = 0
THEN 100
ELSE 75
END
INTO data_weight
FROM user_credentials
WHERE field1 = data1;

Related

MySql stored procedure rows issue

I have this stored procedure:
CREATE DEFINER=`admin`#`%` PROCEDURE `GetTickets4Card`(
IN p_TicketID int,
OUT p_returnvalue int
)
BEGIN
SELECT idbookingstickets
INTO #p_returnvalue
FROM bookingstickets
WHERE TicketId = p_TicketID;
/* Return value accordingly */
IF mysqll_affected_rows = 0 THEN SET p_returnvalue = 0;
/*
ELSE
SELECT * FROM BookingsTicketsCollected WHERE p_returnalue = idtickets;
if mysqll_affected_rows = 0 THEN SET p_returnvalue = -1;
END IF;
*/
END IF;
END
It gives me the following error: "Result consisted of more than one row". It may have something to do with mysql_affected_rows , but I have no idea, I want to know if the sql statement returns 1 row or not, any ideas?
Call code:
set #p_returnvalue = 0;
call yourTICKETbox_LIVE_DB.GetTickets4Card("aabb188e-6adc-11e5-9770-061de6653ea3", #p_returnvalue);
select #p_returnvalue;
When you use SELECT ... INTO variable, the query must return at most one row. If you only care whether there are any matching rows, you can use the EXISTS() function.
SET p_returnvalue = EXISTS(
SELECT 1
FROM bookingstickets
WHERE TicketId = p_TicketID);
BTW, the MySQL equivalent to the PHP function mysqli_affected_rows() is ROW_COUNT().

Updating a column name of a same table which has a parent child relationship using mysql

I searched a lot of doing a task but found no appropriate solution.
Basically the scenario is. I have a user_comment table in which there are 5 column(id,parent_id,user_comments,is_deleted,modified_datetime). There is a parent child relationship like 1->2,1->3,2->4,2->5,5->7 etc. Now i am sending the id from the front end and i want to update the column is_deleted to 1 and modified_datetime on all the records on
this id as well as the all the children and children's of children.
I am trying to doing this by using a recursive procedure. Below is the code of my procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `user_comments`(
IN mode varchar(45),
IN comment_id int,
)
BEGIN
DECLARE p_id INT DEFAULT NULL ;
if(mode = 'delete')
then
update user_comment set is_deleted = 1, modified_datetime = now()
where id = comment_id ;
select id from user_comment where parent_id = comment_id into p_id ;
if p_id is not null
then
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call user_comments('delete', p_id);
end if;
end if;
END
By using this procedure it give me an error of more than one row.
If i return the select query without giving it to variable then shows me the the appropriate results on the select query but i have to call this procedure recursively based on getting the ids of the select query.
I need help i have already passed 2 days into this.
I used cursor also. Below is the code of cursor
CREATE DEFINER=`root`#`localhost` PROCEDURE `user_comments`(
IN mode varchar(45),
IN comment_id int,
)
BEGIN
DECLARE p_emp int;
DECLARE noMoreRow INT;
DECLARE cur_emp CURSOR FOR select id from user_comment where parent_id = comment_id ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET noMoreRow = 0;
if(mode = 'delete')
then
OPEN cur_emp;
LOOPROWS: LOOP
IF noMoreRow = 0 THEN
update user_comment set is_deleted = 1, modified_datetime = now() where id = comment_id
CLOSE cur_emp;
LEAVE LOOPROWS;
END IF;
FETCH cur_emp INTO p_emp;
update user_comment set is_deleted = 1, modified_datetime = now() where id = p_emp ;
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call user_comments('delete', p_emp);
END LOOP;
end if;
END
After using cursor i am getting a thread error.i don't know how can overcome this problem!!!
Mysql's documentation on select ... into varlist clearly says:
The selected values are assigned to the variables. The number of
variables must match the number of columns. The query should return a
single row. If the query returns no rows, a warning with error code
1329 occurs (No data), and the variable values remain unchanged. If
the query returns multiple rows, error 1172 occurs (Result consisted
of more than one row). If it is possible that the statement may
retrieve multiple rows, you can use LIMIT 1 to limit the result set to
a single row.
Since you wrote in the OP that a comment can be parent of many comments, using simple variables cannot be a solution. You should use a CURSOR instead, that can store an entire resultset.
You loop through the records within the cursos as shown in the sample code in the above link and call user_comments() in a recursive way.
UPDATE
If your receive
Error Code: 1436. Thread stack overrun
error, then you can do 2 things:
Increase the thread_stack setting in the config file and restart mysql server.
You can try to simplify your code to use less recursions and therefore less stack space. For example, when you fetch all children into the cursor, then rather calling the user_comments() recursively for each, you can set all direct children's status within the code and call the function recirsively on grand-childrens only (if any). You can also change your data structure and use nested set model to approach hierarchical structures.
Nested set model is more complex to understand, it is less resource intensive to traverse, but more resource intensive to maintain.

MySQL procedure gone wrong

I have a MySQL database in which I have the following rows (by exemple) created by default (id, task and case may be different but the current value is always 1)
....idtaskcaseuser............datecurrent
238......31001.....0..............null..........1
239......41001.....0..............null..........1
I have to randomly create rows like this with insert statement (new rows). As you can see a date is filled and de current equal 0
....idtaskcaseuser............datecurrent
240......51001.....12015.04.03..........0
241......21002.....12015.04.03..........0
When I come across one of the lines created by default I want to use an update instead of an insert statement.
So I created the following procedure in MySQL
DELIMITER //
DROP PROCEDURE IF EXISTS FillProgress//
CREATE PROCEDURE FillProgress ( get_case INT(10),get_task INT(10), get_user INT(10) )
BEGIN
DECLARE test tinyint(1);
SET test = (SELECT COUNT(*) FROM progress WHERE case_id = get_case AND task_id = get_task);
IF test = 1 THEN
UPDATE progress SET current = 0, date = NOW(), user_id = get_user WHERE task_id = get_id AND case_id = get_case;
ELSE
INSERT INTO progress(task_id,case_id,user_id,date,current) VALUES (get_task,get_case,get_user,NOW(),0);
END IF;
END; //
DELIMITER ;
I use count to see if a already have a row with the same case and task. If it's true (test=1) I use UPDATE, otherwise and use INSERT.
If I test with the following row already wrote in the database
....idtaskcaseuserdatecurrent
241......41001.....0..null..........1
I use CALL FillProgress(1001,4,1);
The row is not updated, but I do not have any error message.
11:38:02 CALL FillProgress(1001,4,1) 0 row(s) affected 0.000 sec
And if I manually use my update query
UPDATE progress SET current = 0, date = NOW(), user_id = 1 WHERE task_id = 4 AND case_id = 1001;
It works like a charm.
The insert query also works fine.
The UPDATE query within the procedure has a "WHERE task_id = get_id" clause, however I don't see get_id being defined in the procedure; there is a "get_task" parameter for the stored procedure, though.

stored procedure syntax in mysql

I am new to writing stored Procedures and I can't seem to find the error in this procedure.
The error is marked near the where part.
I tried looking for an example where the set is done based on a if condition but I can't seem to find such an example. Can anyone point me to my error?
DELIMITER $$
CREATE PROCEDURE `incubation`.`bt_voice_modification`
(in input_slot varchar(45),in input_port varchar(45))
BEGIN
SET #SVLAN_STH:=1000;
SET #SVLAN_DTH:=999;
SET #CVLAN_DTH:=1000;
SET #FLOW_INSTANCE:=1;
UPDATE one_2_one_table
SET L2S_USER_FLOW_INSTANCE = #FLOW_INSTANCE := #FLOW_INSTANCE+1;
SET L2S_NW_SLOT = input_slot;
SET L2S_NW_PORT = input_port;
IF STH_DTH = 'STH' then
set L2S_NW_SVLAN = #SVLAN_STH :=#SVLAN_STH + 1;
ELSE
set L2S_NW_SVLAN = #SVLAN_DTH ;
set L2S_NW_CVLAN = #CVLAN_DTH :=#CVLAN_DTH + 1;
END if;
WHERE IPDSLAM_USER_SLOT = 2 AND L2S_USER_TYPE like "%gplt%";
END
Your code suggest you don't have a very clear picture of how UPDATE statement works or the exact syntax. When you put a ;, it marks the end of the (UPDATE) statement. The syntax is - for one table:
UPDATE tableX
SET columnA = what_value_should_columnA-get ,
columnB = what_value_should_columnB_get ,
...
columnX = what_value_should_columnX_get
WHERE (conditions that restrict the rows that will be affected)
ORDER BY SomeColumn ; --- this can be used in MySQL only. Standard SQL
--- (and most DBMS) do not allow ORDER BY clause in
--- UPDATE statements. Since you are using variables
--- and the order of updating affects the updated values,
--- it's essential that you include an ordering.
So, your UPDATE would be something like:
UPDATE one_2_one_table
SET L2S_USER_FLOW_INSTANCE = #FLOW_INSTANCE := #FLOW_INSTANCE+1 ,
L2S_NW_SLOT = input_slot,
L2S_NW_PORT = input_port,
L2S_NW_SVLAN = CASE WHEN STH_DTH = 'STH'
THEN #SVLAN_STH := #SVLAN_STH + 1
ELSE #SVLAN_DTH
END ,
L2S_NW_CVLAN = CASE WHEN STH_DTH = 'STH'
THEN L2S_NW_CVLAN
ELSE #CVLAN_DTH := #CVLAN_DTH + 1
END
WHERE IPDSLAM_USER_SLOT = 2
AND L2S_USER_TYPE like '%gplt%'
ORDER BY SomeColumn ;

Finding min and max value of the table in a constant time

I have a table which contains relative large data,
so that it takes too long for the statements below:
SELECT MIN(column) FROM table WHERE ...
SELECT MAX(column) FROM table WHERE ...
I tried index the column, but the performance still does not suffice my need.
I also thought of caching min and max value in another table by using trigger or event.
But my MySQL version is 5.0.51a which requires SUPER privilege for trigger and does not support event.
It is IMPOSSIBLE for me to have SUPER privilege or to upgrade MySQL.
(If possible, then no need to ask!)
How to solve this problem just inside MySQL?
That is, without the help of OS.
If your column is indexed, you should find min(column) near instantly, because that is the first value MySQL will find.
Same goes for max(column) on an indexed column.
If you cannot add an index for some reason the following triggers will cache the MIN and MAX value in a separate table.
Note that TRUE = 1 and FALSE = 0.
DELIMITER $$
CREATE TRIGGER ai_table1_each AFTER INSERT ON table1 FOR EACH ROW
BEGIN
UPDATE db_info i
SET i.minimum = LEAST(i.minimum, NEW.col)
,i.maximum = GREATEST(i.maximum, NEW.col)
,i.min_count = (i.min_count * (new.col < i.minumum))
+ (i.minimum = new.col) + (i.minimum < new.col)
,i.max_count = (i.max_count * (new.col > i.maximum))
+ (i.maximum = new.col) + (new.col > i.maximum)
WHERE i.tablename = 'table1';
END $$
CREATE TRIGGER ad_table1_each AFTER DELETE ON table1 FOR EACH ROW
BEGIN
DECLARE new_min_count INTEGER;
DECLARE new_max_count INTEGER;
UPDATE db_info i
SET i.min_count = i.min_count - (i.minimum = old.col)
,i.max_count = i.max_count - (i.maximum = old.col)
WHERE i.tablename = 'table1';
SELECT i.min_count INTO new_min_count, i.max_count INTO new_max_count
FROM db_info i
WHERE i.tablename = 'table1';
IF new_max_count = 0 THEN
UPDATE db_info i
CROSS JOIN (SELECT MAX(col) as new_max FROM table1) m
SET i.max_count = 1
,i.maximum = m.new_max;
END IF;
IF new_min_count = 0 THEN
UPDATE db_info i
CROSS JOIN (SELECT MIN(col) as new_min FROM table1) m
SET i.min_count = 1
,i.minimum = m.new_min;
END IF;
END $$
DELIMITER ;
The after update trigger will be some mix of the insert and delete triggers.