Stored Procedure (mysql) fails with "can't return a result set in the given context" - mysql

I'm trying to get this SP to return (leave) if some conditions fails and so forth.
This code validates and it saves the procedure, but when I call the procedure with:
CALL ACH_Deposit(30027616,3300012003,200.00,"USD", "127.0.0.1")
It fails with error: "Procedure can't return a result set in the given context"
Does anyone have any idea on what the error is?
Procedure code:
CREATE DEFINER=`redpass_web_urs`#`%` PROCEDURE `ACH_Deposit`(
IN __Account_ID BIGINT,
IN __To_Bank_Account BIGINT,
IN __Amount DECIMAL(10,2),
IN __Currency CHAR(3),
IN __IP_Address VARCHAR(50)
)
COMMENT 'Makes a ACH deposit'
BEGIN
-- Declare Account Parameters
DECLARE _Account_Status INT;
DECLARE __Transaction_ID INT;
DECLARE _Account_Type INT DEFAULT 0;
DECLARE _Fee INT;
SELECT
Account_Status AS _Account_Status,
Account_Type AS _Account_Type
FROM Account_Users
WHERE Account_ID = __Account_ID;
main: BEGIN
-- Step 1, is account active ?
IF _Account_Status <> 1 THEN
-- Account must be active (not restricted, closed etc)
SELECT Response_Code, Description FROM ResponseCodes WHERE Response_Code = 106;
LEAVE main; -- Here we die..
END IF;
-- Step 2, Calculate the FEE (Loading Funds with ACH)
IF _Account_Type = 1 THEN
-- Personal Account
SET _Fee = (SELECT Fee_Template_Personal_1 FROM Fees WHERE Fee_Type_ID = __Fee_Type_ID);
ELSE
-- Business Account
SET _Fee = (SELECT Fee_Template_Business_1 FROM Fees WHERE Fee_Type_ID = __Fee_Type_ID);
END IF;
-- Step 3, Check that Fee is not bigger then the actual amount
IF _Fee > __Amount THEN
SELECT Response_Code, Description FROM ResponseCodes WHERE Response_Code = 108;
LEAVE main; -- Here we die..
END IF;
-- If we come here, we can make the transactions
INSERT INTO Bank_Transaction
(Bank_Account_ID
,Transaction_Type
,Amount
,IP_Address
,Pending)
VALUES
(__To_Bank_Account
,11
,__Amount
,__IP_Address
,1); -- Reserverade pengar
-- Transaction ID
SET __Transaction_ID = (SELECT LAST_INSERT_ID());
-- Deduct the Fee
INSERT INTO Bank_Transaction
(Bank_Account_ID
,Transaction_Type
,Amount
,Fee_Type_ID
,Fee_Transaction_ID)
VALUES
(__To_Bank_Account
,4
,-__Fee
,21
,__Transaction_ID);
END main;
SELECT Response_Code, Description, __Transaction_ID AS Transaction_ID
FROM ResponseCodes
WHERE Response_Code = 1;
END

To retrieve multiple resultsets from the stored procs, you should use a client which supports multiple queries.
If you use PHP, use MySQLi extension and call the procedure using mysqli_multi_query.
MySQL extension is only able to retrieve the first recordset returned by the proc. To be able to use ti, you should set CLIENT_MULTI_RESULTS (decimal 131072) in the parameter $client_flags to mysql_connect

Related

Creating Stored Procedures and joining tables

