MySQL stored function SELECT INTO unexpected results - mysql

I am trying to write a stored function in mysql 5.1 that returns the value 'AccountIDref' for a given room. If I only query the inner SELECT statement this works (returns the value for room). But invoking the function I get the response:
'#1172 - Result consisted of more than one row'
CREATE FUNCTION getAccountId (room INT) RETURNS INT
BEGIN
DECLARE refID INT DEFAULT NULL;
SELECT AccountIDref INTO refID FROM Allocation
WHERE Room = room;
RETURN refID;
END
What am I doing wrong here?

Field name and parameter name must be different -
CREATE FUNCTION getAccountId (room_param INT) RETURNS INT
BEGIN
DECLARE refID INT DEFAULT NULL;
SELECT AccountIDref INTO refID FROM Allocation
WHERE Room = room_param;
RETURN refID;
END
In your function you were getting all tables records.

What I am going to suggest isn't going to be much different from what you have, but I am skeptical about the where clause being in the next line and also let's use limit 1 to explicitly set the limit.
Try this :
CREATE FUNCTION getAccountId (room INT) RETURNS INT
BEGIN
DECLARE refID INT DEFAULT NULL;
SELECT AccountIDref INTO refID FROM Allocation WHERE Room = room LIMIT 1;
RETURN refID;
END

Related

How to return boolean based on number of records in database?

Here's what I've tried. My host is returning an error, "Sorry an unexpected error happened!" .
I want it to return true if there is at least 1 record with combination pdriver_id, ptruck_number, and pdate.
DELIMITER %%
CREATE FUNCTION DriverActiveInTruckByDate(
pdriver_id INT,
ptruck_number INT,
pdate DATETIME
)
RETURNS boolean
DETERMINISTIC
BEGIN
DECLARE inDB INT DEFAULT 0;
SET inDB =
SELECT IF(COUNT(*) >= 1,1,0)
FROM
truck_timeline tl
WHERE 1=1
AND tl.driver_id = pdriver_id
AND tl.truck_number = ptruck_number
AND ((pdate BETWEEN tl.begin_date AND tl.end_date) OR (pdate >= tl.begin_date AND tl.end_date IS NULL))
END
%%
DELIMITER ;
Several fixes are needed:
The function is not DETERMINISTIC. This means the result will always be the same given the same inputs. In your case, the result may be different depending on the data in your truck_timeline table. So I would suggest using READS SQL DATA.
If you use SET variable = SELECT... you must put the SELECT in a subquery:
SET inDB = (SELECT ...);
The current manual recommends using SELECT ... INTO variable instead of SET. See https://dev.mysql.com/doc/refman/8.0/en/select-into.html
The INTO position at the end of the statement is supported as of MySQL 8.0.20, and is the preferred position.
SELECT ... INTO inDB;
The function you show doesn't have a RETURN statement. See https://dev.mysql.com/doc/refman/8.0/en/return.html
There must be at least one RETURN statement in a stored function.
Your Full Code could be like this:
DELIMITER %%
CREATE FUNCTION DriverActiveInTruckByDate(
pdriver_id INT,
ptruck_number INT,
pdate DATETIME
)
RETURNS boolean
DETERMINISTIC
BEGIN
DECLARE inDB INT DEFAULT 0;
SET inDB =
(SELECT IF(COUNT(*) >= 1,1,0)
FROM
truck_timeline tl
WHERE 1=1
AND tl.driver_id = pdriver_id
AND tl.truck_number = ptruck_number
AND ((pdate BETWEEN tl.begin_date AND tl.end_date) OR (pdate >= tl.begin_date AND tl.end_date IS NULL))
);
END %%
DELIMITER ;

Why does my SQL function return a table when I want it to return a single value?

I want to write a function because I need the laststop value in a subsequent question calculation the bus fare with a pair of bus stops. If the alight bus stop value is Null the last stop will be used to calculate the fair.
for example, test data for bus service 77:
stoprank table
I want the function to return stopid "40129" for sid = 77 so I can do this:
select fare
from busfare
where boardtstop = 'xxx' and
alightstop = if(boardstop is not null,boardstop,laststop(77))
I also need the stop value for other questions as well when alightstop is null.
I hope I'm clear enough, the actual question is more complicated I'm trying to simplify it.
I have a table called stoprank which has columns: stopid, sid(bus service id), stoprank. I want to create a function laststop that takes in a bus service id and returns the last stop of the service(highest stoprank).
Overview of the stoprank table
I wrote the following function:
delimiter $$
create function LastStop (serviceID int)
returns int
DETERMINISTIC
begin
declare laststopid int;
set laststopid = (select stopid from stoprank where sid = serviceID and
rankorder = (select max(rankorder) from stoprank where sid = serviceID));
return laststopid;
end $$
delimiter ;
However, instead of returning one value, the last stop, it returns a table of the same value:
actual output
expected output
The value is correct but the format is wrong, I can't figure out why.
You should write the code in this way.
(select stopid from stoprank where sid = serviceID order by rankorder desc limit 1);

MySQL: Function not returning the correct integer

