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;
Related
I would like to create a PL/SQL Function that calculates the age of any person from an existing table "Family tree" (Familienbaum), based on their Name. The Table has the needed Values Name, BirthYear (Geburtsjahr), YearOfDeath (Sterbejahr), etc.
Now I want to calculate the age of the person in two ways:
If the Person has a YearOfDeath, it should subtract the BirthYear from the YearofDeath to calculate
If the Person has no YearOfDeath, it should subtract the BirthYear from the Current System Year of the Oracle SQL Server
So far I have tried using the SELECT INTO clause to declare the variables needed for the calculation from the table Family Tree (Familienbaum):
CREATE OR REPLACE FUNCTION BerechneAlter(Person VARCHAR2)
RETURN INTEGER IS
BEGIN
SELECT Name, Sterbejahr, Geburtsjahr FROM Familienbaum
WHERE Person = Name;
RETURN (CASE
WHEN Sterbejahr IS NULL THEN (year(curDate()) - Geburtsjahr)
WHEN Sterbejahr IS NOT NULL THEN (Sterbejahr - Geburtsjahr)
END);
END BerechneAlter;
The SELECT INTO clause is giving me a lot of problems, does anyone know what needs to be changed in the syntax?
I also tried using cursors, but it seems more complicated than needed:
create or replace FUNCTION BerechneAlter(Person VARCHAR2)
RETURN INTEGER IS
Sterbejahr INTEGER;
Geburtsjahr INTEGER;
CURSOR SJ IS SELECT familienbaum.sterbejahr FROM familienbaum WHERE familienbaum.name=Person;
CURSOR GJ IS SELECT familienbaum.geburtsjahr FROM familienbaum WHERE familienbaum.name=Person;
BEGIN
OPEN SJ;
FETCH SJ INTO Sterbejahr;
CLOSE SJ;
OPEN GJ;
FETCH GJ INTO Geburtsjahr;
CLOSE GJ;
RETURN (CASE
WHEN Sterbejahr IS NULL THEN (2022 - Geburtsjahr)
WHEN Sterbejahr IS NOT NULL THEN (Sterbejahr - Geburtsjahr)
END);
END BerechneAlter;
If you are using a SQL SELECT statement within an anonymous block or function or procedure, etc (in PL/SQL - between the BEGIN and the END keywords) you must select INTO something so that PL/SQL can utilize a variable to hold your result from the query. It is important to note here that if you are selecting multiple columns, (which you are by "SELECT Name, Sterbejahr, Geburtsjahr"), you must specify multiple variables or a record to insert the results of your query into.
for example:
SELECT 1
INTO v_dummy
FROM dual;
SELECT 1, 2
INTO v_dummy, v_dummy2
FROM dual;
It is also worth pointing out that if your SELECT , ... FROM.... will return multiple rows, PL/SQL will throw an error. You should only expect to retrieve 1 row of data from a SELECT INTO.
In your case, it would look something like this (note - I haven't confirmed that your logic is correct, also note that I don't know your datatypes so you'll have to work on that bit too):
CREATE OR REPLACE FUNCTION BerechneAlter(p_person VARCHAR2)
RETURN INTEGER IS
v_name VARCHAR2(100);
v_sterbejahr VARCHAR2(100);
v_geburtsjahr VARCHAR2(100)
BEGIN
SELECT Name, Sterbejahr, Geburtsjahr
INTO v_name, v_sterbejahr, v_geburtsjahr
FROM Familienbaum
WHERE Name = p_person;
RETURN (CASE
WHEN v_sterbejahr IS NULL THEN (year(curDate()) - v_geburtsjahr)
WHEN v_sterbejahr IS NOT NULL THEN (v_sterbejahr - v_geburtsjahr)
END);
END BerechneAlter;
I think the function's logic is overcomplicated. You can get data and calculate age in an SQL statement, so only one var is needed.
create or replace function get_age(p_name varchar2) return number
is
l_aelter number;
begin
select nvl(sterbejahr, to_char(sysdate, 'YYYY')) - geburtsjahr aelter
into l_aelter
from familienbaum
where name = p_name;
return l_aelter;
end;
If using plsql is not required, you might wanted to use a standalone SQL statement to perform all the calculations you need:
select nvl(sterbejahr, to_char(sysdate, 'YYYY')) - geburtsjahr aelter
from familienbaum
where name = p_name;
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?
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);
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;
I have a stored procedure, shown below, which I created to add dollar sales to a table (WeeklySales) which currently stores only unit sales. The cursor operates on on the WeeklySales table. The pricing data is stored in the Pricing table. The Pricing table actually contains changes in prices. The effective date for a price change is stored in Pricing.effectiveDate, so I have to find the pricing which was effective for the week in which the unit was sold (which is stored in WeeklySales.weekStart).
The problem I'm having is that the first select after the IF doesn't return anything. I've confirmed that this select does return a value when I run it outside of the procedure using the values which it would be called with inside the procedure. I'm not sure what's wrong here, but I'm guessing maybe this has to do with the fact that the this select is operating on a table which is different from the cursor? Anyone know? Is there a better way to do this?
DELIMITER //
CREATE PROCEDURE `createWeeklyPricing` (IN startDate DATE, IN endDate DATE)
BEGIN
--
-- Populate the proceeds column using the Pricing table
DECLARE product VARCHAR(255);
DECLARE weekStart DATE;
DECLARE units, done INT;
DECLARE proceeds DECIMAL(6,2);
DECLARE effectiveDate DATE;
DECLARE currentRow CURSOR FOR SELECT `weekStart`, `product`, `units` FROM `WeeklySales` WHERE `weekStart` >= startDate AND `weekStart` <= endDate;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN currentRow;
SET done = 0;
WHILE done = 0 DO
FETCH currentRow INTO weekStart, product, units;
IF done = 0 THEN
SELECT MAX(`effectiveDate`) FROM `Pricing` WHERE `effectiveDate` <= weekStart AND `product` = product INTO effectiveDate;
SELECT `proceeds` FROM `Pricing` WHERE `effectiveDate` = effectiveDate AND `product` = product INTO proceeds;
UPDATE `WeeklySales` SET `proceeds` = units * proceeds WHERE `weekStart` = weekStart AND `product` = product;
END IF;
END WHILE;
CLOSE currentRow;
END//
echo (select) weekstart before the if statement...
If it returns null change the select FROM WeeklySales WHERE weekStart between startDate AND endDate
you need to use the INTO before FROM and variable needs '#' sign
change it to
SELECT MAX(`effectiveDate`) INTO #effectiveDate FROM `Pricing` WHERE `effectiveDate` <= weekStart AND `product` = product ;
hope this helps
This is because your variable name is overwriting your column name:
You have a variable named 'effectiveDate'
You have a column named 'effectiveDate'
SELECT MAX(`effectiveDate`) ...
Is MAX-ing the variable effectiveDate, not the column
Try naming the variable maxEffectiveDate
Beware that variables are case insensitive. This happened to me when i tried to select column IsBackUp into variable isBackUp (notice the i).