I have a mysql procedure that it doesn´t work an IF condition with AND. I'm not sure what is the correct syntax.
CREATE PROCEDURE insere_orcamento(
IN ida VARCHAR(10),
IN volta VARCHAR(10),
OUT result INT
)
BEGIN
IF (ida='sim' AND volta=NULL) THEN
SET result = 50;
ELSEIF (ida=NULL AND volta='sim') THEN
SET result = 51;
END IF;
END
The value NULL must be checked with IS
Or like akina said you can also use <=>
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `insere_orcamento`(
IN ida VARCHAR(10),
IN volta VARCHAR(10),
OUT result INT
)
BEGIN
IF (ida='sim' AND volta IS NULL) THEN
SET result := 50;
ELSEIF (ida IS NULL AND volta = 'sim') THEN
SET result := 51;
END IF;
END$$
DELIMITER ;
Related
How to improve the procedure to perform faster?
I have 3 procedures, the first searches the balance before the second updates the balance and the third I use to do the processing where I call the two previous procedures.
In short, when I insert a table record a timer in the service redo the balance processing by calling the procedure PROC_PROCESSAR_SALDO.
DROP PROCEDURE IF EXISTS `PROC_SALDO_ANTERIOR`;
DELIMITER $$
CREATE PROCEDURE `PROC_SALDO_ANTERIOR` (
IN codigo_Empresa_par INT,
IN codigo_Filial_par INT,
IN codigo_Conta_par INT,
IN sequencia_par BIGINT(20),
IN data_Hora_par DATETIME,
OUT sequencia_ret BIGINT(20),
OUT data_Hora_ret DATETIME,
OUT saldo_Atual_ret DECIMAL(20, 2)
)
BEGIN
SELECT SEQUENCIA, DATAHORA, SALDO_ATUAL INTO sequencia_ret, data_Hora_ret, saldo_Atual_ret
FROM CONTAS_CORRENTES
WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
CODIGO_FILIAL = codigo_Filial_par AND
CODIGO_CONTA = codigo_Conta_par AND
((DATAHORA =data_Hora_par AND SEQUENCIA < sequencia_par) OR (DATAHORA < data_Hora_par))
ORDER BY DATAHORA DESC, SEQUENCIA DESC LIMIT 1;
if sequencia_ret IS NULL THEN
SET sequencia_ret := 0;
SET data_Hora_ret := '0001/01/01 12:00:00';
SET saldo_Atual_ret := 0;
END IF;
END;
DELIMITER ;
DROP PROCEDURE IF EXISTS `PROC_ATUALIZAR_SALDO`;
DELIMITER $$
CREATE PROCEDURE `PROC_ATUALIZAR_SALDO` (
IN codigo_Empresa_par INT,
IN codigo_Filial_par INT,
IN codigo_Conta_par INT,
IN sequencia_par BIGINT(20),
IN data_Hora_par DATETIME,
IN saldo_Atual_par DECIMAL(20,2)
)
BEGIN
DECLARE SEQUENCIA_NEW BIGINT(20) DEFAULT 0;
DECLARE DEBITO_NEW DECIMAL(20,2) DEFAULT 0;
DECLARE CREDITO_NEW DECIMAL(20,2) DEFAULT 0;
DECLARE SALDO_ANTERIOR DECIMAL(20,2) DEFAULT 0;
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR SELECT A.SEQUENCIA, A.DEBITO, A.CREDITO
FROM CONTAS_CORRENTES A
WHERE A.CODIGO_EMPRESA = codigo_Empresa_par AND
A.CODIGO_FILIAL = codigo_Filial_par AND
A.CODIGO_CONTA = codigo_Conta_par AND
((A.DATAHORA = data_Hora_par AND
A.SEQUENCIA > sequencia_par) OR
(A.DATAHORA > data_Hora_par))
ORDER BY A.DATAHORA ASC,
A.SEQUENCIA ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
START TRANSACTION;
SET SALDO_ANTERIOR := saldo_Atual_par;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO SEQUENCIA_NEW, DEBITO_NEW, CREDITO_NEW;
IF done THEN
LEAVE ins_loop;
END IF;
SET SALDO_ANTERIOR := SALDO_ANTERIOR - DEBITO_NEW + CREDITO_NEW;
UPDATE CONTAS_CORRENTES SET SALDO_ATUAL = SALDO_ANTERIOR
WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
CODIGO_FILIAL = codigo_Filial_par AND
CODIGO_CONTA = codigo_Conta_par AND
SEQUENCIA = SEQUENCIA_NEW;
END LOOP;
CLOSE cur;
COMMIT;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS `PROC_PROCESSAR_SALDO`;
DELIMITER $$
CREATE PROCEDURE `PROC_PROCESSAR_SALDO` (
IN codigo_Empresa_new INT,
IN codigo_Filial_new INT,
IN codigo_Conta_new INT,
IN sequencia_new BIGINT(20),
IN data_Hora_new DATETIME
)
BEGIN
CALL PROC_SALDO_ANTERIOR(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, sequencia_new,
data_Hora_new, #sequencia_ret, #data_Hora_ret, #saldo_Atual_ret);
CALL PROC_ATUALIZAR_SALDO(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, #sequencia_ret,
#data_Hora_ret, #saldo_Atual_ret);
END $$
DELIMITER ;
CALL PROC_PROCESSAR_SALDO(#CODIGO_EMPRESA, #CODIGO_FILIAL, #CODIGO_CONTA, #SEQUENCIA, #DATAHORA);
You have to check what makes the queries slow. You basically have two things to check:
Do the individual queries use indexes?
Does the cursor loop produce so many rows that (mabye an slightly unoptimized) query in the loop adds up leading to the slow performance
Check the individual queries with EXPLAIN for index use. You can also add select now() after in each query and execute the procedure and you should see which part consumes the time.
I created a stored procedure which requirement as below
When I execute the stored procedure with one username typed in which be compare if username are exists in database then (variable) result_userId will set at userId ELSE if username dose not exists in database then (variable) result_userId will be set the number 99
BUT I CANNOT DO THAT
Please help me !
::CODE BELOW::
DELIMITER $$
USE `shoppy` $$
CREATE PROCEDURE `testProc02`
(
IN _username CHAR(50),
OUT result_userId INT UNSIGNED
)
BEGIN
SELECT #uId := userId FROM user
WHERE userName = _username;
IF #uId = NULL THEN
SET result_userId = 99;
ELSE
SET result_userId = #uId;
END IF;
END $$
DELIMITER ;
When I CALL testProc02();
enter image description here
You can't use the equality operator = on null. You have to test the expression IS NULL or use the null-safe equality operator <=>.
Your code should be
DELIMITER $$
USE `shoppy` $$
CREATE PROCEDURE `testProc02`
(
IN _username CHAR(50),
OUT result_userId INT UNSIGNED
)
BEGIN
SELECT #uId := userId FROM user
WHERE userName = _username;
IF #uId IS NULL THEN
SET result_userId = 99;
ELSE
SET result_userId = #uId;
END IF;
END $$
DELIMITER ;
What happens is that #uID = NULL always evaluates to null, which the if interprets as false.
I have to create an SP that returns a value if it's valid or not. But it doesn't return anything and I don't know, why?
CREATE DEFINER=`root`#`localhost` PROCEDURE `validar_egreso`(
IN codigo_producto VARCHAR(100),
IN cantidad INT,
OUT valido INT(11)
)
BEGIN
DECLARE resta INT(11);
SET resta = 0;
SELECT (s.stock - cantidad) INTO resta
FROM stock AS s
WHERE codigo_producto = s.codigo;
IF (resta > s.stock_minimo) THEN
SET valido = 1;
ELSE
SET valido = -1;
END IF;
SELECT valido;
END
You have done the stored procedure correctly but I think you have not referenced the valido variable properly. I was looking at some examples and they have put an # symbol before the parameter like this #Valido
This statement SELECT valido; should be like this SELECT #valido;
Look at this link mysql stored-procedure: out parameter. Notice the solution with 7 upvotes. He has reference the parameter with an # sign, hence I suggested you add an # sign before your parameter valido
I hope that works for you. if it does vote up and mark it as the answer. If not, tell me.
Add:
DELIMITER at the beginning and end of the SP.
DROP PROCEDURE IF EXISTS validar_egreso; at the beginning
When calling the SP, use #variableName.
This works for me. (I modified some part of your script so ANYONE can run it with out having your tables).
DROP PROCEDURE IF EXISTS `validar_egreso`;
DELIMITER $$
CREATE DEFINER='root'#'localhost' PROCEDURE `validar_egreso` (
IN codigo_producto VARCHAR(100),
IN cantidad INT,
OUT valido INT(11)
)
BEGIN
DECLARE resta INT;
SET resta = 0;
SELECT (codigo_producto - cantidad) INTO resta;
IF(resta > 1) THEN
SET valido = 1;
ELSE
SET valido = -1;
END IF;
SELECT valido;
END $$
DELIMITER ;
-- execute the stored procedure
CALL validar_egreso(4, 1, #val);
-- display the result
select #val;
Update your SP and handle exception in it using declare handler with get diagnostics so that you will know if there is an exception.
e.g.
CREATE DEFINER=`root`#`localhost` PROCEDURE `validar_egreso`(
IN codigo_producto VARCHAR(100),
IN cantidad INT,
OUT valido INT(11)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
#p1 = RETURNED_SQLSTATE, #p2 = MESSAGE_TEXT;
SELECT #p1, #p2;
END
DECLARE resta INT(11);
SET resta = 0;
SELECT (s.stock - cantidad) INTO resta
FROM stock AS s
WHERE codigo_producto = s.codigo;
IF (resta > s.stock_minimo) THEN
SET valido = 1;
ELSE
SET valido = -1;
END IF;
SELECT valido;
END
I have written a stored procedure which enrols a student in a table. But before doing so, it checks weather the student is already present, if it does then no insertion takes place.
DELIMITER //
CREATE PROCEDURE test(IN sid varchar(6), IN us varchar(20), IN pswd varchar(20))
BEGIN
declare temp varchar(20);
declare x int;
declare y int;
set temp=(select username from login_student where s_id=sid);
IF(temp == NULL)
THEN insert into login_student values(sid, us, pswd);
ELSEIF (temp != NULL)
THEN set x=x+1; //have written it randomly
ELSE
set y=y+1; //have written it randomly
END IF;
END //
DELIMITER ;
login_student table schema is defined as:
CREATE TABLE login_student
(s_id varchar(6),
username varchar(20),
password varchar(20)
);
It's giving me some syntax error, can any one mark out the mistake please?
Two problems I see:
You need to use IS NULL and IS NOT NULL instead of == NULL and != NULL
You are using the wrong syntax for MySQL comments. Use -- not //
It should also be noted that you will never reach the ELSE in this case, since temp is either NULL or NOT NULL, so you could simplify it to an IF/ELSE if you want.
And I would recommend using SELECT ... INTO instead of SET to set the temp value.
Putting it all together:
DELIMITER //
DROP PROCEDURE IF EXISTS test //
CREATE PROCEDURE test(IN sid varchar(6), IN us varchar(20), IN pswd varchar(20))
BEGIN
declare temp varchar(20);
declare x int;
declare y int;
select username into temp from login_student where s_id=sid;
IF(temp IS NULL)
THEN insert into login_student values(sid, us, pswd);
ELSEIF (temp IS NOT NULL)
THEN set x=x+1; -- have written it randomly
ELSE
set y=y+1; -- have written it randomly
END IF;
END //
DELIMITER ;
Would be nice to get the text of an error, but I think it should be:
IF(temp IS NULL)
THEN insert into login_student values(sid, us, pswd);
ELSEIF (temp IS NOT NULL)
THEN set x=x+1; //have written it randomly
ELSE
set y=y+1; //have written it randomly
END IF;
I have a little problem. Looks like the procedure does not exist. Somehow it's dropped after the creation. I get different error each time i change something. I'm not really sure what's causing the error, maybe I'm not allowed to drop procedures and creating them in the same query.
I hope you guys can help me out.
drop procedure if exists refIntChk;
DELIMITER //
CREATE PROCEDURE refIntChk(IN district INT(11), OUT b INT(1))
BEGIN
DECLARE b INT(1);
IF district IN (select dist FROM t13)
THEN
SET b = 1;
ELSE
SET b = 0;
END IF;
END; //
DELIMITER ;
drop procedure gen if exists ;
DELIMITER //
CREATE PROCEDURE gen()
BEGIN
DECLARE rows INT(11) DEFAULT (SELECT COUNT(dist) FROM t13);
DECLARE district INT(11);
DECLARE custname VARCHAR(16);
DECLARE revenue FLOAT;
DECLARE x INT DEFAULT 10000;
DECLARE outvar INT(11);
WHILE x > 0
DO
SET district = FLOOR(RAND()*rows)+1;
CALL refIntChk(district, outvar);
IF outvar = 1
THEN
SET custname = substring(MD5(RAND()), -16);
SET revenue = (RAND() * 10);
INSERT INTO t14 VALUES(NULL, custname, district, revenue);
SET x = x - 1;
END IF;
END WHILE;
END;//
DELIMITER ;
CALL gen();
When you get errors, it's usually good to run each statement, one by one, and see which one is producing the error.
The second DROP procedure statement should be:
drop procedure if exists gen;