Related
There is probably something simple here that I'm just not seeing, but I've been trying all I can think of for a few hours. It's time to toss it to more knowledgable folks...
I want to attempt to intercept a duplicate index, so my auto increment value doesn't advance. Plus, after this much time, it has just become one of those things I have to solve at this point.
Starting with an empty table, I call the procedure with PricingHeaderID_In set to zero in order to invoke the INSERT logic.
Lookup1 obviously finds nothing, because there is nothing to find, and pricingHeaderID1 is NULL. Then, the new row is inserted, Lookup2 retrieves the newly inserted row as expected, and pricingHeaderID2 shows the correct value.
Now, I call the procedure with EXACTLY the same values everywhere, Lookup1 still finds nothing, and pricingHeaderID1 is NULL. That causes the insert logic to run, and MySQL correctly detects a duplicate.
My question is simple: If MySQL can detect that the values will cause a duplicate key, then why is Lookup1 failing?
Here's my table definition:
CREATE TABLE PricingHeaders (
PricingHeaderID bigint NOT NULL AUTO_INCREMENT,
UserID bigint NOT NULL,
ClientName varchar(100) NOT NULL,
Subdivision varchar(100) NOT NULL,
SubjectProperty varchar(100) NOT NULL,
DatePrepared date NOT NULL,
MonthsSearched smallint DEFAULT NULL,
Bedrooms tinyint DEFAULT NULL,
Bathrooms tinyint DEFAULT NULL,
Stories tinyint DEFAULT NULL,
SquareFeet smallint DEFAULT NULL,
YearBuilt smallint DEFAULT NULL,
HasPool bit DEFAULT 0,
Created datetime DEFAULT CURRENT_TIMESTAMP,
Modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (PricingHeaderID),
UNIQUE KEY UserClientPropertyDate (UserID,ClientName,SubjectProperty,DatePrepared),
INDEX UserSubdivision (UserID,Subdivision)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
And here's my stored procedure:
CREATE PROCEDURE SavePricingHeader ( Token_In VARCHAR(36),
PricingHeaderID_In bigint,
UserID_In bigint,
ClientName_In varchar(100),
Subdivision_In varchar(100),
SubjectProperty_In varchar(100),
DatePrepared_In date,
MonthsSearched_In smallint,
Bedrooms_In tinyint,
Bathrooms_In tinyint,
Stories_In tinyint,
SquareFeet_In smallint,
YearBuilt_In smallint,
HasPool_In bit )
BEGIN
DECLARE errNo int DEFAULT 0;
DECLARE errMsg varchar(250) DEFAULT 'OK';
DECLARE currOp varchar(250) DEFAULT 'Init';
DECLARE pricingHeaderID1 bigint DEFAULT NULL;
DECLARE pricingHeaderID2 bigint DEFAULT NULL;
DECLARE tokenValidated bit DEFAULT 0;
DECLARE sqlErrNo CHAR(5) DEFAULT '00000';
DECLARE sqlErrMsg TEXT DEFAULT '';
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 sqlErrNo = RETURNED_SQLSTATE, sqlErrMsg = MESSAGE_TEXT;
SET errNo = 1;
SET errMsg = 'SQL Error';
END;
IF errNo = 0 THEN
SET currOp = 'Extend session';
CALL ExtendSession(Token_In, tokenValidated);
END IF;
IF errNo = 0 THEN
IF tokenValidated = 0 THEN
SET errNo = 9001;
SET errMsg = 'Invalid session.';
END IF;
END IF;
IF errNo = 0 THEN
SET currOp = 'Lookup1';
SELECT `PricingHeaderID` INTO pricingHeaderID1 FROM `PricingHeaders`
WHERE `UserID` = UserID_In
AND `ClientName` = ClientName_In
AND `SubjectProperty` = SubjectProperty_In
AND `DatePrepared` = DatePrepared_In;
IF errNo = 0 THEN
IF pricingHeaderID1 IS NOT NULL THEN
IF pricingHeaderID1 <> PricingHeaderID_In THEN
SET errNo = 9002;
SET errMsg = 'Duplicate Index.';
END IF;
END IF;
END IF;
END IF;
IF errNo = 0 THEN
IF PricingHeaderID_In = 0 THEN
SET currOp = 'Insert';
INSERT INTO `PricingHeaders` (
`UserID`,
`ClientName`,
`Subdivision`,
`SubjectProperty`,
`DatePrepared`,
`MonthsSearched`,
`Bedrooms`,
`Bathrooms`,
`Stories`,
`SquareFeet`,
`YearBuilt`,
`HasPool`
) VALUES (
UserID_In,
ClientName_In,
Subdivision_In,
SubjectProperty_In,
DatePrepared_In,
MonthsSearched_In,
Bedrooms_In,
Bathrooms_In,
Stories_In,
SquareFeet_In,
YearBuilt_In,
HasPool_In
);
IF errNo = 0 THEN
SET pricingHeaderID1 = LAST_INSERT_ID();
END IF;
ELSE
SET currOp = 'Update';
SET pricingHeaderID1 = PricingHeaderID_In;
UPDATE `PricingHeaders` SET
`ClientName` = ClientName_In,
`Subdivision` = Subdivision_In,
`SubjectProperty` = SubjectProperty_In,
`DatePrepared` = DatePrepared_In,
`MonthsSearched` = MonthsSearched_In,
`Bedrooms` = Bedrooms_In,
`Bathrooms` = Bathrooms_In,
`Stories` = Stories_In,
`SquareFeet` = SquareFeet_In,
`YearBuilt` = YearBuilt_In,
`HasPool` = HasPool_In
WHERE `PricingHeaderID` = PricingHeaderID_In;
END IF;
END IF;
IF errNo = 0 THEN
SET currOp = 'Lookup2';
SELECT `PricingHeaderID` INTO pricingHeaderID2 FROM `PricingHeaders`
WHERE `UserID` = UserID_In
AND `ClientName` = ClientName_In
AND `SubjectProperty` = SubjectProperty_In
AND `DatePrepared` = DatePrepared_In;
END IF;
IF errNo = 0 THEN
IF pricingHeaderID2 IS NULL THEN
SET errNo = 9003;
SET errMsg = 'Not retrieved.';
END IF;
END IF;
SELECT pricingHeaderID1, pricingHeaderID2, errNo, errMsg, currOp, sqlErrNo, sqlErrMsg;
END
Your basic problem is your call to the second procedure,
which must look like
CALL ExtendSession(Token_In, #tokenValidated)
Whe4n you want to retrieve an OUT variable in MySQL#
CREATE TABLE PricingHeaders (
PricingHeaderID bigint NOT NULL AUTO_INCREMENT,
UserID bigint NOT NULL,
ClientName varchar(100) NOT NULL,
Subdivision varchar(100) NOT NULL,
SubjectProperty varchar(100) NOT NULL,
DatePrepared date NOT NULL,
MonthsSearched smallint DEFAULT NULL,
Bedrooms tinyint DEFAULT NULL,
Bathrooms tinyint DEFAULT NULL,
Stories tinyint DEFAULT NULL,
SquareFeet smallint DEFAULT NULL,
YearBuilt smallint DEFAULT NULL,
HasPool bit DEFAULT 0,
Created datetime DEFAULT CURRENT_TIMESTAMP,
Modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (PricingHeaderID),
UNIQUE KEY UserClientPropertyDate (UserID,ClientName,SubjectProperty,DatePrepared),
INDEX UserSubdivision (UserID,Subdivision)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
CREATE PROCEDURE ExtendSession(IN Token_In VARCHAR(36), OUT tokenValidated int)
BEGIN
SET tokenValidated = 1;
END;
✓
CREATE PROCEDURE SavePricingHeader ( Token_In VARCHAR(36),
PricingHeaderID_In bigint,
UserID_In bigint,
ClientName_In varchar(100),
Subdivision_In varchar(100),
SubjectProperty_In varchar(100),
DatePrepared_In date,
MonthsSearched_In smallint,
Bedrooms_In tinyint,
Bathrooms_In tinyint,
Stories_In tinyint,
SquareFeet_In smallint,
YearBuilt_In smallint,
HasPool_In bit )
BEGIN
DECLARE errNo int DEFAULT 0;
DECLARE errMsg varchar(250) DEFAULT 'OK';
DECLARE currOp varchar(250) DEFAULT 'Init';
DECLARE pricingHeaderID1 bigint DEFAULT NULL;
DECLARE pricingHeaderID2 bigint DEFAULT NULL;
DECLARE tokenValidated bit DEFAULT 0;
DECLARE sqlErrNo CHAR(5) DEFAULT '00000';
DECLARE sqlErrMsg TEXT DEFAULT '';
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 sqlErrNo = RETURNED_SQLSTATE, sqlErrMsg = MESSAGE_TEXT;
SET errNo = 1;
SET errMsg = 'SQL Error';
END;
IF errNo = 0 THEN
SET currOp = 'Extend session';
CALL ExtendSession(Token_In, #tokenValidated);
END IF;
IF errNo = 0 THEN
IF #tokenValidated = 0 THEN
SET errNo = 9001;
SET errMsg = 'Invalid session.';
END IF;
END IF;
IF errNo = 0 THEN
SET currOp = 'Lookup1';
SELECT `PricingHeaderID` INTO pricingHeaderID1 FROM `PricingHeaders`
WHERE `UserID` = UserID_In
AND `ClientName` = ClientName_In
AND `SubjectProperty` = SubjectProperty_In
AND `DatePrepared` = DatePrepared_In;
IF errNo = 0 THEN
IF pricingHeaderID1 IS NOT NULL THEN
IF pricingHeaderID1 <> PricingHeaderID_In THEN
SET errNo = 9002;
SET errMsg = 'Duplicate Index.';
END IF;
END IF;
END IF;
END IF;
IF errNo = 0 THEN
IF PricingHeaderID_In = 0 THEN
SET currOp = 'Insert';
INSERT INTO `PricingHeaders` (
`UserID`,
`ClientName`,
`Subdivision`,
`SubjectProperty`,
`DatePrepared`,
`MonthsSearched`,
`Bedrooms`,
`Bathrooms`,
`Stories`,
`SquareFeet`,
`YearBuilt`,
`HasPool`
) VALUES (
UserID_In,
ClientName_In,
Subdivision_In,
SubjectProperty_In,
DatePrepared_In,
MonthsSearched_In,
Bedrooms_In,
Bathrooms_In,
Stories_In,
SquareFeet_In,
YearBuilt_In,
HasPool_In
);
IF errNo = 0 THEN
SET pricingHeaderID1 = LAST_INSERT_ID();
END IF;
ELSE
SET currOp = 'Update';
SET pricingHeaderID1 = PricingHeaderID_In;
UPDATE `PricingHeaders` SET
`ClientName` = ClientName_In,
`Subdivision` = Subdivision_In,
`SubjectProperty` = SubjectProperty_In,
`DatePrepared` = DatePrepared_In,
`MonthsSearched` = MonthsSearched_In,
`Bedrooms` = Bedrooms_In,
`Bathrooms` = Bathrooms_In,
`Stories` = Stories_In,
`SquareFeet` = SquareFeet_In,
`YearBuilt` = YearBuilt_In,
`HasPool` = HasPool_In
WHERE `PricingHeaderID` = PricingHeaderID_In;
END IF;
END IF;
IF errNo = 0 THEN
SET currOp = 'Lookup2';
SELECT `PricingHeaderID` INTO pricingHeaderID2 FROM `PricingHeaders`
WHERE `UserID` = UserID_In
AND `ClientName` = ClientName_In
AND `SubjectProperty` = SubjectProperty_In
AND `DatePrepared` = DatePrepared_In;
END IF;
IF errNo = 0 THEN
IF pricingHeaderID2 IS NULL THEN
SET errNo = 9003;
SET errMsg = 'Not retrieved.';
END IF;
END IF;
SELECT pricingHeaderID1, pricingHeaderID2, errNo, errMsg, currOp, sqlErrNo, sqlErrMsg;
END
✓
CALL SavePricingHeader(1,0,1,'test','subd','subepro',NOW(), 1,2,1,1,12,1981,0)
pricingHeaderID1 | pricingHeaderID2 | errNo | errMsg | currOp | sqlErrNo | sqlErrMsg
---------------: | ---------------: | ----: | :----- | :------ | :------- | :--------
1 | 1 | 0 | OK | Lookup2 | 00000 |
✓
db<>fiddle here
I am trying to convert a complex oracle sql procedure to mysql. The procedure contains of many differenct selects, cursors etc. I already wrote a version of it in mysql, but it does not work and only gives some error messages. I hope on could help me.
Tables
CREATE TABLE IF NOT EXISTS `NutritionalInformation`
(
`idNuIn` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`calories` FLOAT NULL,
`saturatedFat` FLOAT NULL,
`transFat` FLOAT NULL,
`carbohydrates` FLOAT NULL,
`sugar` FLOAT NULL,
`protein` FLOAT NULL,
`salt` FLOAT NULL
);
CREATE TABLE IF NOT EXISTS `Inventory`
(
`idInventory` INT NOT NULL,
`idIngredient` INT NOT NULL,
`idStore` INT NOT NULL,
`expiryDate` DATE NULL,
`deliveryDate` DATE NOT NULL,
`amount` INT NOT NULL,
`isAccessible` INT NOT NULL,
CONSTRAINT `fk_Inventory_Ingredient`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_Inventory_StoreA`
FOREIGN KEY (`idStore`)
REFERENCES `WaffleStore` (`idStore`),
CONSTRAINT pk_Inventory
PRIMARY KEY (idInventory)
);
CREATE TABLE IF NOT EXISTS `Inventory`
(
`idInventory` INT NOT NULL,
`idIngredient` INT NOT NULL,
`idStore` INT NOT NULL,
`expiryDate` DATE NULL,
`deliveryDate` DATE NOT NULL,
`amount` INT NOT NULL,
`isAccessible` INT NOT NULL,
PRIMARY KEY (`idIngredient`, `idStore`),
CONSTRAINT `fk_Inventory_Ingredient`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_Inventory_StoreA`
FOREIGN KEY (`idStore`)
REFERENCES `WaffleStore` (`idStore`)
);
CREATE TABLE IF NOT EXISTS `Product`
(
`idProduct` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`idNuIn` INT NOT NULL,
`price` FLOAT NOT NULL,
`name` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_Product_NutritionalInformation1`
FOREIGN KEY (`idNuIn`)
REFERENCES `NutritionalInformation` (`idNuIn`)
);
CREATE TABLE IF NOT EXISTS `Waffle`
(
`idWaffle` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`creatorName` VARCHAR(255) NULL,
`creationDate` DATE NOT NULL,
`processingTimeSec` INT,
`healty` VARCHAR(255),
CONSTRAINT `fk_Waffle_Product1`
FOREIGN KEY (`idWaffle`)
REFERENCES `Product` (`idProduct`)
);
CREATE TABLE IF NOT EXISTS `WaffleIngredient`
(
`idIngredient` INT NOT NULL,
`idWaffle` INT NOT NULL,
`amount` INT NOT NULL,
PRIMARY KEY (`idIngredient`, `idWaffle`),
CONSTRAINT `fk_WaffleRecept_Ingredient1`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_WaffleRecept_Waffle1`
FOREIGN KEY (`idWaffle`)
REFERENCES `Waffle` (`idWaffle`)
);
CREATE TABLE IF NOT EXISTS `WaffleStore`
(
`idStore` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(255) NULL,
`areaCode` VARCHAR(15) NULL,
`location` VARCHAR(255) NULL,
`streetName` VARCHAR(255) NULL,
`houseNumber` VARCHAR(45) NULL
);
Example Inserts
INSERT INTO NutritionalInformation (idNuIn, calories, saturatedFat, transFat, carbohydrates, sugar, protein, salt)
VALUES (4, 60, 0, 0, 0, 0, 0, 0);
INSERT INTO NutritionalInformation (idNuIn, calories, saturatedFat, transFat, carbohydrates, sugar, protein, salt)
VALUES (5, 350, 3, 3, 5, 5, 3, 1);
INSERT INTO INGREDIENT (idIngredient, idNuIn, name, unit, price, processingTimeSec)
VALUES (3, 4, 'Apfel', 'g', 0.5, 3);
INSERT INTO PRODUCT (idProduct, idNuIn, price, name)
VALUES (4, 5, 3.5, 'ApfelWaffel');
INSERT INTO WAFFLE (idWaffle, creatorName, creationDate, processingTimeSec, healty)
VALUES (4, 'Berndt', '2020-12-01', NULL, NULL);
INSERT INTO WAFFLEINGREDIENT(idIngredient, idWaffle, amount)
VALUES (3, 4, 2);
INSERT INTO WaffleStore (idStore, name, areaCode, location, streetName, houseNumber)
VALUES (1, 'Waffle GMBH', '50000', 'TEST', 'TEST', '38');
INSERT INTO INVENTORY(idInventory, idIngredient, idStore, expiryDate, deliveryDate, amount, isAccessible)
VALUES (2, 3, 1, '3032-12-30', '3032-12-30', 100, 1);
INSERT INTO WaffleOrder(idOrder, idStore, totalAmount, paymentStatus, orderDate)
VALUES (1, 1, 2, 0, '2020-12-30');
Oracle SQL PROCEDURE
CREATE OR REPLACE PROCEDURE OnInventoryAdd (
s_idProduct IN INT,
s_idOrder IN INT,
s_extenal_amount IN INT
)
IS
v_store INT;
v_waffle_id INT;
v_cursor_ingredientid INT;
v_cursor_amount INT;
v_cursor_expiryDate DATE;
v_cursor_deliveryDate DATE;
v_operator VARCHAR(3) := 'add';
CURSOR v_Ingredient_Cursor_On_Insert(w_Id INT) IS
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = w_Id;
CURSOR v_Ingredient_Cursor_On_Delete(i_id INT) IS
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = i_id;
BEGIN
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT w.idWaffle INTO v_waffle_id FROM Waffle w WHERE w.idProduct = s_idProduct;
-- If more than one waffle is bought
FOR x IN 1..s_extenal_amount LOOP
-- Get all ingredient information of waffle
OPEN v_Ingredient_Cursor_On_Insert(v_waffle_id);
LOOP
FETCH v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
EXIT WHEN v_Ingredient_Cursor_On_Insert%NOTFOUND;
-- Get all old expirydate and deliverydate information
OPEN v_Ingredient_Cursor_On_Delete(v_cursor_ingredientId);
LOOP
FETCH v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
EXIT WHEN v_Ingredient_Cursor_On_Delete%NOTFOUND;
END LOOP;
CLOSE v_Ingredient_Cursor_On_Delete;
END LOOP;
CLOSE v_Ingredient_Cursor_On_Insert;
-- Update the Inventory
InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
END LOOP;
END;
/
Current Version
DROP PROCEDURE IF EXISTS `OnInventoryAdd`;
DELIMITER //
CREATE PROCEDURE `OnInventoryAdd` (
s_idProduct INT,
s_idOrder INT,
s_extenal_amount INT
)
BEGIN
DECLARE loop_counter INT DEFAULT s_extenal_amount;
DECLARE v_store INT;
DECLARE v_waffle_id INT;
DECLARE v_cursor_ingredientid INT;
DECLARE v_cursor_amount INT;
DECLARE v_cursor_expiryDate DATE;
DECLARE v_cursor_deliveryDate DATE;
DECLARE v_operator VARCHAR(3) DEFAULT 'add';
DECLARE v_c_insert_done, v_c_delete_done BOOLEAN DEFAULT FALSE;
DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_insert_done = TRUE;
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
WHILE loop_counter > 0 DO
SET loop_counter = loop_counter - 1;
OPEN v_Ingredient_Cursor_On_Insert;
curr_insert_loop: LOOP
FETCH FROM v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
IF v_c_insert_done THEN
CLOSE v_Ingredient_Cursor_On_Insert;
LEAVE curr_insert_loop;
END IF;
BLOCK2 : BEGIN
DECLARE v_Ingredient_Cursor_On_Delete CURSOR FOR
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = v_cursor_ingredientid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_delete_done = TRUE;
OPEN v_Ingredient_Cursor_On_Delete;
curr_delete_loop : LOOP
FETCH FROM v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
IF v_c_delete_done THEN
CLOSE v_Ingredient_Cursor_On_Delete;
LEAVE curr_delete_loop;
END IF;
END LOOP curr_delete_loop;
END BLOCK2;
END LOOP curr_insert_loop;
CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
END WHILE;
END //
DELIMITER ;
Error
4 row(s) affected, 2 warning(s): 1264 Out of range value for column 'expiryDateOnInsert' at row 2 1264 Out of range value for column 'deliveryDateOnInsert' at row 1
Even tho I wrote the Oracle Procedure, I have zero clue how to write the same behavior in MYSQL and more over how to fix this error. If there is a alternative to do the same without cursors, then it would be fine too
Ok, I've managed to convert the oracle procedure into mysql stored procedure, here is the working code:
Code
CREATE PROCEDURE `OnInventoryAdd` (
s_idProduct INT,
s_idOrder INT,
s_extenal_amount INT
)
BEGIN
DECLARE loop_counter INT DEFAULT s_extenal_amount;
DECLARE done1, done2 BOOLEAN DEFAULT FALSE;
DECLARE v_store INT;
DECLARE v_waffle_id INT;
DECLARE v_operator VARCHAR(3) DEFAULT 'add';
DECLARE v_cursor_ingredientid INT;
DECLARE v_cursor_amount INT;
DECLARE v_cursor_expiryDate DATE;
DECLARE v_cursor_deliveryDate DATE;
DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = TRUE;
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
REPEAT
OPEN v_Ingredient_Cursor_On_Insert;
loop1 : LOOP
FETCH FROM v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
IF done1 THEN
CLOSE v_Ingredient_Cursor_On_Insert;
LEAVE loop1;
END IF;
BLOCK1 : BEGIN
DECLARE v_Ingredient_Cursor_On_Delete CURSOR FOR
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = v_cursor_ingredientid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = TRUE;
OPEN v_Ingredient_Cursor_On_Delete;
loop2 : LOOP
FETCH FROM v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
IF done2 THEN
SET done2 = FALSE; -- This was the solution
LEAVE loop2;
END IF;
END LOOP loop2;
END BLOCK1;
END LOOP loop1;
CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
SET loop_counter = loop_counter - 1;
UNTIL loop_counter = 0
END REPEAT;
END //
DELIMITER ;
I have a stored procedure to update some rows in MySQL. But when I call the stored procedure, it affects more than actual rows.
Here is my stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `SP_INSERT_DATA`(
IN `incoming_data` TEXT,
IN `value_array` TEXT,
IN `serial_number` VARCHAR(50),
IN `data_timestamp` VARCHAR(50),
OUT `result_id` INT,
OUT `result_message` VARCHAR(500)
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE i INT;
DECLARE value_iteration VARCHAR(50);
DECLARE lcl_data_type_id INT;
DECLARE arr_data_type_name VARCHAR(50);
DECLARE affected_data_row_count INT;
DECLARE cstmr_id INT;
DECLARE exit handler FOR 40001
BEGIN
GET DIAGNOSTICS CONDITION 1
#p1 = MYSQL_ERRNO, #p2 = MESSAGE_TEXT;
SET result_id = -2;
SET result_message = CONCAT('RETURNED ERROR NO : ', #p1 , '\r\nMESSAGE TEXT : ',#p2);
ROLLBACK;
END;
DECLARE exit handler for sqlexception
BEGIN
GET DIAGNOSTICS CONDITION 1
#p1 = MYSQL_ERRNO, #p2 = MESSAGE_TEXT;
SET result_id = -999;
SET result_message = CONCAT('RETURNED ERROR NO : ', #p1 , '\r\nMESSAGE TEXT : ',#p2);
ROLLBACK;
END;
START TRANSACTION;
SET i = 1;
SET affected_data_row_count = 0;
SET cstmr_id = 0;
SET result_id = 0;
SET result_message = 'Success';
SELECT id INTO cstmr_id FROM templaricustomers WHERE templaricustomers.customer_serial_number = serial_number LIMIT 1;
IF(cstmr_id <> 0) THEN
WHILE (LOCATE(',', value_array) > 0)
DO
SET arr_data_type_name = SUBSTRING_INDEX(value_array,',',i);
SET value_array = SUBSTRING(value_array, LOCATE(',',value_array) + 1);
SELECT JSON_EXTRACT(incoming_data, arr_data_type_name) INTO value_iteration;
SET arr_data_type_name := SUBSTRING_INDEX(arr_data_type_name, ".", -1);
IF (SELECT COUNT(id) FROM datatypes WHERE datatypes.data_name = arr_data_type_name) > 0 THEN
SELECT id INTO lcl_data_type_id FROM datatypes WHERE datatypes.data_name = arr_data_type_name LIMIT 1;
ELSE
INSERT INTO datatypes (datatypes.data_name,datatypes.description ,datatypes.inserted_date) VALUES(arr_data_type_name,arr_data_type_name,NOW());
SELECT id INTO lcl_data_type_id FROM datatypes WHERE datatypes.data_name = arr_data_type_name LIMIT 1;
END IF;
IF (SELECT COUNT(id) FROM mqttpacket WHERE mqttpacket.data_type_id = lcl_data_type_id AND mqttpacket.customer_id = cstmr_id) > 0 THEN
UPDATE mqttpacket SET mqttpacket.data_value = value_iteration , mqttpacket.inserted_time = data_timestamp WHERE mqttpacket.data_type_id = lcl_data_type_id AND mqttpacket.customer_id = cstmr_id;
ELSE
INSERT INTO mqttpacket (mqttpacket.data_type_id,mqttpacket.customer_id,mqttpacket.data_value,mqttpacket.inserted_time) VALUES(lcl_data_type_id,cstmr_id,value_iteration,data_timestamp);
END IF;
SET affected_data_row_count = affected_data_row_count +1;
END WHILE;
SET result_id = 0;
SET result_message = CONCAT('Query performed successfully. Effected rows : ',CAST(affected_data_row_count AS CHAR));
ELSE
SET result_id = -1;
SET result_message = 'Customer Serial Number not found.';
END IF;
COMMIT;
END
Here is how I call it:
CALL `SP_INSERT_DATA`('{"subcooling":-40,"B1":113,"B2":206,"B3":471,"B4":226,"B5":8,"B6":380,"B7":210,"B8":187,"Discharge":135,"Suction":120,"High_Pressure":90,"Low_Pressure":90,"Evaporation":73,"Condensation":73,"MAX_CMP_SPEED":1100,"Thermal_Limit":748,"SH":46,"EEV_pct":0,"COP":0,"DSH":60,"WaterFlux":8,"FanPower":1,"DeltaTtoStart":0,"DeltaPtoStart":60,"CMP_ROTOR_RPS":0,"SET_CH_FLASH":120,"SET_HP_FLASH":350,"SET_DHW_FLASH":470,"Defrosting":0,"B8_AVERAGE":63,"SET_PLANT":0,"SET_CH_BMS":160,"SET_HP_BMS":200,"SET_DHW_BMS":480,"SET_ACTIVE":200,"SET_DSH":250,"EEV_INJ_pct":0,"LPT":0,"HPT":0,"PLANT_MODE_MANUAL":0,"DHW_MODE_MANUAL":0,"WATER_FLOW":8,"DISCHARGE_TMP":135,"INVERTER_TMP":8,"ENVELOP_ZONE":1,"EEV_A_STEPS":0,"EBM_POWER":1,"EBM_MAX_POWER":106,"COMP_pct_FINAL":0,"TOTAL_POWER_ABSORBED":10,"POWER_OUT_KW":0,"COOLINGCAPACITY":0}' , '$.subcooling,$.B1,$.B2,$.B3,$.B4,$.B5,$.B6,$.B7,$.B8,$.Discharge,$.Suction,$.High_Pressure,$.Low_Pressure,$.Evaporation,$.Condensation,$.MAX_CMP_SPEED,$.Thermal_Limit,$.SH,$.EEV_pct,$.COP,$.DSH,$.WaterFlux,$.FanPower,$.DeltaTtoStart,$.DeltaPtoStart,$.CMP_ROTOR_RPS,$.SET_CH_FLASH,$.SET_HP_FLASH,$.SET_DHW_FLASH,$.Defrosting,$.B8_AVERAGE,$.SET_PLANT,$.SET_CH_BMS,$.SET_HP_BMS,$.SET_DHW_BMS,$.SET_ACTIVE,$.SET_DSH,$.EEV_INJ_pct,$.LPT,$.HPT,$.PLANT_MODE_MANUAL,$.DHW_MODE_MANUAL,$.WATER_FLOW,$.DISCHARGE_TMP,$.INVERTER_TMP,$.ENVELOP_ZONE,$.EEV_A_STEPS,$.EBM_POWER,$.EBM_MAX_POWER,$.COMP_pct_FINAL,$.TOTAL_POWER_ABSORBED,$.POWER_OUT_KW,$.COOLINGCAPACITY,', '123456', '2021-02-24 10:43:00.00' ,#result_id, #result_message);
The table mqttpacket is a system versioned table. Here are the table creation queries.
CREATE TABLE test_database.MQTTPacket(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
data_type_id INT NOT NULL,
customer_id INT NOT NULL,
data_value INT NULL,
row_start TIMESTAMP(6) GENERATED ALWAYS AS ROW START INVISIBLE,
row_end TIMESTAMP(6) GENERATED ALWAYS AS ROW END INVISIBLE,
inserted_time TIMESTAMP(6) NULL DEFAULT NULL,
PERIOD FOR SYSTEM_TIME(row_start,row_end),
FOREIGN KEY (data_type_id) REFERENCES test_database.DataTypes(id),
FOREIGN KEY (customer_id) REFERENCES test_database.templaricustomers(id)
)WITH SYSTEM VERSIONING;
CREATE TABLE `datatypes` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`data_name` VARCHAR(50) NOT NULL COLLATE 'latin1_general_ci',
`inserted_date` DATE NULL DEFAULT NULL,
`description` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_general_ci',
`device_id` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `device_id` (`device_id`) USING BTREE,
CONSTRAINT `datatypes_ibfk_1` FOREIGN KEY (`device_id`) REFERENCES `test_database`.`devices` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
)
CREATE TABLE `templaricustomers` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`customer_serial_number` VARCHAR(50) NOT NULL COLLATE 'latin1_general_ci',
`customer_name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_general_ci',
`inserted_date` TIMESTAMP(6) NOT NULL DEFAULT current_timestamp(6),
PRIMARY KEY (`id`) USING BTREE
)
So, when I first call the stored procedure, my result_message variable returns "Query performed successfully. Effected rows : 53" however MySql says
Affected rows: 107 Found rows: 0 Warnings: 0 Duration for 1 query: 0.015 sec.
In the second call of the SP, it says
Affected rows: 160 Found rows: 0 Warnings: 0 Duration for 1 query: 0.031 sec.
Thankful for any help in advance.
My mysql version is 5.5 and when run this mysql store procedure it's return this error.
Code:
CREATE DEFINER = CURRENT_USER PROCEDURE `getReceiptNumber`(IN bankcode
varchar,IN receipttype varchar,OUT seq int)
BEGIN
update receipt_number
set seq_number = (seq_number + 1)
where bank_code = bankcode and receipt_type = receipttype;
select seq_number from receipt_number where bank_code = bankcode and
receipt_type = receipttype into seq;
END;
Table Structure:
CREATE TABLE `receipt_number` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bank_code` varchar(255) DEFAULT NULL,
`cur_date` varchar(255) DEFAULT NULL,
`cur_year` int(11) DEFAULT NULL,
`receipt_type` varchar(255) DEFAULT NULL,
`seq_number` int(5) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
Error:
[Err] 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 'IN receipttype varchar,OUT seq int)
BEGIN
update receipt_number
set seq_nu' at line 1
You have not mentioned the size for in parameter varchar,
Try below code.
DELIMITER $$
CREATE DEFINER = CURRENT_USER PROCEDURE getReceiptNumber(IN bankcode VARCHAR(10),IN receipttype VARCHAR(10),OUT seq INT)
BEGIN
UPDATE receipt_number
SET seq_number = (seq_number + 1)
WHERE bank_code = bankcode AND receipt_type = receipttype;
SELECT seq_number FROM receipt_number WHERE bank_code = bankcode AND
receipt_type = receipttype INTO seq;
END$$
DELIMITER ;
I'am trying to create a procedure checking table and insert
but it show me some error which i'am not sure how to fix it
this is the error code
Explicit or implicit commit is not allowed in stored function or
trigger
DELIMITER ;;
CREATE FUNCTION `getLabel`(paradocid INT, paradoctype char(10),paradoclineid INT,paraqty INT,paracreated date,paracreatedby INT) RETURNS int(100)
BEGIN
DECLARE transtotal int;
DECLARE i int DEFAULT 0;
DECLARE total int;
CREATE TABLE IF NOT EXISTS `sim_lable`(
`label_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`doctype` varchar(10) NOT NULL,
`docid` int NOT NULL,
`doclineid` int NOT NULL,
`created` date NOT NULL,
`createdby` int NOT NULL
) ENGINE='InnoDB' COLLATE 'utf8_unicode_ci';
DELETE FROM sim_lable where
(TIME_TO_SEC(TIMEDIFF(paracreatedby,createdby))/60) >30;
SELECT #total=coalesce(count(*),0) as total2 from sim_label where
doctype=paradoctype and paradocid=docid;
IF total = 0 THEN
WHILE i < paraqty DO
INSERT INTO dbo.Students
(
`doctype` ,
`docid`,
`doclineid` ,
`created` ,
`createdby`
)
VALUES
(
paradoctype,
paradocid,
paradoclineid,
paracreated,
paracreatedby
) ;
END WHILE;
END IF;
END
As the error message says, explicit or implicit commit is not allowed in stored function or trigger. CREATE TABLE statement causes an implicit commit, therefore it is not allowed in a function.
Your code does not seem to return any value (there is no return statement in the function's body) and what you are doing there should be done in a stored procedure, rather than in a function.