use local variables in mysql IF statement - mysql

I modified the statements as below, but still errors at the line with the DECLARE statement.
BEGIN
DECLARE searchresult int(11);
SET searchresult=(Select count(*) from wbsimsynuqsql where SimBase='a cappella');
IF searchresult >0 THEN
Select * from simsyn1sql where BaseID = (Select Distinct BaseID from wbsimsynuqsql where SimBase='a cappella')
ELSE
Select * from simsyn1sql where BaseID = (Select Distinct BaseID from wbsimsynuqsql where SimSyn='a cappella')
END IF;
END
I am using the expression below in PHPMYADMIN with the intent to use it later in a PHP/MySQL application. It gives an error relating to the DECLARE statement in line 1.
I've looked at example declarations in MySQL and I don't see an error, but I'm doing something wrong and would appreciate a correction/suggestion.
DECLARE searchresult int(11);
SET searchresult=(Select count(*) from wbsimsynuqsql where SimBase='a cappella');
IF searchresult >0
{Select * from simsyn1sql where BaseID = (Select Distinct BaseID from wbsimsynuqsql where SimBase='a cappella')}
[ ELSE
{Select * from simsyn1sql where BaseID = (Select Distinct BaseID from wbsimsynuqsql where SimSyn='a cappella')} ]
END IF;

DECLARE is permitted only inside a BEGIN ... END compound statement and must be at its start, before any other statements.
like inside a CREATE PROCEDURE you can use DECLARE
Your IF statement is missing a THEN
and remove the square brackets ([]) and the curly braces ({})
If your subquery returns more than one BaseID you might have to use IN instead of =
sqlfiddle

Related

Can I use subquery in a user-defined function

I try to use subquery in mysql custom user-defined function I get an error so could u help me with one example.
Here is my code:
CREATE DEFINER=`root`#`localhost` FUNCTION `findsubName`(counts INT)
RETURNS varchar(255) CHARSET utf8
BEGIN
DECLARE result VARCHAR(500) DEFAULT NULL;
DECLARE v_name VARCHAR(200);
DECLARE finished INT(1) DEFAULT 0;
DECLARE my_cursor CURSOR FOR
SELECT id, (SELECT t_name FROM ajctb_titles b WHERE a.jt_id=b.t_id)
as tableName FROM ajctb_vacancies a limit counts;
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN my_cursor;
calc_change: LOOP
FETCH my_cursor INTO v_name;
IF finished THEN
LEAVE calc_change;
END IF;
IF result<>'' THEN
SET result = CONCAT_WS(',',result,v_name);
ELSE
SET result = v_name;
END IF;
END LOOP calc_change;
CLOSE my_cursor;
RETURN result;
END
Error message:
Error Code: 1328. Incorrect number of FETCH variables
Error message: Error Code: 1328. Incorrect number of FETCH variables
Error messages attempt to tell you what the problem is. It is in the FETCH. Looking at the documentation:
13.6.6.3 Cursor FETCH Syntax
FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
This statement fetches the next row for the
SELECT statement associated with the specified cursor (which must be
open), and advances the cursor pointer. If a row exists, the fetched
columns are stored in the named variables. The number of columns
retrieved by the SELECT statement must match the number of output
variables specified in the FETCH statement.
https://dev.mysql.com/doc/refman/8.0/en/fetch.html
2 columns in your query:
SELECT
id
, (
SELECT
t_name
FROM ajctb_titles b
WHERE a.jt_id = b.t_id
)
AS tableName
means 2 variables are needed the FETCH
It hasn't even attempted the subquery yet.
Regarding that correlated subquery it could be a problem. When you use a subquery in the select clause like this it MUST return no more then one value. So you should use limit 1 if you continue with that subquery.
That subquery can be replaced with a join. e.g.
SELECT
id
, b.t_name AS tableName
FROM ajctb_vacancies a
LEFT JOIN ajctb_titles b ON a.jt_id = b.t_id
You may want to use an INNER JOIN if you must always have a non-null tablename returned.

How to use GROUP_CONCAT in Stored procedure MySQL

