I have this function in my DB
CREATE FUNCTION BookBed (pPaciente varchar(255),
pHospital bigint(20)) RETURNS BOOLEAN
BEGIN
DECLARE NumLeitosDisponiveis INT;
DECLARE vReservaOK BOOLEAN;
DECLARE dt TIMESTAMP;
SET dt = (Select now());
SET NumLeitosDisponiveis = (SELECT AVAILABLEBEDCOUNT FROM HOSPITAL WHERE ID = pHospital);
IF((SELECT NumLeitosDisponiveis) > 0) THEN
BEGIN
START TRANSACTION;
INSERT INTO RESERVATION(PERSON, HOSPITAL, DATE) VALUES (pPaciente, pHospital, dt);
UPDATE HOSPITAL
SET AVAILABLEBEDCOUNT = AVAILABLEBEDCOUNT - 1
WHERE ID = pHospital;
SET vReservaOk = true;
commit;
END;
ELSE
SET vReservaOk = false;
END IF;
RETURN vReservaOK;
END;
In the if part of my if-else statement, I would like to perform all the operations in a atomic way.
I wanted to use the START TRANSACTION command, but they are disallowed in functions and I couldn't find any other command to perform it.
Are functions atomic by default?
If not, is there any way I can implement it?
Thanks,
Oscar
EDIT: And if I have to use a function, is it possible to have transactions?
Use a stored procedure with an output parameter for returning the operation status.
DELIMITER //
CREATE PROCEDURE BookBed (
pPaciente varchar(255),
pHospital bigint(20),
OUT oReservaOK boolean)
BEGIN
DECLARE NumLeitosDisponiveis INT;
DECLARE dt TIMESTAMP;
SET dt = (Select now());
SET NumLeitosDisponiveis =
SELECT AVAILABLEBEDCOUNT FROM HOSPITAL WHERE ID = pHospital;
IF((SELECT NumLeitosDisponiveis) > 0) THEN
BEGIN
START TRANSACTION;
INSERT INTO RESERVATION(PERSON, HOSPITAL, DATE)
VALUES (pPaciente, pHospital, dt);
UPDATE HOSPITAL
SET AVAILABLEBEDCOUNT = AVAILABLEBEDCOUNT - 1
WHERE ID = pHospital;
SET oReservaOk = true;
commit;
END;
ELSE
SET oReservaOk = false;
END IF;
END//
If you are having trouble calling the stored procedure using Hibernate, then move the transaction logic to Hibernate. That is, start, commit or rollback the transaction using Hibernate constructs.
EDIT
Transactions require using the InnoDB engine as #bobobobo notes on the comments.
Related
So for some reason, I just got this error message: `Deadlock found when trying to get lock; try restarting transaction, but I'm not quite sure why since I've never gotten this before, and it used to work fine.
Stored procedure
CREATE PROCEDURE `AddTestResultRequirement`(varTestResultId INT, RequirementNameId INT)
BEGIN
declare reqId INT;
declare linkId INT;
set linkId = -1;
IF NOT EXISTS(SELECT * FROM testcaserequirement where nameId = RequirementNameId) THEN
insert into testcaserequirement(id, nameId) values (NULL, RequirementNameId);
set reqId = last_insert_id();
ELSE
set reqId = GetRequirementNameId(RequirementNameId);
END IF;
IF NOT EXISTS(select * from testresultrequirementlink where requirementId = reqId and testresultId = varTestResultId) THEN
insert into testresultrequirementlink(id, requirementId, testresultId) values(NULL, reqId, varTestResultId);
set linkId = last_insert_id();
else
set linkId = GetRequirementTestResultLinkId(varTestResultId, reqId);
end if;
select linkId;
END
Function
CREATE FUNCTION `GetRequirementTestResultLinkId`(varTestResultId INT, RequirementId INT) RETURNS int(11)
BEGIN
RETURN (SELECT id from testresultrequirementlink where testresultid = varTestResultId and requirementId = RequirementId LIMIT 1);
END
Anyone who can see where this deadlock would appear?
I do know that deadlock means that a deadlock is when two transactions are trying to lock two locks at opposite orders, but I still can't figure out why I got it.
Hello I have the following stored procedure for MySQL but when it is executed in my ASP.NET Core application I get a Subquery returns more than 1 row error. What am I doing wrong here? The equivalent SQL Server version used to work without problems...
-- System Calculates Candidate’s Matching Score based on a Manager’s Answer Weights
CREATE PROCEDURE spSysCalcCandScore
(
IN Candidate_ID INT,
IN Manager_ID INT
)
Begin
DECLARE ansID INT;
DECLARE tempSum INT;
DECLARE Sum INT;
DECLARE Done INT DEFAULT FALSE;
DECLARE MyCursor CURSOR FOR
SELECT Answer_ID FROM Completed_Questionnaire
WHERE Candidate_ID = Candidate_ID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET Done = TRUE;
START TRANSACTION;
OPEN MyCursor;
myloop: LOOP
FETCH MyCursor INTO ansID;
IF Done THEN
LEAVE myloop;
END IF;
SET tempSum = (SELECT Weight_Value FROM Weight WHERE (Answer_ID = ansID AND Manager_ID = Manager_ID));
SET Sum = Sum + tempSum;
END LOOP;
CLOSE MyCursor;
IF (Sum IS NULL) THEN
SET Sum = 0;
END IF;
UPDATE `Interest`
SET Matching_Score = Sum
WHERE (Candidate_ID = Candidate_ID AND Manager_ID = Manager_ID);
COMMIT;
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;
DELIMITER //
DROP PROCEDURE IF EXISTS sp_vk_suspend//
CREATE PROCEDURE sp_vk_suspend2()
declare today = DATETIME DEFAULT NULL;
declare accid = INT DEFAULT 11;
set today = now();
BEGIN
SELECT * FROM members where expirydate < today;
END //
This is my stored procedure. I have to add one or more query depend with id from members table. How can I retrieve id from members table.
ex: I have to add this query in my sp
UPDATE members
SET suspend = 1
WHERE id = 'some id from mem: tables'
i see IMHO cursors it's what you need
DECLARE done INT DEFAULT FALSE;
DECLARE cur1 CURSOR FOR SELECT id FROM members where expirydate < today;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE a INT;
OPEN cur1;
my_loop: LOOP
FETCH cur1 INTO a
IF done THEN
LEAVE my_loop;
END IF;
UPDATE members SET suspend=1 WHERE id = a;
INSERT INTO another(member_id) values(a);
END LOOP;
CLOSE cur1;
I have the following MySQL query:
DELIMITER //
CREATE PROCEDURE InsertResult (IN winnerID INT, IN loserID INT)
BEGIN
INSERT INTO KomperResult (WinnerID, LoserID) VALUES (#winnerID, #loserID);
DECLARE winnerScore, loserScore INT;
SELECT Score INTO #winnerScore FROM KomperPerson WHERE ID = #winnerID;
SELECT Score INTO #loserScore FROM KomperPerson WHERE ID = #loserID;
IF (#loserScore >= #winnerScore) THEN UPDATE KomperPerson SET Score = #loserScore + 1 WHERE ID = #winnerID; END IF;
END//
I get an error on:
DECLARE winnerScore, loserScore INT;
What am I doing wrong?
DECLAREs need to go on the first line of your procedure.
From the docs:
DECLARE is permitted only inside a
BEGIN ... END compound statement and
must be at its start, before any other
statements.