error procedure mysql db - mysql

I've created a procedure in my DB of a veterinary clinic that shows what is: the first date, the first time available with a veterinarian authorized to perform the service requested (there mustn't be other appointments booked at the same time). However when I call this procedure the cursor stops because the value of eof is 1, but it didn't really see all the records: the cursor leaves the loop before the end of rows! I can not understand why.
here is the code:
DELIMITER //
DROP PROCEDURE IF EXISTS first_booking_available //
CREATE PROCEDURE first_booking_available(IN Perf VARCHAR(30), IN DateP DATE)
BEGIN
DECLARE IdV, eof INTEGER;
DECLARE Dat DATE;
DECLARE i, TimeB, End TIME;
DECLARE vet CURSOR FOR E.Id_vet, W.Date, S.Start_time, S.End_time
FROM Enabled E, Work W, WorkShift S
WHERE E.Code_performance = Perf AND W.Id_vet = E.Id_vet AND S.Code = W.Code_workshift AND W.Date >= DateP ORDER BY W.Date, S.Start_time;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = 1;
SELECT Duration INTO #Duration FROM Perfomance WHERE Code = Perf;
SET #Start_time = NULL;
OPEN vet;
read_loop: LOOP
FETCH vet INTO IdV, Dat, TimeB, End;
IF (eof = 1 OR #Start_time IS NOT NULL) THEN
LEAVE read_loop;
END IF;
SET i = TimeB;
WHILE i < End AND #Start_time IS NULL DO
SET #P = NULL;
SET #F = NULL;
SELECT ADDTIME(ADDTIME(B.Start_time, P.Duration), '00:01:00') INTO #P
FROM Booking B, Performance P
WHERE P.Code = B.Code_performance AND B.Date = Dat AND B.Id_vet = IdV AND B.Start_time = i;
SELECT ADDTIME(ADDTIME(B.Start_time, P.Duration), '00:01:00') INTO #F
FROM Booking B, Performance P
WHERE P.Code = B.Code_performance AND B.Date = Dat AND B.Id_vet = IdV AND B.Start_time BETWEEN i AND ADDTIME(i, #Duration) ORDER BY ADDTIME(B.Start_time, P.Duration) DESC LIMIT 1;
IF #P IS NOT NULL THEN
SET i = #P;
END IF;
IF #F IS NOT NULL THEN
SET i = #F;
END IF;
IF ADDTIME(i, #duration) > End THEN
SET i = End;
END IF;
IF ((#P IS NULL) AND (#F IS NULL) AND (i != End)) THEN
SET #Start_Time = i;
END IF;
END WHILE;
IF #Start_Time IS NOT NULL THEN
SET #Id_vet = IdV;
SET #Date = Dat;
END IF;
END LOOP;
CLOSE vet;
IF #Start_Time IS NULL THEN
SIGNAL sqlstate '99994'
SET MESSAGE_TEXT = 'there is no availability !';
END IF;
END //
DELIMITER ;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = 1;
is mean your query has no result. It is not apply just cursor, another select query too.
SELECT ADDTIME(ADDTIME(B.Start_time, P.Duration), '00:01:00') INTO #P
FROM Booking B, Performance P
WHERE P.Code = B.Code_performance AND B.Date = Dat AND B.Id_vet = IdV AND B.Start_time = i;
SELECT ADDTIME(ADDTIME(B.Start_time, P.Duration), '00:01:00') INTO #F
FROM Booking B, Performance P
WHERE P.Code = B.Code_performance AND B.Date = Dat AND B.Id_vet = IdV AND B.Start_time BETWEEN i AND ADDTIME(i, #Duration) ORDER BY ADDTIME(B.Start_time, P.Duration) DESC LIMIT 1;
this query has no result. HANDLER catch them. and leave cursor.

Related

Want to return data set from this cursor ,stored procedure

i am working on this stored procedure , can any body please help me to get data set from this procedure .
*Create a stored procedure with a variable entry called list_g
This is the procedure (see attached):
and then:
*=at
SET *list = "";
CALL getNodes(*list);
select *list;
Here is the Stored Procedure :
BEGIN
DECLARE done1, done2 BOOLEAN DEFAULT FALSE;
DECLARE row1 varchar(900) default "";
DECLARE parentId INTEGER;
DECLARE cur1 CURSOR FOR SELECT idIncidence FROM incidence
WHERE DATE(dateTimeIn_dt)='2018-01-18' and hour(TIME(dateTimeIn_dt))
BETWEEN '08' and '15';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = TRUE;
open cur1;
loop1: LOOP
FETCH cur1 INTO parentId;
IF done1 THEN
CLOSE cur1;
LEAVE loop1;
END IF;
set list_g=CONCAT(parentId,";",list_g);
BLOCK1 : BEGIN
DECLARE cur2 CURSOR FOR SELECT
a.idIncidence,DATE_FORMAT(dateTimeIn_dt,'%H:%i:%s') as dateTimeIn_dt,0
as conteo, a.classification_str,measure_n,a.keyNode_str_fk,(
SELECT GROUP_CONCAT( nameStation_str SEPARATOR ', ') AS
idStation
FROM (
SELECT nameStation_str,
( 6371 * acos(cos(radians((SELECT lat from incidence where
idIncidence =#parentId))) * cos(radians(lat_str)) *
cos(radians(lon_str) - radians((SELECT lon from incidence where
idIncidence =#parentId))) + sin(radians((SELECT lat from incidence
where idIncidence =#parentId))) * sin(radians(lat_str))) )
AS distance
FROM station HAVING distance < 0.01 ORDER BY distance
) as s
)as
idStation_fk,kp.kindProtective_str,m.nameModel_str
,pa.keyArea_n,kp.idKinProtector FROM incidence a
JOIN node n on a.keyNode_str_fk=n.keyNode_str
JOIN protective pr on n.idProtective_fk=pr.idProtective
JOIN kindProtector kp on pr.idKindProtector_fk=kp.idKinProtector
JOIN model m on pr.idModel_fk=m.idModel
JOIN station st on a.idStation_fk =st.idStation
JOIN branch br on st.idBranch_fk=br.idBranch
JOIN ship sh on br.idShip_fk=sh.idShip
JOIN protectiveArea pa on n.idProtectiveArea=pa.idProtectiveArea
WHERE DATE(dateTimeIn_dt)='2018-01-18' and
hour(TIME(dateTimeIn_dt)) BETWEEN '08' and '15';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = TRUE;
OPEN cur2;
loop2 : LOOP
if done2 THEN
CLOSE cur2;
SET done2 = FALSE;
LEAVE loop2;
END IF;
END LOOP loop2;
END BLOCK1;
END loop loop1;
END
i need to return all the data set from the query
Please help me in this problem. Here are my Tables Name :
Branch , brand ,group_node ,incidence ,kindProtector,model,node,plant,protective,protectiveArea,protectiveGroup,sensor,shift,ship,station,user .

What does "The following query failed" ";"" mean in MySQL?

While trying to update a trigger, MySQL tells me the query ";" failed. How is ";" even a query in MySQL's view is beyond me.
The exact message is:
The following query has failed: ";" MySQL said: #1065 - Query was empty
Here's the new trigger (AFTER INSERT):
BEGIN
DECLARE vIdPlacet VARCHAR(40);
DECLARE vTypeTravaux VARCHAR(32);
DECLARE vEssence VARCHAR(3) DEFAULT '-';
DECLARE vClasseHau VARCHAR(5) DEFAULT '-';
DECLARE vNoMesurag int;
DECLARE new_id_parcelle INT UNSIGNED DEFAULT 0;
DECLARE new_no_microplacette INT UNSIGNED DEFAULT 0;
IF NEW.deleted = 0 THEN
SELECT id_parcelle, no_microplacette
INTO new_id_parcelle, new_no_microplacette
FROM microplacette
WHERE id_microplacette = NEW.id_microplacette;
SELECT travaux, no_mesurag, id__placet
INTO vTypeTravaux, vNoMesurag, vIdPlacet
FROM secteur
LEFT JOIN parcelle ON secteur.id_secteur = parcelle.id_secteur
WHERE id_parcelle = new_id_parcelle;
IF vTypeTravaux = 'inventaire' THEN
SELECT abbreviation INTO vEssence FROM essences WHERE _id = NEW.id_essence;
IF NEW.hauteur_15 = 1 THEN
SET vClasseHau = '15CM+';
END IF;
IF (SELECT COUNT(*) FROM imported_pres_ess WHERE id__placet = vIdPlacet AND
caracteris = '-' AND
classe_hau = vClasseHau AND
essence = vEssence AND
no_mesurag = vNoMesurag AND
no_micro_p = new_no_microplacette) = 0 THEN
INSERT INTO imported_pres_ess (id__placet, caracteris, classe_hau, essence, no_mesurag, no_micro_p)
VALUES (vIdPlacet, '-', vClasseHau, vEssence, vNoMesurag, new_no_microplacette);
END IF;
IF (SELECT COUNT(*) FROM imported_semi_gau WHERE id__placet = vIdPlacet AND
classe_hau = vClasseHau AND
essence = vEssence AND
no_mesurag = vNoMesurag AND
no_micro_p = new_no_microplacette) = 0 THEN
INSERT INTO imported_semi_gau (id__placet, classe_hau, essence, no_mesurag, no_micro_p)
VALUES (vIdPlacet, vClasseHau, vEssence, vNoMesurag, new_no_microplacette);
END IF;
IF NEW.diametre > 0 THEN
SET vClasseHau = 'D2_D8';
ELSE
SET vClasseHau = '-';
END IF;
IF (SELECT COUNT(*) FROM imported_pres_ess WHERE id__placet = vIdPlacet AND
caracteris = '-' AND
classe_hau = vClasseHau AND
essence = vEssence AND
no_mesurag = vNoMesurag AND
no_micro_p = new_no_microplacette) = 0 THEN
INSERT INTO imported_pres_ess (id__placet, caracteris, classe_hau, essence, no_mesurag, no_micro_p)
VALUES (vIdPlacet, '-', vClasseHau, vEssence, vNoMesurag, new_no_microplacette);
END IF;
IF (SELECT COUNT(*) FROM imported_semi_gau WHERE id__placet = vIdPlacet AND
classe_hau = vClasseHau AND
essence = vEssence AND
no_mesurag = vNoMesurag AND
no_micro_p = new_no_microplacette) = 0 THEN
INSERT INTO imported_semi_gau (id__placet, classe_hau, essence, no_mesurag, no_micro_p)
VALUES (vIdPlacet, vClasseHau, vEssence, vNoMesurag, new_no_microplacette);
END IF;
END IF;
END IF;
END
I tried creating the procedure you show, but I don't get any error.
The error about "empty statement" happens when you try to execute a query through the API but the query string is empty.
I can duplicate the error in the mysql client this way:
mysql> set #s = '';
mysql> prepare stmt from #s;
ERROR 1065 (42000): Query was empty
So I suggest you look not at the stored procedure, but whatever code you're executing this from, and check that every time you try to execute a query, that you submit a non-empty string.
It turns out, the trigger I was updating got deleted in the meantime, so I was updating a trigger that didn't exist anymore.
I found out after refreshing the page (the trigger was gone from the trigger list).
I simply recreated the trigger anew and it worked.

MySQL: Procedure Loops, but only inserts once

CREATE DEFINER=`root`#`localhost` PROCEDURE `GenerateCharges2`()
BEGIN
Declare sumFunding LONG;
Declare done INT DEFAULT FALSE;
Declare invoiceCharge LONG;
Declare agencyID INT;
declare invoiceID int;
Declare fundingID INT;
Declare amountOfFunding LONG;
Declare getInvoiceData CURSOR For select invoices.idInvoices, invoices.idAgencies, invoices.InvoiceAmount, fundings.FundingBalance, fundings.idfundings from invoices
inner join agencies on invoices.idAgencies = agencies.idAgencies
inner join fundings on agencies.idAgencies = fundings.IdAgencies
where processed =0
group by invoices.idInvoices;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
open getInvoicedata;
ze_loop: Loop
Fetch getInvoiceData into invoiceID, agencyID, invoiceCharge, amountOfFunding, fundingID;
if done then leave ze_loop;
end if;
if amountOfFunding > invoiceCharge then
insert into charges VALUES (invoiceCharge, invoiceID, fundingID);
end if;
end loop;
close getInvoiceData;
END
My issue is that if you were to insert a select statement, it runs a proper amont of times. However, the insert statement only inserts once with sample data. In every case, amnountOfFunding is ALWAYS greater than invoiceCharge. Desired results is to have all inserts happen for rows fetched.
I have this loop and insert every record that i need! Maybe you can modifiy or update yours loop with that!
DECLARE done INT DEFAULT FALSE ;
DECLARE l_local_formato_retail_codigo,
l_producto_sku,
l_producto_descripcion_sra,
l_producto_marca,
l_producto_categoria VARCHAR (100) ;
DECLARE l_precio DECIMAL (20, 7) DEFAULT 0 ;
DECLARE l_un_1 INT (20) DEFAULT 0 ;
DECLARE l_un_2 INT (20) DEFAULT 0 ;
DECLARE l_clp_1 DECIMAL (20, 7) DEFAULT 0 ;
DECLARE l_clp_2 DECIMAL (20, 7) DEFAULT 0 ;
DECLARE contador INT DEFAULT 0 ;
DECLARE valores CURSOR FOR
SELECT
local_formato_retail_codigo,
producto_sku,
producto_descripcion_sra,
producto_marca,
producto_categoria
FROM
base_comercial
WHERE mes_fecha = fecha
GROUP BY producto_sku,
local_formato_retail_codigo
ORDER BY local_formato_retail_codigo ASC,
producto_sku ASC ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE ;
TRUNCATE precio_cd ;
OPEN valores ;
read_loop :
LOOP
FETCH valores INTO l_local_formato_retail_codigo,
l_producto_sku,
l_producto_descripcion_sra,
l_producto_marca,
l_producto_categoria ;
IF done
THEN LEAVE read_loop ;
END IF ;
SET l_clp_1 =
(SELECT
ROUND(SUM(sellout_clp), 7)
FROM
base_comercial
WHERE anno = DATE_FORMAT(fecha, '%Y')
AND mes = DATE_FORMAT(fecha, '%c')
AND local_formato_retail_codigo = l_local_formato_retail_codigo
AND producto_sku = l_producto_sku) ;
SET l_clp_2 =
(SELECT
ROUND(SUM(sellout_clp), 7)
FROM
base_comercial
WHERE anno = DATE_FORMAT(
DATE_ADD(fecha, INTERVAL - 1 MONTH),
'%Y'
)
AND mes = DATE_FORMAT(
DATE_ADD(fecha, INTERVAL - 1 MONTH),
'%c'
)
AND local_formato_retail_codigo = l_local_formato_retail_codigo
AND producto_sku = l_producto_sku) ;
SET l_un_1 =
(SELECT
SUM(sellout_un)
FROM
base_comercial
WHERE anno = DATE_FORMAT(fecha, '%Y')
AND mes = DATE_FORMAT(fecha, '%c')
AND local_formato_retail_codigo = l_local_formato_retail_codigo
AND producto_sku = l_producto_sku) ;
SET l_un_2 =
(SELECT
SUM(sellout_un)
FROM
base_comercial
WHERE anno = DATE_FORMAT(
DATE_ADD(fecha, INTERVAL - 1 MONTH),
'%Y'
)
AND mes = DATE_FORMAT(
DATE_ADD(fecha, INTERVAL - 1 MONTH),
'%c'
)
AND local_formato_retail_codigo = l_local_formato_retail_codigo
AND producto_sku = l_producto_sku) ;
IF (ISNULL(l_clp_1))
THEN SET l_clp_1 = 0 ;
END IF ;
IF (ISNULL(l_clp_2))
THEN SET l_clp_2 = 0 ;
END IF ;
IF (ISNULL(l_un_1))
THEN SET l_un_1 = 0 ;
END IF ;
IF (ISNULL(l_un_2))
THEN SET l_un_2 = 0 ;
END IF ;
SET l_precio = ((l_clp_1 + l_clp_2) / (l_un_1 + l_un_2)) ;
IF (ISNULL(l_precio))
THEN SET l_precio = 0 ;
END IF ;
INSERT INTO precio_cd
VALUES
(
l_local_formato_retail_codigo,
l_producto_sku,
l_producto_descripcion_sra,
l_producto_marca,
l_producto_categoria,
l_precio
) ;
END LOOP read_loop ;
CLOSE valores ;
SELECT
*
FROM
precio_cd ;

mysql stored procedure error (1172, 'Result consisted of more than one row')

When trying to run the following stored procedure from django, I get an OperationError (1172, 'Result consisted of more than one row') Any idea what I might be doing wrong?
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `UpdatePrices`(IN storeId int, IN bottleSize VARCHAR(50))
BEGIN
DECLARE amount DECIMAL(10,2); DECLARE isCustom INT DEFAULT 0;
DECLARE changeType VARCHAR(50) DEFAULT 'State'; DECLARE updateType INT DEFAULT 0;
IF bottleSize = '1000 Ml' THEN
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId;
IF changeType = 'State' THEN
SELECT updateType = 0;
END IF;
IF changeType = 'Flat' THEN
SELECT S1000IncreaseAmount INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 1;
END IF;
IF changeType = 'Percent' THEN
SELECT 1 - S1000IncreaseAmount/100 INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 2;
END IF;
END IF;
IF updateType = 0 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = ShelfPrice
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice + amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice / amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
END
I'm not sure if it matters, but I initiate the stored procedure like so:
def priceupdate(request, store_id):
cursor = connection.cursor()
cursor.callproc("UpdatePrices", (store_id, '1000 ML'))
cursor.close()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
Your SELECT...INTO queries give result sets with more then one record. The WHERE filters are incorrect - they compare two the same values StoreID = storeId. Rename IN storeId int parementer to another name. For example - IN storeId_param int
The query will be like this -
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId_param;
This is a Bug and you need to apply something like that:
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

Mysql Function - not sure where to start

I would like to write a function in Mysql that from a given product code return a formatted string
Here is an example of the calls I need to manually make now to get the result I want.
SELECT p.productcategoryid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code='T29R66N1';
T29R66NQ is the product code I need the full path for - the above call returns '38' as the category ID.
I then perform the following select based on the result from above
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '38';
This returns
name->Built-In Hobs
parentid->7
productcategorypath=222,7,38
Using that result I then
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '7';
giving me
name->Built-In
parentid->222
productcategorypath=222,7
and again, I then do
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '222';
which in turn gives me
name->Kitchen & Home Appliances
parentid->0
productcategorypath=222
I stop there because parentid = 0 (it may go on for more iterations but will always end with parent id of 0) but i need the results from the last 3 selects to give me the following string
Kitchen & Home Appliances > Built-In > Built-In Hobs
I would like a mysql function whereby I can use it like
select getpath(code) from products where code='T29R66N1'
Any help would be appreciated.
EDIT:
I managed to figure it myself - here is my function
DROP FUNCTION IF EXISTS mydb.getpath;
CREATE FUNCTION mydb.getpath (itemid VARCHAR(20))
RETURNS varchar(255)
BEGIN
DECLARE path_name varchar(255);
DECLARE tmp_name varchar(255);
DECLARE tmp_parentid INT;
DECLARE tmp_parentid1 INT;
SELECT p.productcategoryid INTO tmp_parentid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code=itemid;
myloop:LOOP
SELECT name,parentid INTO tmp_name,tmp_parentid1 FROM productcategory WHERE recid = tmp_parentid;
SET path_name = concat_ws(' > ', tmp_name,path_name);
IF tmp_parentid1!=0 THEN
SET tmp_parentid = tmp_parentid1;
ITERATE myloop;
ELSE
LEAVE myloop;
END IF;
END LOOP;
RETURN path_name;
END;
DROP FUNCTION IF EXISTS mydb.getpath;
CREATE FUNCTION mydb.getpath (itemid VARCHAR(20))
RETURNS varchar(255)
BEGIN
DECLARE path_name varchar(255);
DECLARE tmp_name varchar(255);
DECLARE tmp_parentid INT;
DECLARE tmp_parentid1 INT;
SELECT p.productcategoryid INTO tmp_parentid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code=itemid;
myloop:LOOP
SELECT name,parentid INTO tmp_name,tmp_parentid1 FROM productcategory WHERE recid = tmp_parentid;
SET path_name = concat_ws(' > ', tmp_name,path_name);
IF tmp_parentid1!=0 THEN
SET tmp_parentid = tmp_parentid1;
ITERATE myloop;
ELSE
LEAVE myloop;
END IF;
END LOOP;
RETURN path_name;
END;