I'm trying to use comma separated values (#job_skills) in another query like as follows in my stored procedure. But it does not work as expected. Amy be it only consider first value from comma separated string. Is there any other way to patch up ?
SELECT GROUP_CONCAT(skillId) as job_skills FROM tbljob_skill as jskl WHERE jskl.jobpostingId = param_jobid INTO #job_skills;
BLOCK6: BEGIN
DECLARE curl_job12 CURSOR FOR SELECT * FROM (SELECT js.jobseekerId FROM tbljobseeker_skill as jss INNER JOIN tbmstjobseeker as js ON (js.jobseekerId = jss.jobseekerId) INNER JOIN tblrecommended_jobseekers_details as rjd ON (js.jobseekerId=rjd.jobseekerId) WHERE jss.skillId IN (#job_skills) AND js.isActive = 'Y' AND js.lat<>0 AND js.lang<>0 AND rjd.sessionid=param_sessionid GROUP BY js.jobseekerId) as m;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET job_done12 = TRUE;
OPEN curl_job12;
read_loop_job12: LOOP
FETCH curl_job12 INTO jsid, miles;
IF job_done12 THEN
LEAVE read_loop_job12;
END IF;
INSERT INTO temp_skills (jobId,skill,jobseekerId) VALUES (param_sessionid,#job_skills,jsid);
IF jsid <> '' THEN
SELECT COUNT(1) INTO check_exists FROM tblrecommended_jobseekers_details WHERE sessionid = param_sessionid AND type = 'match 1 - SKILLS' AND jobseekerId = jsid;
IF check_exists = 0 THEN
START TRANSACTION;
INSERT INTO temp_jobseekers_scores (jobseekerId,score,type,miles) VALUES (jsid,score_skills,'match 1',miles);
INSERT INTO tblrecommended_jobseekers_details (jobseekerId,score,type,miles,sessionid) VALUES (jsid,score_skills,'match 1 - SKILLS',miles,param_sessionid);
COMMIT;
END IF;
END IF;
END LOOP;
CLOSE curl_job12;
END BLOCK6;
Generated comma separated values are a SET and treated as a single string when used with IN function. Instead you have to use FIND_IN_SET to compare with other values.
Change your WHERE clause in CURSOR definition as below.
DECLARE curl_job12 CURSOR FOR
SELECT * FROM (
SELECT js.jobseekerId
FROM tbljobseeker_skill as jss
INNER JOIN tbmstjobseeker as js
ON (js.jobseekerId = jss.jobseekerId)
INNER JOIN tblrecommended_jobseekers_details as rjd
ON (js.jobseekerId=rjd.jobseekerId)
-- WHERE jss.skillId IN (#job_skills)
WHERE FIND_IN_SET( jss.skillId, #job_skills )
AND js.isActive = 'Y'
AND js.lat<>0
AND js.lang<>0
AND rjd.sessionid=param_sessionid
GROUP BY js.jobseekerId
) as m;
Refer to Documentation:
FIND_IN_SET(str,strlist)
Returns a value in the range of 1 to N if the string str is in the
string list strlist consisting of N substrings

MySQL 5.5 Query Based on IF statement

I've been battling with this for too long so I'm here to ask for help...
I have a MySQL stored procedure that I want to do the following:
given an 'id' and a 'username' for a given record
if id does not exist in table then create record
else if id exists and username is not the same as what exists then update record
else do nothing
I've tried the following:
BEGIN
DECLARE doCreate INT;
DECLARE doUpdate INT;
SELECT COUNT(*) INTO doCreate FROM app_user WHERE id=1;
IF (doCreate > 0) THEN
SELECT COUNT(*) INTO doUpdate FROM app_user WHERE id=1 AND username='other';
END IF
IF(doCreate = 0) THEN ---SYNTAX ERROR ON THIS LINE---
SELECT 'CREATE';
ELSE IF(doUpdate = 0) THEN
SELECT 'UPDATE';
ELSE
SELECT 'NOTHING';
END IF
END
I've also tried replacing the if-elseif-else block with a case statement but get the same result...
CASE ---ERROR ON THIS LINE---
WHEN doCreate = 0 THEN
SELECT 'CREATE';
WHEN doUpdate = 0 THEN
SELECT 'UPDATE';
ELSE
SELECT 'NOTHING';
END
I seem to get a syntax error on anything that comes after the first END IF, so that's the first problem that occurs...
Any help would be appreciated - I'm sure there's a better way to do this.
I believe you'll need to terminate the END IFs with ;, and internally ELSEIF should be one word. Otherwise, another END IF is needed, but not found.
IF (doCreate > 0) THEN
SELECT COUNT(*) INTO doUpdate FROM app_user WHERE id=1 AND username='other';
END IF; /* terminate with ; */
IF(doCreate = 0) THEN
SELECT 'CREATE';
ELSEIF(doUpdate = 0) THEN
SELECT 'UPDATE';
ELSE
SELECT 'NOTHING';
END IF; /* terminate with ; */
Look over the MySQL IF/ELSE syntax reference for various usage examples.

mysql procedure syntax error

I get an error by sending the following query (MYSQL 5.0):
DELIMITER //
CREATE PROCEDURE relationTable ()
BEGIN
DECLARE articlecount int;
DECLARE keywordcount int;
DECLARE articlehits int;
DECLARE ac int DEFAULT 0;
DECLARE kc int;
DECLARE articleid int;
DECLARE word varchar(100);
DECLARE word_id int;
SET articlehits = 0;
SET articlecount = (SELECT count(id) from articles);
SET keywordcount = (SELECT count(id) from keywords);
outerloop: WHILE (ac < articlecount) DO
SET kc = 0;
SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
innerloop: WHILE (kc < keywordcount) DO
IF (articlehits < 5) THEN
SELECT keyword, id INTO word, word_id from keywords LIMIT 1 OFFSET kc;
IF (0 < (SELECT COUNT(id) from articles WHERE id=articleid AND CONCAT(title, " ",text) REGEXP word)) THEN
INSERT INTO articles (id, articleID, keywordID, type) VALUES(NULL, articleid, word_id, 'type1');
SET articlehits = articlehits + 1;
END IF;
SET kc = kc + 1;
ELSE
SET kc = keywordcount;
END IF;
END WHILE innerloop;
SET ac = ac + 1;
END WHILE outerloop;
END;
//
DELIMITER ;
This produces the following error:
ERROR 1064 (42000): 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 'LIMIT 1 OFFSET ac); innerloop: WHILE (kc <
keywordcount) DO TO word, word_id from' at line 15
Any idea why this happens?
(Wrote this to create a relation table between articles and keywords, to enable smart-links in article view.)
Try to remove the while labels:
WHILE (ac < articlecount) DO
SET kc = 0;
SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
WHILE (kc < keywordcount) DO
IF (articlehits < 5) THEN
SELECT keyword, id INTO word, word_id from keywords LIMIT 1 OFFSET kc;
IF (0 < (SELECT COUNT(id) from articles WHERE id=articleid AND CONCAT(title, " ",text) REGEXP word)) THEN
INSERT INTO articles (id, articleID, keywordID, type) VALUES(NULL, articleid, word_id, 'type1');
SET articlehits = articlehits + 1;
END IF;
SET kc = kc + 1;
ELSE
SET kc = keywordcount;
END IF;
END WHILE;
SET ac = ac + 1;
END WHILE;
MySQL has connection-specific user-defined variables of the form #varname and declared procedure variables of the type you are using in your code sample. In my experience with procedures, sometimes only one of the types is allowed, and if I recall correctly, one of those situations may be when SELECTing INTO. You might try using user-defined variables here, as follows:
SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
innerloop: WHILE (kc < keywordcount) DO
IF (articlehits < 5) THEN
SELECT keyword, id INTO #word, #word_id from keywords LIMIT 1 OFFSET kc;
Just an idea.
One problem may be the SET acticleid = (SELECT...). Try with SELECT .. INTO:
SELECT id INTO #articleid FROM articles LIMIT 1 OFFSET ac;
Variable LIMIT in stored procedures is only supported in new MySQL versions. Note that since you dont have an ORDER BY you will get a random row. It looks like you want to use a CURSOR instead. See docs.
At the risk of seeming over-critical, I believe you should rewrite this procedure to use cursors for traversing your databases, instead of individual selects with LIMIT.
see Cursors in MySQL Docs
Thank for your help so far.
The idea of Tom Haws proved to be correct. The variables for a SELECT INTO statement have to be user-defined.
I edited my code to use cursors, and user-defined variables as followed:
delimiter //
CREATE PROCEDURE relationTable ()
BEGIN
DECLARE articlehits int;
DECLARE looparticles int DEFAULT TRUE;
DECLARE loopwords int DEFAULT TRUE;
DECLARE done INT DEFAULT FALSE;
DECLARE keywordcursor CURSOR FOR SELECT keyword, id FROM keywords;
DECLARE articlecursor CURSOR FOR SELECT id FROM articles;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN articlecursor;
WHILE (looparticles) DO
FETCH articlecursor INTO #articleid;
IF done THEN SET looparticles = FALSE;
ELSE
SET articlehits = 0;
OPEN keywordcursor;
WHILE (loopwords) DO
FETCH keywordcursor INTO #word, #wordid;
IF (articlehits < 5) AND NOT done THEN
IF (0 < (SELECT COUNT(id) FROM articles WHERE id=#articleid AND CONCAT(title, " ", text) REGEXP #word)) THEN
INSERT INTO keyword_article_rel (id, meldungID, wordID) VALUES(NULL, #articleid, #wordid);
SET articlehits = articlehits + 1;
END IF;
ELSE
SET loopwords = FALSE;
CLOSE keywordcursor;
SET done = FALSE;
END IF;
END WHILE;
END IF;
END WHILE;
CLOSE articlecursor;
END;
//
delimiter ;
And now I get an other error that I really can't explain:
ERROR 1064 (42000): 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 CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN articlecursor; W' at line 6
This error confuses me because it can't have a problem with the handler. The handler is declared as in the example of the mysql-documentation. Could the problem be that I can't create two cursors like this?

MySQL Stored Procedures : cursor declaration

Sorry for the vague title, here is my problem. I have stored procedures for DB2 that i try to convert for MySQL. I'd like to know if i can write the SELECT statement in the cursor declaration as a string variable. For example with DB2 i have this :
(...)
-- Declare cursors
DECLARE c_very_init CURSOR WITH RETURN FOR s_very_init;
DECLARE c_date CURSOR WITH RETURN FOR s_date;
DECLARE CONTINUE HANDLER FOR not_found
SET at_end = 1;
-- In case the_date is 0, retrieve the first date
IF the_date = 0 THEN
SET sql_end_date = '
SELECT DATE
FROM ACCOUNTS
WHERE REF = ''' || the_ref || '''
ORDER BY ID ASC FETCH FIRST 1 ROWS ONLY';
PREPARE s_date FROM sql_end_date;
OPEN c_date;
FETCH FROM c_date INTO data_ins;
SET the_last_date = data_ins;
CLOSE c_date;
ELSE
SET the_last_date = the_date;
END IF;
-- Get the 'very' initial value
SET sql_very_init = '
SELECT in, out
FROM MOVEMENTS
WHERE REF = ''' || the_ref || '''
AND DATE < ' || the_last_date;
PREPARE s_very_init FROM sql_very_init;
OPEN c_very_init;
FETCH FROM c_very_init INTO dare, avere;
-- Loop through the results
(...)
I declare a c_very_init cursor, but at the time of the cursor declaration in the SP i still don't know the full select statement because i need to fetch (if necessary) the the_last_date value. It seems i can't do this :
DECLARE c_very_init CURSOR WITH RETURN FOR s_very_init;
with MySQL, the syntax being with the statement directly in the declaration :
DECLARE c_very_init CURSOR FOR SELECT blaablaa...;
Am i wrong?
Thank you.
fabien.
No, you cannot declare cursors in this way. But if 'the_ref' is a variable, you could do it like this -
...
DECLARE the_ref INT DEFAULT 10;
DECLARE cur1 CURSOR FOR SELECT column1 FROM table1 WHERE column1 = the_ref;
...