My database has a table with the following schema:
account(acno,amt)
acno int primary key
amt float(10,2)
How would I write a function that prints all account numbers having odd balance?
This query return odd balance
SELECT acno, amt
FROM
account
WHERE (amt % 2) > 0;
SELECT * FROM account WHERE MOD(amt, .02) > 0;
Should do the trick.
Doesn't really make sense to create function just to do what a simple query can do - that is, just output the rows that match your criteria. If you really need a function I guess you could make one to determine if a number is odd:
CREATE FUNCTION is_odd(amount float) RETURNS BOOLEAN
BEGIN
DECLARE isodd BOOLEAN;
SET isodd = TRUE;
IF MOD(amount,.02) = 0 THEN
SET isodd = FALSE;
END IF;
RETURN (isodd);
END
And then you can use this in the query instead:
SELECT * FROM account where is_odd(amt);
Related
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 ;
I'm trying to use a custom function to get a multiplication of two numbers and insert the result into the table column but I get an error:
Result consisted of more than one row
Code where I run into trouble:
INSERT INTO receipt(drug, amount, sum)
SELECT clientele.drug, clientele.amount, CalculateSum(clientele.amount, smallestprice.price)
FROM clientele, smallestprice
Any ideas?
Edit:
CalculateSum function source code:
SET GLOBAL log_bin_trust_function_creators = 1;
USE pharmacydb;
DELIMITER //
CREATE FUNCTION CalculateSum(amount INT, price DECIMAL)
RETURNS DECIMAL
BEGIN
DECLARE sum DECIMAL;
DECLARE local_otc BOOLEAN;
DECLARE local_amount INT;
SELECT otc FROM drug INTO local_otc;
SELECT amount FROM clientele INTO local_amount;
SET sum = 0;
IF local_otc = true THEN
SET sum = amount * price;
ELSEIF local_amount < amount THEN
SET sum = local_amount * price;
ELSE
SET sum = amount * price;
END IF;
RETURN sum;
END //
DELIMITER ;
Most likely, one (or both) of the two SELECT INTOs in your function's code return more than one result. SELECT INTO expressions can only return one row. Which drug and clientele are you trying to get the respective otc and amount values from?
I want to create a function that takes a input like (289)648-0997 or 12896480997 abd just returns 2896480997
my code below works for the 12896480997 but not for (289)648-0997
Alter FUNCTION [dbo].[fnFormatPhoneNumber](#phoneNumber VARCHAR(24))
RETURNS VARCHAR(24)
BEGIN
RETURN RIGHT(#phoneNumber, LEN(#phoneNumber) - 1)
END
Go
Try changing your function to this:
Alter FUNCTION [dbo].[fnFormatPhoneNumber](#phoneNumber VARCHAR(24))
RETURNS VARCHAR(24)
BEGIN
SET #phoneNumber = REPLACE(REPLACE(REPLACE(#phoneNumber,'(',''),')',''),'-','')
RETURN RIGHT(#phoneNumber, 10)
END
Go
SELECT [dbo].[fnFormatPhoneNumber]('(289)648-0997')
AND
SELECT [dbo].[fnFormatPhoneNumber]('12896480997') both return:
2896480997
use a case when to distinguish between those that begin with 1 and those that dont.
return
case when left(#phonenumber,1) = 1 then
RIGHT(replace(replace(replace(#phoneNumber, '(',''),')',''),'-','') LEN(#phoneNumber) - 1)
else replace(replace(replace(#phoneNumber, '(',''),')','')'-','') end
if the first char is a 1 then remove it and replace the ()- with ''.
if not just replace the ()-
not too sure on the logic of your input, may be possible to do away with the replace part in the first case when if you wouldnt input a number with ()- and a leading 1.
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
I have a field that contains version information such as:
V12.0
V1.0
BE0.50
VV24
I want to query for version greater then n. The number I want to do the comparison on is preceded by a non-fixed number of characters. Is it possible to do something like:
SELECT version FROM table WHERE int_part(version) > 10
V12.0
VV24
In this case it seems that version number appears in end only, alphabets are in beginning. So, probable solution will be to reverse the string, type cast it to get numbers, then reverse back the number obtained.
Try following solution
SELECT version
FROM table
HAVING CAST(REVERSE(IF(LOCATE(".", version), (CAST(REVERSE(version) AS DECIMAL(4,2))), (CAST(REVERSE(version) AS UNSIGNED INTEGER)))) AS DECIMAL(4,2)) > 12;
Hope it helps...
Seem like you have to create you own function to do this:
CREATE FUNCTION IsNumeric (val varchar(255)) RETURNS tinyint
RETURN val REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
CREATE FUNCTION NumericOnly (val VARCHAR(255))
RETURNS VARCHAR(255)
BEGIN
DECLARE idx INT DEFAULT 0;
IF ISNULL(val) THEN RETURN NULL; END IF;
IF LENGTH(val) = 0 THEN RETURN ""; END IF;
SET idx = LENGTH(val);
WHILE idx > 0 DO
IF IsNumeric(SUBSTRING(val,idx,1)) = 0 THEN
SET val = REPLACE(val,SUBSTRING(val,idx,1),"");
SET idx = LENGTH(val)+1;
END IF;
SET idx = idx - 1;
END WHILE;
RETURN val;
END;
select NumericOnly('vv24');
+---------------------+
| NumericOnly('vv24') |
+---------------------+
| 24 |
+---------------------+
Big downside of MySQL not supporting Regular Expressions in REPLACE method. If I have to do any matching of sorts, I usually pull all data to my PHP and process it there. In long run it is better solution. Of course you could always use User Defined Functions if you prefer.
http://dev.mysql.com/doc/refman/5.0/en/adding-udf.html
#shubhansh
Would 24 not change to 0.24 and failed > 12 ?