check if select statement is true in a function in pl/sql - mysql

so i have a table called cars designed like this: ID, Model, Category, Availability.
The categories are standard and luxury.
im trying to write a function that returns either a boolean or an int like this :
function(id)
if category == luxury;
return 1;
else return 0;
i did this select statement but i dont know if i can use it
SELECT (CASE WHEN Category = 'Luxury' THEN 1 ELSE 0 END) AS is_equal
FROM CARS
WHERE ID = 'TM63DTI';
I have to do it in pl/sql. its for a school project and im stuck at this point. I dont have an error with this select statement, i just dont really know how to use it. Maybe suggest an idea of how i can approach this.

PL/SQL means "Oracle", not "MySQL". I suggest you fix tags.
So, if it really is Oracle, then one option might be this:
create or replace function f_category
(par_id in cars.id%type)
return boolean
is
l_is_equal number;
begin
select case when category = 'Luxury' then 1
else 0
end
into l_is_equal
from cars
where id = par_id;
return l_is_equal = 1;
end;
/
Though, it is kind of difficult to use a function that returns Boolean in SQL, so - perhaps you'd also want to consider option that returns a number instead. It is simple to convert previous function to a new version:
create or replace function f_category
(par_id in cars.id%type)
return number
is
l_is_equal number;
begin
select case when category = 'Luxury' then 1
else 0
end
into l_is_equal
from cars
where id = par_id;
return l_is_equal;
end;
/
Now you can use it in SQL as e.g.
select f_category(par_id => 123) from dual;
or
select *
from cars
where f_category(id) = 1;

Related

I am building my first function in PLSQL, it needs to return a single summed value of spending by a user based off parameters username and fiscal year

The function compiles, but when I run this block:
select sumyUserSpending('ALCraft', 15) from infor.credit_card_transaction
It throws error ORA-06575: Package or function sumyuserspending is in an invalid state.
When I run this block:
declare
answer number;
begin
answer := sumyUserSpending('ALCraft', 15);
dbms_output.put_line(answer);
end;
It throws errors ORA-65550 and PLS-00905: object sumyuserspending is invalid.
Here is my function. When I only run the function, it throws no errors, so I am lost as to what it could need to run smoothly. When the query is taken out of the function and I run the query alone, it returns the value I want based on the placeholder values I put in for the parameters. I am working in oracle 12c.
create or replace function sumyUserSpending (userN in varchar2, fiscYear in number)
return number
is
total number;
cursor search1 is
select sum(infor.credit_card_transaction.due_cc_co_amount) into total from infor.credit_card_transaction
inner join infor.credit_card using (credit_card_id)
inner join infor.ext_user using (user_id)
where infor.credit_card_transaction.transaction_date > concat('01-JUL-', (fiscYear - 1))
and infor.credit_card_transaction.transaction_date < concat('30-JUNE-', fiscYear)
and NVL(SUBSTR(infor.ext_user.email_address, 0, INSTR(infor.ext_user.email_address, '#')-1), infor.ext_user.email_address) = userN;
begin
open search1
fetch search1 into total;
if search1%notfound then
total := 0;
end if;
close search1;
return total;
end;
You need to refer to the tables by their just table name or an alias outside the FROM clause and not by schema_name.table_name.
Do not rely on implicit conversion of strings to dates; explicitly convert them using TO_DATE.
If you are using a cursor then a INTO clause is not syntactically valid.
However, you do not need a cursor.
Fixing all that gives you:
create or replace function sumyUserSpending (
userN in ext_user.email_address%TYPE,
fiscYear in number
) RETURN number
IS
total number;
BEGIN
select COALESCE(sum(cct.due_cc_co_amount), 0)
into total
from infor.credit_card_transaction cct
inner join infor.credit_card cc using (credit_card_id)
inner join infor.ext_user eu using (user_id)
where cct.transaction_date >= TO_DATE((fiscyear - 1) || '07-01', 'RR-MM-DD')
and cct.transaction_date < TO_DATE(fiscyear || '07-01', 'RR-MM-DD')
and NVL(SUBSTR(eu.email_address, 0, INSTR(eu.email_address, '#')-1), eu.email_address)
= userN;
return total;
end;
/
db<>fiddle here

Insert multiple value parameters into table