We have a question regarding a function returning the wrong integer-value in MySQL. We have checked that "booked_passengers" contains the right value, 0, and it works just fine when removing that variable, meaning just returning the integer 40. But as soon as we try to subtract "booked_passengers" from it, which still should end up returning 40, it does not work.
Including the code below.
Thanks in advance! :-)
CREATE FUNCTION calculateFreeSeats(flightnumber INT)
RETURNS INT
NOT DETERMINISTIC
BEGIN
DECLARE booked_passengers INT;
SELECT BOOKED_PASSENGERS INTO booked_passengers FROM FLIGHT WHERE (flightnumber = NR);
RETURN (40-booked_passengers);
END $$
When column name and local variable name interfere and there is no table alias then the variable is preferred. So your SELECT BOOKED_PASSENGERS ... selects variable value, not column value. Use
CREATE FUNCTION calculateFreeSeats(flightnumber INT)
RETURNS INT
READS SQL DATA
BEGIN
DECLARE booked_passengers INT;
SELECT FLIGHT.BOOKED_PASSENGERS INTO booked_passengers FROM FLIGHT WHERE (flightnumber = NR);
RETURN (40-booked_passengers);
END $$
From the other side the variable usage is obviously excess:
CREATE FUNCTION calculateFreeSeats(flightnumber INT)
RETURNS INT
READS SQL DATA
RETURN (SELECT 40 - BOOKED_PASSENGERS FROM FLIGHT WHERE flightnumber = NR LIMIT 1);

SELECT...INTO returns null in Stored Procedure

This function:
CREATE FUNCTION `GetCardID`(numId INT) RETURNS int(11)
DETERMINISTIC
BEGIN
DECLARE retcard INT(11);
SELECT id
INTO retcard
FROM cards
WHERE `number` = numId
AND enabled = 1
LIMIT 1;
RETURN retcard;
END
Always returns null even when the query:
SELECT id FROM cards WHERE `number`=<Insert Value Here> AND ENABLED = 1 LIMIT 1;
returns a valid value for the same value used in and the function parameter.
For instance:
SELECT id FROM cards WHERE number=12345 AND ENABLED = 1 LIMIT 1;
-- returns an id, while
GetCardId(12345);
-- returns null
Any ideas what I'm missing here? I consider myself quite skilled at SQL, but a little green on SP's.
How big is the data that you are taking into your function? Is it possible that the number is larger than what will fit into an INT?
Christopher here is your function. Try this and it should work:
CREATE FUNCTION [dbo].[GetCardID]
(
#Num_ID INT
)
RETURNS int
AS
BEGIN
declare #retcard int
select Top 1 #retcard = id
FROM cards
where number = #num_Id
AND enabled = 1
return #retcard
END
Always returns NULL:
Get rid of DETERMINISTIC clause in Procedure definition. MySQL caches the responses from such procedure or functions.
Excerpt from MySQL:
A routine is considered “deterministic” if it always produces the same
result for the same input parameters, and “not deterministic”
otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC is given in
the routine definition, the default is NOT DETERMINISTIC. To declare
that a function is deterministic, you must specify DETERMINISTIC
explicitly
MySQL 5.5 - Creating Procedure or Function

MySQL Function: Selecting and returning column

I have a table Processes, which consists of an ID (unsigned int, auto_increment) and Name (varchar, unique).
Selecting the following function with any input (whether in the table or not) always results in
ERROR 1172 (42000): Result consisted of more than one row
CREATE FUNCTION LookupOrInsertProcess(nametwo VARCHAR(255))
RETURNS INT UNSIGNED
BEGIN
DECLARE myid INT UNSIGNED;
SELECT ID INTO myid FROM Processes WHERE Name=nametwo;
RETURN myid;
END$$
However, selecting the below function always returns NULL:
CREATE FUNCTION LookupOrInsertProcess(nametwo VARCHAR(255))
RETURNS INT UNSIGNED
BEGIN
DECLARE myid INT UNSIGNED;
SELECT ID INTO myid FROM Processes WHERE Name=nametwo;
RETURN myid;
END$$
Furthermore, please note that the following does return the correct result (numbers 30 and 50 are arbitrary):
CREATE FUNCTION LookupOrInsertProcess(nametwo VARCHAR(255))
RETURNS INT UNSIGNED
BEGIN
DECLARE myid INT UNSIGNED;
SELECT ID INTO myid FROM Processes WHERE Name=nametwo;
IF myid IS NULL THEN
RETURN 30;
ELSE
RETURN 50;
END IF;
END$$
Any help is appreciated.
UPDATE: Edited to remove clash between table column and function param. I don't believe that's the issue.
UPDATE2: Please note that the following appears to work, both when the input param is or is not in the table. Why, without the coalesce(), does the function return NULL even for input params which are in the table?
CREATE FUNCTION LookupOrInsertProcess(nametwo VARCHAR(255))
RETURNS INT UNSIGNED
BEGIN
DECLARE myid INT UNSIGNED;
SELECT ID INTO myid FROM Processes WHERE Name=nametwo;
RETURN COALESCE(myid, 0);
END$$
Column names are not case-sensitive in MySql so you may find that where Name = name means 'give me every row'.
Try changing the input parameter to your procedure (and the corresponding condition in the query) to be srchName or something else different to name.
Try to rename input name to different name like inputName.
Update:
Another suggestion.
DECLARE myid INT UNSIGNED;
SET myid = (SELECT ID FROM Processes WHERE Name=nametwo);
RETURN myid;