Insert into *table name* select *function call* doesn't work - mysql

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?

Related

SQL Function to print selected values

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);

Use MySQL query result in a loop

I just started working with SQL and have been working with MySQL.I am trying to write a stored procedure that will take each value from my buyPrice column in my products table, and store each value into a variable. I then want it to multiply this variable by the sales tax and then take each result and place it into my empty sales_tax column. I would like to populate the whole column with the sales tax for each item. When I execute this method I get some error saying the productCode doesn't have a default value. What is the proper way to write this? I know this isn't the most efficient way of doing this task, just trying to practice.
DELIMITER //
CREATE PROCEDURE nFirstProcedure()
BEGIN
DECLARE IdValue, counter, holdValue, result INT DEFAULT 0;
DECLARE holdName VARCHAR(30);
SET counter = 1;
WHILE counter < ( SELECT COUNT(*) FROM products)
DO
SET holdValue = (SELECT buyPrice FROM products WHERE sales_tax = null);
SET result = (holdValue * 0.08);
INSERT INTO products (sales_tax) VALUES (result);
END WHILE;
END//
DELIMITER ;
You should not do this with a loop. Just use update:
update products
set sales_tax = buyPrice * 0.08
where sales_tax is null;

MySQL - Function keeps returning null

I'm trying to create a MySQL function that will store the employee's time on projects and store it into v_emptime and then use that variable to calculate a total expense, like so:
delimiter //
create function F_COUNT_EDUCATION (p_empno char(6)) returns decimal(10, 2)
begin
declare v_emptime decimal(5, 2);
declare output decimal(10, 2);
select sum(emptime) # There are multiple records for some, using sum() for total time
into #v_emptime
from empprojact
where empno = p_empno;
# if I return v_emptime here it will be null
select (#v_emptime * comm + salary + bonus) expense
into #output
from employee
where empno = p_empno;
return #output;
end //
delimiter ;
However, the problem is that output will always return null. I've checked the data countless times and the data all have values. Which means I'm probably overlooking something very simple. Any help or insight would be appreciated, thanks!
Try this :
Change name of "#output" variable. And change query this :
select #v_emptime = sum(emptime)
from empprojact
where empno = p_empno;
And :
select #newVariableName = (#v_emptime * comm + salary + bonus) expense
from employee where empno = p_empno;

GROUP_CONCAT as input of MySQL function

Is it possible to use a GROUP_CONCAT in a SELECT as the input of a MySQL function? I cannot figure out how to cast the variable it seems. I've tried blob. I've tried text (then using another function to break it up into a result set, here) but I haven't had any success.
I want to use it like this:
SELECT
newCustomerCount(GROUP_CONCAT(DISTINCT items.invoicenumber)) AS new_customers
FROM items;
Here is the function:
DROP FUNCTION IF EXISTS newCustomerCount;
DELIMITER $$
CREATE FUNCTION newCustomerCount(invoicenumbers BLOB)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE new_customers INT;
SET new_customers = 0;
SELECT
SUM(nc.record) INTO new_customers
FROM (
SELECT
1 AS customer,
(SELECT COUNT(*) FROM person_to_invoice ps2 WHERE person_id = ps1.person_id AND invoice < ps1.invoice) AS previous_invoices
FROM person_to_invoice ps1
WHERE invoice IN(invoicenumbers)
HAVING previous_invoices = 0
) nc;
RETURN new_customers;
END$$
DELIMITER ;
Because Mysql functions do not support dynamic queries, I recommend you re-think your basic strategy to pass in a list of invoice numbers to your function. Instead, you could modify your function to accept a single invoice number and return the number of new customers just for the one invoice number.
Also, there are some optimizations you can make in your query for finding the number of new customers.
DROP FUNCTION IF EXISTS newCustomerCount;
DELIMITER $$
CREATE FUNCTION newCustomerCount(p_invoice INT)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE new_customers INT;
SET new_customers = 0;
SELECT
COUNT(DISTINCT ps1.person_id) INTO new_customers
FROM
person_to_invoice ps1
WHERE
ps1.invoice = p_invoice
AND NOT EXISTS (
SELECT 1
FROM person_to_invoice ps2
WHERE ps1.person_id = ps2.person_id
AND ps2.invoice < ps1.invoice
);
RETURN new_customers;
END$$
DELIMITER ;
Then you can still get the total number of new customers for a given list of invoice numbers like this:
SELECT
SUM(newCustomerCount(invoice)) as total_new_customers
FROM items
WHERE ...
You could try FIND_IN_SET() instead of IN(). The performance will probably be horrible when passing in a long list of invoice numbers. But it should work.
WHERE FIND_IN_SET(invoice, invoicenumbers)
You are looking in the wrong place.
WHERE invoice IN(invoicenumbers) will not do the desired substitution. Instead you need to use CONCAT to construct the SQL, then prepare and execute it.

MySQL stored function SELECT INTO unexpected results

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