I am trying to create this procedure but there is an error that I cannot solved. It gives me
error 1193 Unknown system variable p_salida.
I have looked at other topics here, but I find nothing that is useful to me.
Thanks!
bloque: BEGIN
-- PK / UK
DECLARE EXIT HANDLER FOR 1062
BEGIN
ROLLBACK;
SET p_salida=-5;
END;
-- FK
DECLARE EXIT HANDLER FOR 1452
BEGIN
ROLLBACK;
SET p_salida=-6;
END;
DECLARE v_Direccion int;
DECLARE v_CodUsuario int;
If not EXISTS (SELECT * From usuarios where Nombre = p_nombre and Apellido
= p_Apellido and Correo = p_correo and Contrasena=p_contrasena) THEN
-- SET p_salida = -1;
LEAVE bloque;
END IF;
SELECT codDireccion into v_Direccion
From direcciones
Order by codDireccion
DESC LIMIT 1;
SET v_Direccion = v_Direccion + 1;
SELECT codUsuario into v_CodUsuario
From usuarios
Order by codusuario
DESC LIMIT 1;
SET v_CodUsuario = v_CodUsuario + 1;
START TRANSACTION;
INSERT Into direcciones (CodDireccion, CodigoPostal, Domicilio, Localidad,
Provincia)
VALUES (v_Direccion, p_CodPostal,
p_Domicilio,p_Localidad,p_Provincia);
INSERT into Usuarios (Apellido, CodUsuario, Contrasena, Correo,
Direccion,FechaNacimiento, nombre)
VALUES (p_Apellido, v_CodUsuario, p_Contrasena, p_Correo, v_Direccion,
p_FechaNacimiento,p_nombre);
COMMIT;
SET p_salida = 1;
END bloque
You have to declare your variable before you can use it. Something like this, placed just after your begin statement (or at least some time before you try to use the variable):
DECLARE p_salida INT DEFAULT 1;
Documentation: https://dev.mysql.com/doc/refman/8.0/en/declare-local-variable.html
Related
Actually I'm trying to insert some data into a table using a cursor, and I'm getting no error. It just says:
Query executed OK, 0 rows affected.
I'm trying to get data from each field of the testdatabase.wp_posts p table and insert it into an existing table `testdatabase.wp_postmeta.
My syntax is:
DROP PROCEDURE IF EXISTS add_authors_to_prod;
DELIMITER $$
CREATE PROCEDURE add_authors_to_prod()
BEGIN
DECLARE v_post_id INT;
DECLARE v_author_id INT;
DECLARE v_last_author INT DEFAULT 0;
DECLARE str VARCHAR(500);
DECLARE v_first_id INT DEFAULT 10916;
DECLARE author_csr CURSOR FOR
SELECT n.nid, p.id FROM testdatabase.wp_posts p
JOIN drupaltest.srmaif_field_data_field_auther_list auth ON auth.entity_id = p.id
JOIN drupaltest.node_field_data n ON auth.field_auther_list_nid = n.nid
ORDER BY p.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_last_author = 1;
START TRANSACTION;
OPEN author_csr;
author_loop:LOOP
FETCH author_csr INTO v_author_id, v_post_id;
IF v_last_author THEN
SET str = CONCAT(str, '}');
LEAVE author_loop;
END IF;
IF v_first_id <> v_post_id THEN
SET v_first_id = v_post_id;
SET str = CONCAT(str, '}');
INSERT INTO testdatabase.wp_postmeta (post_id, meta_key, meta_value)
VALUES(v_post_id, 'authors', CONCAT(str, v_author_id));
SET str = 'a:2:{';
ELSE
SET str = CONCAT(str,'i:', v_author_id, ';s:5:\"', v_author_id, '\";');
END IF;
END LOOP author_loop;
CLOSE author_csr;
SET v_last_author=0;
END$$
DELIMITER ;
CALL add_authors_to_prod()
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
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 am making a procedure that inserts a place ("Sted") and I would like to check if the inputs are NULL. However, whenever I try to add an if-statement at the start to surround my code (marked CRASH below), it gives me an error saying my syntax is not right at "DECLARE varStedskodeID INT;" which is the part after the IF-statement I'm trying to add.
To my eyes the syntax of my if-statement is the same inside the code, but only my soon-to-be-NULL-check if-statement crashes even with just a simple IF(TRUE) THEN.
Can anyone give me a hint of what causes this one if to crash?
DROP PROCEDURE IF EXISTS InsertSted;
DELIMITER $$
CREATE PROCEDURE InsertSted(
IN inputStedsnavn VARCHAR(255),
IN inputStedstype VARCHAR(255),
IN inputKommunenavn VARCHAR(255))
BEGIN
IF(TRUE) THEN <<------ CRASH
DECLARE varStedskodeID INT;
DECLARE varKommunenr INT;
IF(SELECT COUNT(StedkodeID) FROM stedstype WHERE Kodenavn = inputStedstype LIMIT 1) = 0 THEN
INSERT INTO stedstype VALUES(DEFAULT, inputStedstype);
END IF;
SET varStedskodeID = (SELECT StedkodeID FROM stedstype WHERE Kodenavn = inputStedstype LIMIT 1);
IF(SELECT COUNT(Kommunenr) FROM kommune WHERE Kommunenavn = inputKommunenavn LIMIT 1) = 1 THEN
SET varKommunenr = (SELECT Kommunenr FROM kommune WHERE Kommunenavn = inputKommunenavn LIMIT 1);
INSERT INTO sted VALUES(DEFAULT, inputStedsnavn, varStedskodeID, varKommunenr);
END IF;
END IF; <<------ CRASH
END$$
DELIMITER ;
DECLARE is permitted only inside a BEGIN ... END compound statement
and must be at its start, before any other statements.
http://dev.mysql.com/doc/refman/5.0/en/declare.html
MySQL follows strict rules for DECLARE. You have to DECLARE variables, tables, etc... at the beginning of Stored Procedure.
Change Stored Procedure like this
DECLARE varStedskodeID INT;
DECLARE varKommunenr INT;
IF(TRUE) THEN
IF(SELECT COUNT(StedkodeID) FROM stedstype WHERE Kodenavn = inputStedstype LIMIT 1) = 0 THEN
INSERT INTO stedstype VALUES(DEFAULT, inputStedstype);
END IF;
SET varStedskodeID = (SELECT StedkodeID FROM stedstype WHERE Kodenavn = inputStedstype LIMIT 1);
IF(SELECT COUNT(Kommunenr) FROM kommune WHERE Kommunenavn = inputKommunenavn LIMIT 1) = 1 THEN
SET varKommunenr = (SELECT Kommunenr FROM kommune WHERE Kommunenavn = inputKommunenavn LIMIT 1);
INSERT INTO sted VALUES(DEFAULT, inputStedsnavn, varStedskodeID, varKommunenr);
END IF;
END IF;
I have a table for categories with "order" column for ordering the categories.
I'm trying to set order incrementally in trigger before insert:
CREATE TRIGGER `categories_set_order` BEFORE INSERT ON `categories` FOR EACH ROW BEGIN
DECLARE max_order INT DEFAULT 0;
SELECT MAX(categories.order) INTO max_order FROM categories;
SET NEW.order = max_order + 1;
END;
But if there are no records in the db, order column is being set to NULL.
I've modified the trigger code:
CREATE TRIGGER `categories_set_order` BEFORE INSERT ON `categories` FOR EACH ROW BEGIN
DECLARE max_order INT DEFAULT 0;
SELECT MAX(categories.order) INTO max_order FROM categories;
IF (ISNULL(#max_order)) THEN BEGIN
SET max_order = 0;
END;
SET NEW.order = max_order + 1;
END;
And I'm getting the following error:
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 9
Line 9 is:
IF (ISNULL(#max_order)) THEN BEGIN
I've tried to remove the "#", but still getting the same error. How to fix it?
You need to change the delimiter. Otherwise the DB thinks your trigger definition ends at the first ; which would be incomplete.
Also remove the BEGIN from your IF statement and add use END IF to end your IF
delimiter |
CREATE TRIGGER `categories_set_order` BEFORE INSERT ON `categories`
FOR EACH ROW BEGIN
DECLARE max_order INT DEFAULT 0;
SELECT MAX(categories.order) INTO max_order FROM categories;
IF (ISNULL(#max_order)) THEN
SET max_order = 0;
END IF;
SET NEW.order = max_order + 1;
END
|
delimiter ;
Besides delimiter you need an END IF
DELIMITER //
CREATE TRIGGER `categories_set_order` BEFORE INSERT ON `categories` FOR EACH ROW BEGIN
DECLARE max_order INT DEFAULT 0;
SELECT MAX(categories.order) INTO max_order FROM categories;
IF (ISNULL(#max_order)) THEN
SET max_order = 0;
END IF;
SET NEW.order = max_order + 1;
END; //
DELIMITER ;