select statement intermittently returns null - mysql

So I have the following code in a stored procedure:
set #Id = (select id from foo where Name = 'bar');
IF #Id is null THEN
#add missing record
END IF;
However, its seems that the database will only return a value intermittently. Even when I know my select statement will return a record (copied and pasted directly out of my stored proc). Has anyone else had this issue with MySQL?
about the only crazy thing my proc is doing:
DECLARE CONTINUE HANDLER FOR 1062, 1452
but neither of those should effect my query (I am sure there is one and only one record)
Thanks

You can use a stored procedure like the following:
CREATE PROCEDURE example_proc (pName VARCHAR(10))
BEGIN
IF NOT EXISTS(SELECT 1 FROM foo WHERE Name = pName) THEN
INSERT INTO foo (Name) VALUES (pName);
END IF;
END
demo on dbfiddle.uk

SO i don't know why this fixed the problem, but it did.
By setting the variable to null first before the assignment seems to have fixed the problem. I was have the problem intermittently, so maybe I'm just lucking out longer than I did last time.

Related

Problem with comparison within a trigger statement using a variable gotten from query

I am trying to use an attribute from a 2nd table in the trigger of the 1st. To do this I am trying to load that value into a variable and then use it as a comparison.
However whenever I try and test the process the comparison answers false.
DELIMITER $$
create trigger evolve_persona before update on phantom_thieves
for each row begin
set #t := (select tier from persona where pname = old.persona);
if((new.persona != old.persona) and (select cast(#t as unsigned) = '1')) then
set
new.st = old.st+10, new.ma = old.ma+10, new.en= old.en+10, new.ag= old.ag+10,
new.lu= old.lu+20;
end if;
end$$
DELIMITER ;
I can see nothing wrong with your trigger but, this is somewhat more complicated as be written in a comment.
Make please following
SET #t = -1;
SELECT #t; -- returns -1
update phantom_thieves SET .....
SELECT #t; -should display at sometime 1
This seems to be the only problem that tier don't has the response 1 and with above, you can see what you get.

Want to generate unique Id's using a function in mysql

I wrote a function to generate unique id's,its working but sometimes two people are getting same id,I mean duplicates are formed. My unique id looks like
2016-17NLR250001, I deal with only last four digits 0001. I am posting my function please correct it and please help me in avoiding duplicates even though users login into same account or if they do it on same time.
MY FUNCTION:
DELIMITER $$
USE `olmsap`$$
DROP FUNCTION IF EXISTS `fun_generate_uniqueid`$$
CREATE DEFINER=`root`#`%` FUNCTION `fun_generate_uniqueid`( V_DATE DATE,V_MANDALID INT ) RETURNS VARCHAR(30) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE MDLCODE VARCHAR(5);
SET MDLCODE = ' ';
SELECT COUNT(*) INTO #CNT FROM `st_com_mandal` WHERE MANDAL_VS_MC=V_MANDALID;
SELECT dist_mandal_code INTO MDLCODE FROM `st_com_mandal` WHERE MANDAL_VS_MC=V_MANDALID;
IF #CNT>0 THEN
SET #YR=`FUN_FISCAL_YR`(V_DATE);
SELECT CONCAT(IF(DIST_SAN_CODE='GUN','GNT',DIST_SAN_CODE),IFNULL(`dist_mandal_code`,'NULL'))INTO #MANDAL
FROM `st_com_dist` SCD INNER JOIN `st_com_mandal` STM ON STM.`mandal_dist_id`= SCD.`DIST_VC_DC` WHERE MANDAL_VS_MC=V_MANDALID;
IF MDLCODE >0 THEN
SELECT COUNT(Soil_Sample_ID)+1 INTO #ID FROM `tt_mao_soil_sample_dtls` WHERE MANDAL_ID=V_MANDALID AND SUBSTR(UNIQUE_ID,1,7)=#YR ;
ELSE
SELECT COUNT(Soil_Sample_ID)+1 INTO #ID FROM `tt_mao_soil_sample_dtls` WHERE SUBSTR(UNIQUE_ID,1,14)=CONCAT(#YR,#MANDAL) ;
END IF ;
IF LENGTH(#ID)=1 THEN
SET #ID=CONCAT('000',#ID);
ELSEIF LENGTH(#ID)=2 THEN
SET #ID=CONCAT('00',#ID);
ELSEIF LENGTH(#ID)=3 THEN
SET #ID=CONCAT('0',#ID);
ELSE
SET #ID=#ID;
END IF ;
RETURN CONCAT(#YR,#MANDAL,#ID);
ELSE
RETURN 'Mandal Doesnt Exists';
END IF;
END$$
DELIMITER ;
I do not think community will be able to help you with this question. This is a complex function that requires very careful analysis of table / index access and locking.
The only thing I can recommend is to not use existing table data to calculate next sequence as this is a bad practice.
Besides Race conditions that you are experiencing you will also get problems if the record with the last sequence is deleted.
I suggest you read this to get an idea on how to write a custom sequence generator:
http://en.latindevelopers.com/ivancp/2012/custom-auto-increment-values/

Weird issue with a stored procedure in MySQL

I need to add a new stored procedure on our company's MySQL server. Since it's just slightly different, I used an already existing one, added the additional field and changed the name of the procedure. The weird thing now is that when I want to execute the statement, it returns:
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 '' at line 3
reffering to the 0 in this line: SET #update_id := 0; What makes it weird is, that I queried that stored procedure by using SHOW CREATE PROCEDURE . It's saved in our database and is working fine. I just can't use it as a new stored procedure (no matter if I try to apply it to the new test database or if I use it on the existing database by giving it a new name).
I searched the internet for a solution. Unfortunately to no avail. I even set up a new database with a new table and some demo values where I tried to execute the original, unaltered stored procedure. It returns the exact same error.
Here's the currently used and working stored procedure I'm talking about:
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
SET #update_id := 0;
UPDATE customer_shop SET state = 1, id = (SELECT #update_id := id), instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment WHERE tariff=Itariff AND state = 0 LIMIT 1;
SELECT * FROM customer_shop WHERE id = #update_id;
END
I hope you guys can help me as I am completely out of ideas what's wrong. :/
Regards, Mark
You need to define an alternative command delimiter, as MySQL currently thinks your CREATE PROCEDURE command ends at the first ; it encounters (on line 3, after the 0), which would be a syntax error as it's after a BEGIN but before the corresponding END:
DELIMITER ;; -- or anything else you like
CREATE PROCEDURE
...
END;; -- use the new delimiter you chose above here
DELIMITER ; -- reset to normal
MySQL stored procedures do not use ":=" for value assignment, just use "=".
Also don't think "id = (SELECT #update_id := id)" is acceptable. Here's an alternative solution (untested):
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
select id into #update_id from customer_shop WHERE tariff=Itariff AND state = 0 LIMIT 1;
UPDATE customer_shop SET state = 1, instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment where id = #update_id;
SELECT * FROM customer_shop WHERE id = #update_id;
END
You may also want to put error handlers in case there's no matching row to be edited.

MySQL: IF / THEN statements in stored procedures

I'm writing a stored procedure that uses multiple IF / THEN statements that also need to execute multiple queries if they evaluate to true. Problem is, I can't seem to find any examples of the appropriate syntax. From the MySQL dev handbook, it seems like I could have multiple queries in the "statement_list," but so far I can't get it to work.
Here's what I'm trying to do:
SET agency =
COALESCE((SELECT org_agency_o_id
FROM orgs_agencies
WHERE org_agency_code = maj_agency_cat)
,(SELECT min(org_id)
FROM orgs
WHERE org_name LIKE CONCAT('U.S.',SUBSTRING(maj_agency_cat,5))))
IF agency IS NULL THEN
-- execute multiple queries
INSERT INTO orgs (org_name
,org_name_length
,org_type
,org_sub_types)
VALUES (CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5))
,LENGTH(CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
,'org','Org,GovernmentEntity,Federal,Agency');
SET agency = LAST_INSERT_ID();
END IF;
The error:
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 'IF agency IS NULL THEN
INSERT INTO orgs (org_name,org_name_length,org_type,' at line 53
Any ideas? I know it has to be something simple, so I would greatly appreciate anybody's input.
You got a few issues as far as I can see:
As David pointed out, each and every statement needs to be terminated by a ;
If you do a SELECT, better make sure it can only select one value by doing a LIMIT 1; If you've got an aggregate function like min() then only one value can come out.
If you writing the procedure using the CREATE PROCEDURE ... syntax, don't forget to set DELIMITER $$ before the CREATE PROCEDURE ... END $$ body and a DELIMITER ; after.
If you have multiple statements inside your IF THEN ... END IF block, it's a good idea to put them inside a BEGIN ... END; block.
If you have a return value, like agency here, why not make it a FUNCTION name (arg1: INTEGER) RETURNS INTEGER instead of a PROCEDURE name (IN arg1 INTEGER, OUT agency INTEGER). The function is much more versatile.
DELIMITER $$
CREATE PROCEDURE name(arg1 INTEGER, arg2 INTEGER, ...)
BEGIN
SELECT SET agency =
COALESCE((SELECT org_agency_o_id
FROM orgs_agencies
WHERE org_agency_code = maj_agency_cat) LIMIT 1,
(SELECT min(org_id) FROM orgs
WHERE org_name LIKE CONCAT('U.S.',SUBSTRING(maj_agency_cat,5))));
IF agency IS NULL THEN BEGIN
-- execute multiple queries
INSERT INTO orgs (org_name
,org_name_length
,org_type
,org_sub_types)
VALUES (CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5))
,LENGTH(CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
,'org','Org,GovernmentEntity,Federal,Agency');
SET agency = LAST_INSERT_ID();
END; END IF;
END $$
DELIMITER ;
No semicolon after your first SET statement.

MYSQL Procedures run, but return 0 rows affected

I call a procedure, it runs, and the console says "0 rows affected". Is this normal behavior for a MySQL procedure ?
The procedures are clearly doing what they should. One procedure has 2 insert statements, another has an insert and update statement, and I've seen the results with my own eyes. There are indeed rows being affected.
I'm not sure that I would use that result later on, but it seems like I'd want to get an accurate response from my DB whether or not anything was updated, especially when its expected.
Thoughts ?
MySQL 5.5 if it matters, and the procedures use transactions over auto-committed statements.
CREATE DEFINER=`root`#`localhost` PROCEDURE `create_issue`(user_id SMALLINT, title varchar(255), body LONGTEXT)
BEGIN
DECLARE MYUSERID SMALLINT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
START TRANSACTION;
INSERT INTO tracker.issue (user_id, title, body, creation_date, last_mod_date) values (user_id, title, body, CURDATE(), CURDATE());
UPDATE user_activity SET last_new_issue = CURDATE(), post_count = post_count + 1 WHERE user_activity.user_id = user_id;
COMMIT;
END
Edited to show the actual query. Also I've been searching and as best as I can tell this is a known issue over a year and a half old. So I suppose this one can be closed.
the "0 rows affected" response is for the last statement executed in the stored procedure.
usually i track the number of rows effected by manually counting them into session variables
DELIMITER $$
CREATE PROCEDURE `create_issue`(user_id SMALLINT, title varchar(255), body LONGTEXT)
BEGIN
DECLARE MYUSERID SMALLINT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
SET #inserted_rows = 0;
SET #updated_rows = 0;
START TRANSACTION;
INSERT INTO tracker.issue (user_id, title, body, creation_date, last_mod_date) values (user_id, title, body, CURDATE(), CURDATE());
SET #inserted_rows = ROW_COUNT() + #inserted_rows;
UPDATE user_activity SET last_new_issue = CURDATE(), post_count = post_count + 1 WHERE user_activity.user_id = user_id;
SET #updated_rows = ROW_COUNT() + #updated_rows;
COMMIT;
END
$$
the session variables can then be read after the SP was executed.
i am not sure if it is possible to override the response from the ROW_COUNT() function by setting a value to a variable,
I guess this is a reported bug. May be a good question for MySQL mailing list/forum. http://bugs.mysql.com/bug.php?id=44854
Something definitely isn't right. A sproc should still return the number of rows affected if there are multiple inserts occurring. I'm using the same version of MySQL and this works fine for me.
Are you sure you're not doing something like that
...SET col1='value1' AND col2='value2'...
instead of
...SET COL1='value1', col2='value2'...
Could you post your stored procedure?