Working with user defined variables in mysql - mysql

I have below set statements for MSSQL, which works perfect :
Declare #uid INT;
Declare #ct int;
Declare #code int;
Declare #usertype int;
Declare #flag char;
Declare #max_itemid int;
Declare #ulname varchar(10);
Declare #ufname varchar(10);
set #code= 123;
set #ulname='Will';
set #ufname='Smith';
set #max_itemid=(select max(itemid) from registration;
set #uid = (select uid from users where ulname=#ulname and ufname=#ufname)
set #ct=(select count(*) from usercodes where itemId=#uid)
set #usertype=(select usertype from users where uid=#uid)
If(#usertype=1)
begin
If (#uid>0)
Begin
select * from users where uid=#uid;
select * from usercodes where itemId=#uid;
if(#ct=0)
begin
if (#max_itemid=2 or #max_itemid=0)
set #flag='D';
else
set #flag='O';
insert into usercodes (itemId,CODE,Flag) values(#uid,#code,#flag);
select * from usercodes where itemId=#uid;
else
begin
PRINT 'UserCode is already added and below is result:';
select * from usercodes where itemId=#uid;
end
end
Else
PRINT 'No User Found';
end
else
begin
print 'User not added as usertype is ';PRINT #usertype;
end
Now i am a newbee to Mysql and want to rewrite the above statements as per the Mysql conventions. I figured out the syntax, and changes the declarations as :
SET #CODE='S10_12345' ;
SET #NAME='Will Smith';
and so on.
But the executions stops once it enters the IF statement. Can someone help figuring out where I am wrong ?
P.S. I am not using any procedures/functions - i can't store these bunch of statements as I have to customize the select statements as the DB can change each time.

Related

Select into multiple varibales with MySQL

I need to write a stored procedure using mysql.
In the repeat loop showing below, if I use something as:
SET VDATEI=(SELECT A.DATEI FROM STAFF_CONVENIOS A WHERE
A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
the stored procedure works well and I get a result set.
But, I need select into multiple variables. Something as:
SELECT
A.DATEI, A.DIAI, A.HORAI
INTO
VDATEI, VDIAI, VHORAI
FROM
STAFF_CONVENIOS A
WHERE
A.CONV_ID = CONVE AND A.STAFF_ID = MED
LIMIT 1;
In this case my stored procedure is broken I get no result set.
How to use select into to multiple variables into stored procedure with temporary tables?
My stored procedure is similar to:
CREATE PROCEDURE P_GETHORARIOS(
IN `MED` BIGINT,
IN `DATAREF` DATE,
IN `ESPEC` BIGINT,
IN `CONVE` BIGINT
)
BEGIN
DECLARE BDONE,BTEMP, BOCUP INT;
DECLARE DIA;
DECLARE VDIA,OK TINYINT;
DECLARE VDURACAO TINYINT;
DECLARE VDATEI DATE;
DECLARE VDIAI TINYINT;
DECLARE VHORAI TIME;
DECLARE VHORA, VHORAI,VHORAF TIME;
DECLARE CURS CURSOR FOR SELECT DIA,COALESCE(A.DURACAO,30) AS DURACAO, A.HINI FROM STAFF_ESCALA A
WHERE A.DIA=DIA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET BDONE = 1;
DROP TEMPORARY TABLE IF EXISTS TBLRESULTS;
CREATE TEMPORARY TABLE IF NOT EXISTS TBLRESULTS (
DATA_AG DATE,
DIA TINYINT,
HORA TIME );
SET DIA=DAYOFWEEK(DATAREF);
OPEN CURS;
SET BDONE = 0;
REPEAT
SET OK=TRUE;
FETCH CURS INTO VDIA,VDURACAO,VHORAI;
-- SET VDATEI=(SELECT A.DATEI FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT A.DATEI, A.DIAI,A.HORAI INTO VDATEI, VDIAI,VHORAI FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
SET BTEMP=IF(VDATEI IS NULL,TRUE,FALSE);
SET OK=OK AND BTEMP ;
IF (OK) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA);
ELSE INSERT INTO TBLRESULTS VALUES (VDATEI,VDIAI,VHORAI);
END IF;
UNTIL BDONE END REPEAT;
CLOSE CURS;
SELECT A.* FROM TBLRESULTS;
END
I have posted a sample of my problem. Here is the real stored procedure:
CREATE DEFINER=`SYSDBA`#`%` PROCEDURE `P_GETHORARIOS`(
IN `MED` BIGINT,
IN `DATAREF` DATE,
IN `ESPEC` BIGINT,
IN `CONVE` BIGINT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE BDONE INT;
DECLARE BTEMP TINYINT;
DECLARE BOCUP TINYINT;
DECLARE DIA BIGINT;
DECLARE VDIA TINYINT;
DECLARE VDURACAO TINYINT;
DECLARE VHORA, VHORAI,VHORAF TIME;
DECLARE VMED_ID BIGINT;
DECLARE VESPEC_ID BIGINT;
DECLARE VCONV_ID BIGINT;
DECLARE OK TINYINT;
DECLARE VNOMEESPEC,VNOMEMED VARCHAR(100);
DECLARE CURS CURSOR FOR SELECT DIA,COALESCE(A.DURACAO,30) AS DURACAO, A.HINI, A.HFIM, A.STAFF_ID,B.NOME AS NOMESTAFF, A.ESPEC_ID,C.NOME AS NOMEESPEC
FROM STAFF_ESCALA A
LEFT JOIN STAFF B ON B.ID=A.STAFF_ID
LEFT JOIN ESPECIALIDADES C ON C.ID=A.ESPEC_ID
WHERE A.DIA=DIA;
-- DECLARE CURS CURSOR FOR SELECT HINI, HFIM FROM STAFF_ESCALA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET BDONE = 1;
DROP TEMPORARY TABLE IF EXISTS TBLRESULTS;
CREATE TEMPORARY TABLE IF NOT EXISTS TBLRESULTS (
DATA_AG DATE,
DIA TINYINT,
HORA TIME,
MED_ID BIGINT,
NOME_MED VARCHAR(100),
ESPEC_ID BIGINT,
NOME_ESPEC VARCHAR(100)
);
SET DIA=DAYOFWEEK(DATAREF);
OPEN CURS;
SET BDONE = 0;
REPEAT
SET OK=TRUE;
FETCH CURS INTO VDIA,VDURACAO,VHORAI,VHORAF,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC;
IF (MED IS NOT NULL) THEN
SET OK=IF(MED=VMED_ID,TRUE,FALSE) ;
END IF;
IF (ESPEC IS NOT NULL) THEN
SET OK=OK AND IF(ESPEC=VESPEC_ID,TRUE,FALSE) ;
END IF;
IF (CONVE IS NOT NULL) THEN
-- SET #EOK=(SELECT 1 FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT 1 INTO #EOK FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
SET BTEMP=IF(#EOK IS NULL,TRUE,FALSE);
SET OK= OK AND BTEMP ;
END IF;
IF (OK) THEN
SET VHORA=VHORAI;
IF (VDURACAO IS NULL) THEN
SET VDURACAO=30;
END IF;
WHILE (VHORA <= VHORAF) DO
SET BOCUP=(SELECT 1 FROM AGENDA_STAFF A WHERE A.DATA_MARCADA=DATAREF AND A.HORA_MARCADA=VHORA);
IF (BOCUP IS NULL) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC);
END IF;
SET VHORA=ADDTIME(VHORA, VDURACAO * 100);
END WHILE;
SET VHORA=ADDTIME(VHORA, VDURACAO * (-100));
IF (VHORA < VHORAF) THEN
SET VHORA=VHORAF;
SET BOCUP=(SELECT 1 FROM AGENDA_STAFF A WHERE A.DATA_MARCADA=DATAREF AND A.HORA_MARCADA=VHORA);
IF (BOCUP IS NULL) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC);
END IF;
END IF;
END IF;
UNTIL BDONE END REPEAT;
CLOSE CURS;
SELECT A.* FROM TBLRESULTS A LEFT JOIN AGENDA_STAFF B ON B.STAFF_ID=A.MED_ID AND B.HORA_MARCADA=A.HORA AND B.DATA_MARCADA=A.DATA_AG;
END
//
The problem is with the lines:
-- SET #EOK=(SELECT 1 FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT 1 INTO #EOK FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
If I use "SET #EOK..." all works well.
If I use SELECT 1 INTO #EOK.. the problem appears.
More info with data
Expected result from call p_gethorarios(7,'2017-11-20',47,21)
"data_ag";"dia";"hora";"med_id";"nome_med";"espec_id";"nome_espec"
"2017-11-20";"2";"08:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"10:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"08:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"10:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
STAFF-ESCALA TABLE
ID;STAFF_ID;DIA;HINI;HFIM;ESPEC_ID;DURACAO;CREATION_TIME;MODIFICATION_TIME;LAST_USER_MODIF
25;7;2;08:00:00;10:00:00;50;;18/11/2017 21:44:02;;1
26;7;6;08:00:00;10:00:00;50;;18/11/2017 21:55:27;;1
27;7;4;08:00:00;10:00:00;50;;18/11/2017 21:55:27;;1
28;7;5;08:00:00;10:00:00;50;;18/11/2017 21:56:36;;1
35;7;3;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
36;7;5;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
38;7;2;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
You may have to use user/session variables (the #xyz kind). The documentation does not explicitly state such, but it only shows examples with them.
https://dev.mysql.com/doc/refman/5.7/en/select-into.html
If it is an issue with the NOT FOUND handler getting triggered from something other than the cursor, you could try structuring your code something like this (very pseudocode):
FETCH
WHILE( NOT DONE )
BEGIN
DO STUFF
SET DONE = FALSE
FETCH
END

procedure, setting variable, repeat until, substring from one variable, mysql

I am looking for help with my sql procedure.
I would like to substring in loop each username, and alias from two input arguments and add it into table users. I have two procedures.
Sorry for Polish variable names and procedure names.
My first procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `dodajZawodnika`(IN `dane` VARCHAR(50), IN `wyswietlanie` VARCHAR(50))
NO SQL
BEGIN
IF (SELECT 1 = 1 from zawodnicy where danezawodnika = dane AND dowyswietlenia=wyswietlanie) THEN
BEGIN
Select id from zawodnicy where danezawodnika=dane AND dowyswietlenia=wyswietlanie;
END;
ELSE
BEGIN
Insert INTO zawodnicy (danezawodnika, dowyswietlenia) VALUES(dane, wyswietlanie);
SELECT last_insert_id() AS ID;
END;
END IF;
END;
My second procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `stworzSklad`(IN `dane` VARCHAR(1500), IN `pseudo` VARCHAR(1000))
NO SQL
BEGIN
DECLARE counter INTEGER;
DECLARE zawodnik VARCHAR(1500);
DECLARE pseudonim VARCHAR(1000);
DECLARE zawodnicy VARCHAR(1500);
DECLARE pseudonimy VARCHAR(1000);
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
ROLLBACK;
END;
set counter = 0;
set #zawodnicy = dane;
set #pseudonimy = psuedo;
select #zawodnicy, #pseudonimy;
REPEAT
set zawodnik=(SELECT TRIM(SUBSTRING_INDEX(#zawodnicy, ',', 1)));
set pseudonim=(SELECT TRIM(SUBSTRING_INDEX(#pseudonimy, ',', 1)));
call dodajZawodnika(zawodnik, pseudonim);
SELECT RIGHT(#zawodnicy, TRIM(length(#zawodnicy) - length(SUBSTRING_INDEX(#zawodnicy, ',', 1)) - 1)) into #zawodnicy;
SELECT RIGHT(#pseudonimy, TRIM(length(#pseudonimy) - length(SUBSTRING_INDEX(#pseudonimy, ',', 1)) - 1)) into #pseudonimy;
select zawodnik as 'zawodnik', pseudonim as 'pseudonim', dane as 'dane', pseudo as 'pseudo', #zawodnicy as 'zawodnicy', #pseudonimy as 'pseudonimy';
set counter = counter + 1;
UNTIL (#zawodnicy = '' or counter = 30)
END REPEAT;
select counter;
END
I am fighting with it from about 2 hours.
I would like to use also transaction for this insert.
Please help me with this little problem.
How to make this in proper way?
Now, calling stworzSklad procedure make endless loop (ofc without counter in until condition) and any of user was not inserted in my table.
Cheers!

Sql trigger not not working

Hi I've a student table where I have columns like username, usertype, password etc.
I have wrote a trigger for the this table which creates a username for the for the usertype 'Student', Here is the trigger codes
> DROP TRIGGER `sasis`.`USERNAMEAutoGen`;
DELIMITER ||
CREATE TRIGGER `sasis`.`USERNAMEAutoGen`
BEFORE INSERT ON `sasis`.`userinfo`
FOR EACH ROW BEGIN
if (usertype== 'Student')
declare i varchar(2);
declare usrnm varchar(20);
declare fullusrnm varchar(255);
declare curyr varchar(10);
declare curm varchar(10);
declare rcount varchar(50);
set i='I';
select date_format(now(),'%y') into curyr;
select date_format(now(),'%b') into curm;
set usrnm=concat(i,curyr,upper(curm));
select count(*) into rcount from userinfo where username like concat(usrnm,'%');
if(rcount<9) then
set rcount=concat('0000',(rcount+1));
elseif (rcount<99) then
set rcount=concat('000',(rcount+1));
elseif (rcount<999) then
set rcount=concat('00',(rcount+1));
end if;
set fullusrnm=concat(i,curyr,upper(curm),rcount);
if (new.username is null or trim(new.username)='') then
set NEW.username=fullusrnm;
end if; end if; END||
DELIMITER ;
It was working before, but now its showing some error which states that there is a syntax error near '=='Student') declare i varchar(2). etc. And I have no clue how to solve it
please help with your valuable answers. Thanks in advance.
I have tried with "if (usertype= 'Student') THEN" as well but then it shows error message like syntax error near declare i varchar(2);
As I browsed on the manual, I can't see any == supported,
MySQL OPERATORS
So in your TRIGGER, should only be IF (usertype = 'Student') THEN
FULL TRIGGER CODE
CREATE TRIGGER `sasis`.`USERNAMEAutoGen`
BEFORE INSERT ON `sasis`.`userinfo`
FOR EACH ROW
BEGIN
declare i varchar(2);
declare usrnm varchar(20);
declare fullusrnm varchar(255);
declare curyr varchar(10);
declare curm varchar(10);
declare rcount varchar(50);
IF (usertype== 'Student') THEN
set i='I';
select date_format(now(),'%y') into curyr;
select date_format(now(),'%b') into curm;
set usrnm=concat(i,curyr,upper(curm));
select count(*) into rcount from userinfo where username like concat(usrnm,'%');
if(rcount<9) then
set rcount=concat('0000',(rcount+1));
elseif (rcount<99) then
set rcount=concat('000',(rcount+1));
elseif (rcount<999) then
set rcount=concat('00',(rcount+1));
end if;
set fullusrnm=concat(i,curyr,upper(curm),rcount);
if (new.username is null or trim(new.username)='') then
set NEW.username=fullusrnm;
end if;
end if;
END||
DELIMITER ;
are you sure mysql allows == as equality operator?

Find a column in one of many tables given only one value?

I have this:
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name = 'whatever'
but what I need is something like this:
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_data = 'whatever'
So, in words, I have a value and I have no idea where it's stored. Is there a way to literally check the entire database and return the table, column?
aaaand yes, I know, db admins wouldn't be happy!
This might get you going in the right direction.
1. Create find_column stored procedure
DROP PROCEDURE IF EXISTS `find_column`;
DELIMITER $$
CREATE PROCEDURE `find_column`(IN i_value varchar(200),
OUT o_columns varchar(2000),
OUT o_message varchar(500))
MAIN_BLOCK : BEGIN
DECLARE is_numeric boolean;
CHECK_NUMERIC : BEGIN
set is_numeric = i_value REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
END CHECK_NUMERIC;
FIND_IT : BEGIN
DECLARE bNoMoreRows BOOLEAN DEFAULT FALSE;
DECLARE v_schema varchar(64);
DECLARE v_table varchar(64);
DECLARE v_column varchar(64);
DECLARE v_data_type varchar(64);
DECLARE v_count int;
-- all schemas, tables and columns in DB
DECLARE columns CURSOR FOR
select table_schema,table_name,column_name,data_type from information_schema.columns;
DECLARE EXIT HANDLER for SQLEXCEPTION set o_message := concat('Unexpected error while trying to find schema, table and column for value : ',i_value);
declare continue handler for not found set bNoMoreRows := true;
open columns;
set o_columns = "";
COLUMN_LOOP: loop
fetch columns
into v_schema,v_table,v_column,v_data_type;
if (
(v_data_type in ('int','bigint','tinyint','decimal','smallint','mediumint') and is_numeric=1)
or (v_data_type not in ('int','bigint','tinyint','decimal','smallint','mediumint') and is_numeric=0)
)
then
SET #dyn_sql=CONCAT('select count(*) into #c from `',v_schema,'`.`',v_table,'` where `',v_column,'`=?');
SET #c = 0;
SET #v_value = i_value;
PREPARE stmt FROM #dyn_sql;
EXECUTE stmt using #v_value;
DEALLOCATE PREPARE stmt;
SET v_count = #c;
if v_count > 0 then
if length(o_columns <= 1800) then
set o_columns = concat(o_columns,",",v_schema,".",v_table,".",v_column);
end if;
end if;
end if;
if bNoMoreRows then
set o_columns = substring(o_columns,2);
close columns;
leave COLUMN_LOOP;
end if;
END loop COLUMN_LOOP;
END FIND_IT;
END MAIN_BLOCK$$
DELIMITER ;
2. Call find_column stored procedure with your value
call `find_column`('whatever',#columns,#message);
3. Check out the results
select #columns;
The is_numeric bit is lovingly ripped-off JBB's answer from this post.
It ain't perfect (what happens if the number of columns that your value exists exceeds 10 or so? If that is the case then this will only return the first 10 or so columns (depends on how long the schema.table.column name string is).
Hopefully it'll get you going in the correct direction.
An you're right. You're DB admins will be unhappy with you. But if you don't annoy them once in a while then you're not trying hard enough IMHO ;-)
Good luck.

MySQL Procedure with Cursor Parameter

I have the following code that is supposed to return a list of customers that are younger than the provided age parameter and a total count of found records.
My table consists of: columns ID, FIRST_FIRSTNAME, LASTNAME, DATE_OF_BIRTH
I could have easily made a few mistakes in the syntax, logic and formatting of this procedure but forgive me, I am new to this! The following is my sql procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS sample_procedure$$
CREATE PROCEDURE sample_procedure(IN actualinput INT)
BEGIN
DECLARE no_more_customers int(4);
DECLARE l_customer_count int(4);
DECLARE l_id varchar(1);
DECLARE l_first_name varchar(10);
DECLARE l_last_name varchar(10);
DECLARE l_date_of_birth varchar(20);
DECLARE customer_list varchar(250);
DECLARE dateinput DATE;
SET dateinput=DATE_SUB(now(), interval actualinput year);
DECLARE cid CURSOR FOR
SELECT ID, FIRST_FIRSTNAME, LAST_NAME, DATE_OF_BIRTH
FROM customers WHERE DATE_OF_BIRTH >= dateinput;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_customers=1;
SET no_more_customers=0;
SET l_customer_count=0;
OPEN cid;
cid_cursor: REPEAT
FETCH cid INTO l_id, l_first_name, l_last_name, l_date_of_birth; IF no_more_customers THEN
LEAVE cid_cursor;
END IF;
SET customer_list=concat(customer_list, l_id,',',l_first_name,',',l_last_name,',',l_date_of_birth);
SET l_customer_count=1+l_customer_count;
UNTIL no_more_customers
END REPEAT cid_cursor;
CLOSE cid;
SET no_more_customers=0;
SELECT customer_list AS Customers;
SELECT concat(l_customer_count);
END;
$$
I appear to have an error in the method I used to calculate the age of customers, possibly an issue with the method I used to call the cursor and my final list of customers is only returning null.
Thanks in advance...
I can suppose that variable 'customer_list' should be initialized, e.g. -
...
DECLARE customer_list VARCHAR(250) DEFAULT '';
...
because 'SET customer_list = CONCAT(customer_list, ...)' when customer_list is NULL, will return NULL too.
Take advantage of MySQL Stored Procedure Debugger. Hope this feature will help you.