I have a client who wants to drop a list of values into a parameter in Reporting Services, compare it to a table in her database and return the full list of values with a yes or no in the next field indicating whether the value is found in the database table. For example if her list is Duck, Horse, Chicken and only Duck exists in the table she wants the result to look like this:
Duck Yes
Horse No
Chicken No
She doesn't want to return only those values that match so a simple WHERE Animal IN (#ReportParameter1) isn't going to do it.
I can make this work for a single value parameter like this:
DECLARE #FarmAnimals AS TABLE (Animal varchar(50))
INSERT INTO #FarmAnimals VALUES (#ReportParameter1)
SELECT Animal
,'In Barnyard’ = CASE WHEN EXISTS
(SELECT *
FROM tblBarnyard
WHERE BarnyardAnimal = Animal)
THEN 'Yes'
ELSE 'No'
END
FROM #FarmAnimals
But is it possible to loop through a multiple value parameter of unspecified length and create an INSERT INTO statement for each individual value? If this isn't possible I'm happy to tell her it can't be done but I can't think of a time I've found that something was impossible in SQL.
There's no need to do it in SQL, you can just write a custom code function to iterate through the selected parameter values to get the result that you want.
On the Report menu, access Report Properties... and select the Code tab. Insert the following code:
Function IsFieldSelected (fieldValue as String, ByVal parameter As Parameter) As String
Dim Result As String
Result = "No"
If parameter.IsMultiValue Then
For i As integer = 0 To parameter.Count-1
If (fieldValue = parameter.Value(i)) Then
Result = "Yes"
End If
Next
Else
If (fieldValue = parameter.Value) Then
Result = "Yes"
End If
End If
Return Result
End Function
then use this expression in the cell that you want the "Yes/No" to access the result:
=Code.IsFieldSelected(Fields!MyField.Value, Parameters!MyParameter)
Note that you are passing the parameter object here, not the Value property (so don't put .Value on the end). We access the Value property of the parameter object in the custom code function and compare it to the field value passed.
This will work for both single- and multi-value parameters.
You can do this using the STRING_SPLIT function in SQL Server.
--Placeholder table
DECLARE #ExistingValuesInTable TABLE (Val VARCHAR(255)) ;
INSERT INTO #ExistingValuesInTable (Val) VALUES ('Duck') ;
--
DECLARE #UserInput VARCHAR(255) = 'Duck, Horse, Chicken' ;
SELECT ss.value,
CASE WHEN evit.Val IS NULL THEN 'No' ELSE 'Yes' END AS AlreadyExists
FROM STRING_SPLIT(#UserInput, ',') AS ss
LEFT OUTER JOIN #ExistingValuesInTable AS evit ON ss.value = evit.Val ;

MySQL user-defined function returns incorrect value when used in a SELECT statement

I met a problem when calling a user-defined function in MySQL. The computation is very simple but can't grasp where it went wrong and why it went wrong. Here's the thing.
So I created this function:
DELIMITER //
CREATE FUNCTION fn_computeLoanAmortization (_empId INT, _typeId INT)
RETURNS DECIMAL(17, 2)
BEGIN
SET #loanDeduction = 0.00;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
INTO #totalAmount, #periodicDeduction, #totalInstallments, #deductionFlag
FROM loans_table
WHERE TypeId = _typeId AND EmpId = _empId;
IF (#deductionFlag = 1) THEN
SET #remaining = #totalAmount - #totalInstallments;
IF(#remaining < #periodicDeduction) THEN
SET #loanDeduction = #remaining;
ELSE
SET #loanDeduction = #periodicDeduction;
END IF;
END IF;
RETURN #loanDeduction;
END;//
DELIMITER ;
If I call it like this, it works fine:
SELECT fn_computeLoanAmortization(3, 4)
But if I call it inside a SELECT statement, the result becomes erroneous:
SELECT Id, fn_computeLoanAmortization(Id, 4) AS Amort FROM emp_table
There's only one entry in the loans_table and the above statement should only result with one row having value in the Amort column but there are lots of random rows with the same Amort value as the one with the matching entry, which should not be the case.
Have anyone met this kind of weird dilemma? Or I might have done something wrong from my end. Kindly enlighten me.
Thank you very much.
EDIT:
By erroneous, I meant it like this:
loans_table has one record
EmpId = 1
TypeId = 2
PeriodicDeduction = 100
TotalAmount = 1000
TotalInstallments = 200
DeductionFlag = 1
emp_table has several rows
EmpId = 1
Name = Paolo
EmpId = 2
Name = Nikko
...
EmpId = 5
Name = Ariel
when I query the following statements, I get the correct value:
SELECT fn_computeLoanAmortization(1, 2)
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table WHERE EmpId = 1
But when I query this statement, I get incorrect values:
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table
Resultset would be:
EmpId | Amort
--------------------
1 | 100
2 | 100 (this should be 0, but the query returns 100)
3 | 100 (same error here)
...
5 | 100 (same error here up to the last record)
Inside your function, the variables you use to retrieve the values from the loans_table table are not local variables local to the function but session variables. When the select inside the function does not find any row, those variables still have the same values as from the previous execution of the function.
Use real local variables instead. In order to do that, use the variables names without # as a prefix and declare the variables at the beginning of the function. See this answer for more details.
I suspect the problem is that the variables in the INTO are not re-set when there is no matching row.
Just set them before the INTO:
BEGIN
SET #loanDeduction = 0.00;
SET #totalAmount = 0;
SET #periodicDeduction = 0;
SET #totalInstallments = 0;
SET #deductionFlag = 0;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
. . .
You might just want to set them to NULL.
Or, switch your logic to use local variables:
SET v_loanDeduction = 0.00;
SET v_totalAmount = 0;
SET v_periodicDeduction = 0;
SET v_totalInstallments = 0;
SET v_deductionFlag = 0;
And so on.

Complex MySQL query issue

I have a somewhat complex mySQL query I am trying to execute. I have two parameters: facility and isEnabled. Facility can have a value of "ALL" or be specific ID. isEnabled can have value of "ALL" or be 0/1.
My issue is that I need to come up with logic that can handle the following scenarios:
1) Facility = ALL AND isEnabled = ALL
2) Facility = ALL AND isEnabled = value
3) Facility = someID AND isEnabled = ALL
4) Facility = someID AND isEnabled = value
The problem is that I have several nested IF statements:
IF (Facility = 'ALL') THEN
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
ELSE
SELECT * FROM myTable
WHERE isEnabled = value
END IF;
ELSE
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
WHERE facility = someID
ELSE
SELECT * FROM myTable
WHERE facility = someID AND isEnabled = value
END IF;
END IF;
I would like to be able to combine the logic in the WHERE clause using either a CASE statement or Conditional's (AND/OR) but I am having trouble wrapping my head around it this morning. Currently the query is not performing as it is expected to be.
Any insight would be helpful!
Thanks
You could do this...
SELECT
*
FROM
myTable
WHERE
1=1
AND (facility = someID OR Facility = 'ALL')
AND (isEnabled = value OR isEnabled = 'ALL')
However, this yields a poor execution plan - it's trying to find one size fits all, but each combination of parameters can have different plans depending on data, indexes, etc.
This means that it is better to build the query dynamically
SELECT
*
FROM
myTable
WHERE
1=1
AND facility = someID -- Only include this line if : Facility = 'ALL'
AND isEnabled = value -- Only include this line if : isEnabled = 'ALL'
I know it can feel dirty to use dynamic queries, but this is a good corner case as to when then really can excel. I'll go find a spectacularly informative link for you now. (It's a lot to read, but it's very worth learning from)
Link : Dynamic Search

query result what should i use Count() or Any()

I am checking login of a user by this repository method,
public bool getLoginStatus(string emailId, string password)
{
var query = from r in taxidb.Registrations
where (r.EmailId == emailId && r.Password==password)
select r;
if (query.Count() != 0)
{
return true;
}
return false;
}
I saw in one of the previous questions !query.Any() would be faster... Which should i use? Any suggestion....
The sql generated will be different between the two calls. You can check by setting your context.Log property to Console.Out or something.
Here's what it will be:
SELECT COUNT(*) AS [value]
FROM [dbo].[Registrations] AS [t0]
WHERE [t0].[EmailId] = #p0 and [t0].Password = #p1
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[Registrations] AS [t0]
WHERE [t0].[EmailId] = #p0 and [t0].Password = #p1
) THEN 1
ELSE 0
END) AS [value]
In this case, I doubt it will make any difference because EmailID is probably a unique index so there can only be 1 result. In another case where count can be > 1, Any would be preferable because the second query allows sql server to short circuit the search since it only needs to find one to prove that any exist.
You could express it quite a bit shorter like this:
return taxidb.Registrations.Any(r => r.EmailId == emailId && r.Password==password);