I am using a database called salesshort used mostly for learning MySQL. I am trying to create a stored procedure but for some odd reason when I run my code is not even creating the store procedure I think my syntax is wrong.
here are the instructions and my code.
Create a stored procedure ‘gbSaleP’ that returns the following ‘order types’:
"we are loosing money" if the actual profit for each order (i.e., OrderNumber)- is lower than or equal to zero; "good sale" if the difference between potential profit and actual profit is $2500 or lower; and
"bad sale" if the difference between potential profit and actual profit is greater than $2500.
delimiter //
create procedure gbSaleP ( in orderNumber int(10), out SaleStatus varchar (40))
begin
set gbsaleP = (select sum(o.quantityOrdered*p.MSRP - o.quantityOrdered*p.buyPrice) - abs(sum(o.quantityOrdered*o.priceEach - o.quantityOrdered*p.buyPrice))
from orderdetails as o
join products as p
using(productCode)
group by orderNumber
having porderNumber = orderName);
if gbSaleP <= 2500 then set SalesStatus = "good sale"
elseif gbSaleP => 2500 then set SaleStatus = "bad sale"
else set gbSaleP = "unknown"
end if;
end;
delimiter //
If your amount calculation script is right, you may use below.
DELIMITER //
CREATE procedure gbSaleP (IN orderNumber int(10), OUT SaleStatus varchar (40))
BEGIN
DECLARE amount DECIMAL(20,2);
set amount = (/*.......Correct SQL script*/);
if amount <= 2500 then
set SaleStatus = 'good sale';
elseif amount > 2500 then
set SaleStatus = 'bad sale';
else
set SaleStatus = 'unknown';
end if;
END; //
DELIMITER ;
You can test it with:
CALL `gbSaleP` (7, #`SaleStatus`);
SELECT #SaleStatus;

Mysql Stored Proc not returning a VARCHAR out parameter

Below is my stored procedure. It works fine but my problem is I can't get the output parameter as VARCHAR.
The part where I'm having problem is the assignment of #curcName to the out parameter op_resultMessage
BEGIN
SET op_resultMessage = #curcName;
END;
Here's the Stored Procedure.
CREATE DEFINER=`root`#`localhost` PROCEDURE `addCurriculum`(
IN p_curcName varchar(100),
IN p_description TEXT,
IN p_yearLevel VARCHAR(50),
IN p_syStart INT,
IN p_syEnd INT,
IN p_creator VARCHAR(50),
OUT op_resultMessage VARCHAR(50))
BEGIN
DECLARE curcName VARCHAR(20) ;
IF EXISTS
(SELECT #curcName := `name`
FROM curriculum
WHERE
yearLevel = p_yearLevel
AND syStart = p_syStart
AND syEnd = p_syEnd )
THEN --
BEGIN
SET op_resultMessage = #curcName;
END;
ELSE
BEGIN
INSERT INTO curriculum(`name`, description, yearLevel, syStart, syEnd, creator)
VALUES(p_curcName,p_description,p_yearLevel,p_syStart,p_syEnd,p_creator);
END;
END IF;
END
I'm trying to return a message IF name EXISTS
So it should go something like
SET op_resultMessage = #curcName 'already uses the school year and year level you're trying to insert';
But I don't know how to properly concatenate and assign values. I'm still confused with := SET and = operators. I guess that's where I'm having problems with.
If I change the out parameter's type to an INT like
OUT op_resultMessage VARCHAR(50)
then assigns a number to op_resultMessage like SET op_resultMessage = 1;
It returns the number 1 as out parameter values. It just won't work with varchar.
So when I try to call the procedure
CALL `enrollmentdb`.`addCurriculum`
('Test Curriculum ','Test ','Grade 1',2015,2016,'jordan',#outputMsg);
SELECT #outputMsg; -- this doesn't return any value even if Grade 1, 2015 and 2016 exists
I'd appreciate any help. I actually just learned mysql recently.
Thanks.
drop procedure if exists addCurriculum;
delimiter $$
CREATE PROCEDURE `addCurriculum`(
IN p_curcName varchar(100),
IN p_description TEXT,
IN p_yearLevel VARCHAR(50),
IN p_syStart INT,
IN p_syEnd INT,
IN p_creator VARCHAR(50),
OUT op_resultMessage VARCHAR(50))
BEGIN
DECLARE curcName VARCHAR(20) ;
SELECT `name` into #curcName
FROM curriculum
WHERE
yearLevel = p_yearLevel
AND syStart = p_syStart
AND syEnd = p_syEnd
LIMIT 1;
-- Note change above. When selecting into a variable (or more than 1)
-- then 0 or 1 rows can come back max or an Error occurs
IF #curcName is not null then
SET op_resultMessage = #curcName;
ELSE
BEGIN
INSERT INTO curriculum(`name`, description, yearLevel, syStart, syEnd, creator)
VALUES(p_curcName,p_description,p_yearLevel,p_syStart,p_syEnd,p_creator);
END;
SET op_resultMessage = 'GEEZ I am right here'; -- Drew added this
END IF;
END$$
delimiter ;
Note the commentary in the stored procedure, especially the part of only 0 or 1 rows returning else an Error will occur with a select into var pattern. So LIMIT 1. That may or may not be the row you want (limit 1), but that is where it is at right now.

declaring variable inside mysql stored procedure

we are trying to declare a variable inside mysql stored procedure that has transaction implemented in it. but it seems to be giving a syntax error :
following is the syntax of the stored procedure:
CREATE PROCEDURE `sp_MarkAppointmentRefferal`(
p_AppId bigint,
p_NewLocation bigint,
p_userId bigint,
p_ReferralReason varchar(500),
p_NewLocationName varchar(100)
)
begin
declare v_OldLocation int default 0;
set v_OldLocation = (select LocationId FROM appointments where iAppID = p_AppId limit 1 );
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
select -1;
END;
START TRANSACTION;
update table
set is_referred = 1,
referred_timestamp = now(),
referral_reason = p_ReferralReason
where iAppID = p_AppId
limit 1;
-- create a new appointment for the new referred location..
insert into appointments
(vAppName, vAppType, dAppDate, vCell, iPatID, iAppStatus, iuserid, iActive,
dInsertDate, iHSID, daily_ticket_no, LocationId, visit_id, encounter_id, ReferredFrom,ReferredOPDName, opd_name )
select vAppName, vAppType, now(), vCell, iPatID, iAppStatus, p_userId,
1, now(), iHSID, fn_GenerateNextAppointmentTicket(now(),p_NewLocation) , p_NewLocation, visit_id, encounter_id+1,
(select LocationId FROM appointments where iAppID = p_AppId limit 1),
(select OPD_Name FROM appointments where iAppID = p_AppId limit 1), p_NewLocationName
FROM appointments
where iAppID = p_AppId limit 1;
select LAST_INSERT_ID();
COMMIT;
end;
the syntax checker is saying that declare command is not valid here.
have also tried to place this inside the transaction clause and similar error shows up ..
any help is appreciated..
All declare statements should be at the top of the stored procedure body. Moving DECLARE EXIT HANDLER before the SET statement should fix the problem.

MySQL stored procedure if statement not working

I have the following stored procedure in MySQL
CREATE DEFINER=`test_db`#`%` PROCEDURE `ADD_ATTENDANCE`(IN `programID` INT, IN `clientID` INT, IN `insDate` DATETIME, IN `updDate` DATETIME, IN `insUser` INT, IN `updUser` INT, IN `lessonDate` DATE, IN `lessonTime` TIME)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Add attedance to my calendar'
BEGIN
DECLARE max_sub, availability INT;
DECLARE cursor_max_sub CURSOR FOR SELECT max_sub FROM app_lesson WHERE id = programID;
DECLARE cursor_availability CURSOR FOR SELECT count(*) FROM attendance WHERE program_id = programID AND lesson_date = lessonDate AND lesson_time = lessonTime;
OPEN cursor_max_sub;
OPEN cursor_availability;
read_loop: LOOP
FETCH cursor_max_sub INTO max_sub;
FETCH cursor_availability INTO availability;
IF (availability < max_sub) THEN
insert into attendance (program_id, client_id, ins_date, upd_date, ins_user, upd_user, lesson_date, lesson_time)
values (programID, clientID, insDate, updDate, insUser, updUser, lessonDate, lessonTime);
LEAVE read_loop;
ELSE
insert into attendance_hold (program_id, client_id, ins_date, upd_date, ins_user, upd_user, lesson_date, lesson_time)
values (programID, clientID, insDate, updDate, insUser, updUser, lessonDate, lessonTime);
END IF;
END LOOP;
CLOSE cursor_max_sub;
CLOSE cursor_availability;
END;
Even though the cursor_max_sub is equal to 6 and the cursor_availability is equal to 4 my procedure always executes the else insert statement. Can you please help me out?
Thanks!!!
OK that was tricky... For some reason when i change the max_sub variable into maxNumberOfSubscription everything worked perfectly... Is max_sub some kind of reserved key word for MySQL or there was a complication because my variable had the same name with the returned field of select statement?

Adding a record with a stored procedure does not quite work

I'm experiencing some issues with adding a record in a ms sql server database with an access form. I enter data in my access form, then I execute a stored procedure which should add the data to 2 different tables.
The issue here is, the data is being submitted to one table, but not in the other one. Here's my stored procedure:
ALTER PROCEDURE [dbo].[spAddArticle]
(
#description VARCHAR(128),
#stock integer,
#price decimal(8,2),
#startdate varchar(30),
#enddate varchar(30),
#supplier varchar(128)
)
AS
BEGIN
IF (
SELECT COUNT(*)
FROM article
WHERE description = #description
) = 0
begin try
BEGIN TRANSACTION
DECLARE #articlenr INT
SELECT #articlenr = MAX(articlenr) + 1 FROM article
INSERT INTO article (articlenr, description, catcode, supplier, stock)
VALUES (#articlenr, #description, NULL, #supplier, #stock)
INSERT INTO articleprice (articlenr, price, startdate, enddate)
VALUES (#articlenr, #price, #startdate, #enddate)
commit
Raiserror('The article has been added!', 16, 1)
end try
begin catch
if ##TRANCOUNT > 0
begin
ROLLBACK
end
Raiserror('An article with description %s already exists!', 16,1,#description)
end catch
END
The data is being added to table article, but not to articleprice, and I just can't seem to figure out why... Any idea's?
Hope you guys can help me out here..
The are a number of issues with this stored procedure. I can't explain why the second insert is failing but the error handling will obfuscate errors. The "success" raiseerror will fire the catch block due to the severity 16 error. A more serious issue is that the code is vulnerable to race conditions (both the EXISTS check and the SELECT MAX). I added an UPDLOCK hint to serialize for the purpose of this proc. The version below requires SQL 2012 or later. If you are using an earlier version, change the CATCH block handling to use RAISERROR instead of THROW.
ALTER PROCEDURE [dbo].[spAddArticle]
(
#description VARCHAR(128),
#stock integer,
#price decimal(8,2),
#startdate varchar(30),
#enddate varchar(30),
#supplier varchar(128)
)
AS
SET NOCOUNT ON; --rowcount messages can confuse some applications, especially ADO classic API
BEGIN TRY
BEGIN TRANSACTION;
IF NOT EXISTS(
SELECT *
FROM article WITH(UPDLOCK, HOLDLOCK) --serialize access for this proc
WHERE description = 'a'
)
BEGIN
DECLARE #articlenr INT;
SELECT #articlenr = MAX(articlenr) + 1 FROM article;
INSERT INTO article (articlenr, description, catcode, supplier, stock) SELECT #articlenr, #description, NULL, #supplier, #stock);
INSERT INTO articleprice (articlenr, price, startdate, enddate) VALUES (#articlenr, #price, #startdate, #enddate);
COMMIT;
RAISERROR('The article has been added!', 0, 0); --informational message for debugging
END
ELSE
BEGIN
RAISERROR('An article with description %s already exists!', 16,1,#description);
END;
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
BEGIN
ROLLBACK;
END;
THROW;
END CATCH
GO