I'd like to know how to use a function parameter conditionaly. This is my function, and you can read the comment inside the query:
CREATE OR REPLACE FUNCTION mediabase.select_media(sysEnvironment character varying, statusId integer)
RETURNS refcursor AS
$BODY$
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR
SELECT media.id, media.title, media.unique_filename, media.owner_id, media.status_id, media.location_name_id, media.upload_user_id, media.upload_ip, media.metadata_id, media.type_id, media.description, media.system_environment, media.upload_date, media.gps_location, media.language_id, media_publications.publication_id, media.limitations, media_categories.category_id, metadata.width, metadata.height, metadata.equipment, metadata.copyright, metadata.creation_time, metadata.file_format, metadata.resolution, metadata.resolution_unit, metadata.gps_longitude, metadata.gps_latitude, metadata.artist, metadata.color_space, metadata.gps_altitude, metadata.software_used, metadata.user_comment
FROM mediabase.media, mediabase.metadata, mediabase.media_categories, mediabase.media_publications
WHERE media.metadata_id = metadata.id
AND media.id = media_categories.media_id
AND media.id = media_publications.media_id
-- Problem: this CASE doesn't work of course
CASE statusId <> -1 THEN
AND media.status_Id = statusId
END
-- End problem
AND media.system_environment = sysEnvironment
ORDER BY media.upload_date DESC;
RETURN ref;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
I only need to use the 'statusId' parameter, if it's different from -1, otherwise I'll recieve no results as there of-course is no status -1. Later on, I'll need to add some more filters of that sort.
Try something like:
AND (media.status_Id = statusId OR statusId = -1)
It wont check media.status_Id = statusId if statusId = -1.
Related
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
From the below source tutorials:
https://www.youtube.com/watch?v=Jt9vSY802mM
http://www.dotnetawesome.com/2017/07/curd-operation-on-fullcalendar-in-aspnet-mvc.html
How do I do the above code samples without Entity Framework, by just using SQL queries?
For example in the above source code, instead of
var v = dc.Events.Where(a => a.EventID == eventID).FirstOrDefault();
if (v != null)
{
dc.Events.Remove(v);
dc.SaveChanges();
status = true;
}
I want to do
DELETE FROM Even WHERE EventID = {0}
FirstOrDefault() in LINQ is equivalent to LIMIT 1 in MySQL, hence the LINQ function can be converted to SQL commands using IF or CASE WHEN like this (assumed commands are running inside a stored procedure):
DELIMITER //
-- 'Events' is a DbSet name by common convention,
-- therefore table name should be 'Event'
CREATE PROCEDURE procedure_name (IN eventID INT)
BEGIN
DECLARE v INT;
SET v = SELECT EventID FROM Event WHERE EventID = eventID LIMIT 1;
CASE WHEN v IS NOT NULL
THEN DELETE FROM Event WHERE EventID = v
ELSE -- do something else
END
-- alternative:
-- IF(v IS NOT NULL, DELETE FROM Event WHERE eventID = v, 0)
-- other stuff here
END//
DELIMITER ;
Note: If EventID is a primary key column, you can remove LIMIT 1 because query result only return single value.
Then, use CALL procedure_name(eventID) or include procedure_name in MySqlCommand to execute it.
Couple of ways:
using raw query in Entity Framework:
Open connection string via SqlConnection and execute:
Pseudo code for method 1:
string sqlDeleteStatement = "DELETE FROM Even WHERE EventID = #id";
List<SqlParameter> parameterList = new List<SqlParameter>();
parameterList.Add(new SqlParameter("#id", 1)); delete id = 1
_context.Database.SqlQuery(sqlDeleteStatement, parameterList);
Pseudo code for method 2:
using(SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = "Server=[server_name];Database=[database_name];Trusted_Connection=true";
string sqlDeleteStatement = "DELETE FROM Even WHERE EventID = #id";
SqlCommand command = new SqlCommand(sqlDeleteStatement , conn);
command.Parameters.Add(new SqlParameter("#id", 1)); //delete id = 1
command.ExecuteNonQuery();
}
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.
I don't know what is the problem why it gives me error in running the function
Here is my sql:
CREATE FUNCTION `test`.`GetProcessorMethodID` (processor_id INT, method_id INT)
RETURNS INTEGER
BEGIN
DECLARE id INT;
SET #id := (SELECT `processor_method_id` FROM `processor_method` WHERE `processor_id` = processor_id AND `method_id` = method_id);
RETURN #id;
END
But when I use this line of sql
SELECT processor_method_id FROM test.processor_method
WHERE processor_id = 1 AND method_id = 2;
It works fine!. It gives but the expected value I want to get. But in my function it does not return my expected values and always gives me error and I don't know what is wrong
Your problem is actually quite simple and you'll DEFINITELY remember it in the future... Change your parameter names... from processor_id, method_id to something like parmProcessor, parmMethod
AS IT Stands, your current parameters are the exact same name as the column names you are querying for, and thus
where `processor_id` = processor_id (same with method)
are BOTH referring to actual column name, and 1=1 all day long and 2=2 the same, so you are getting every record.
By changing them to something slightly different as sampled above you would get
where `processor_id` = parmProcessor and `method_id` = parmMethod
which is an EXPLICITLY DIFFERENT implication in the query.
The Query
SET #id := (SELECT `processor_method_id` FROM `processor_method` WHERE `processor_id` = processor_id AND `method_id` = method_id);
could conceivably return more than one record for processor_method_id which is why it's saying the sub-query returns more than one row. Depending on how you want to select the data, you could use the LIMIT clause.
so it would become:
SET #id := (SELECT `processor_method_id` FROM `processor_method` WHERE `processor_id` = processor_id AND `method_id` = method_id LIMIT 1);
I have searched but been unable to find anything that does what I need.
I would like to create a stored function that will gather data from a secondary field and return a comma separated list of items as the return string. I can't seem to find any way to take a variable I create in the function and iterate through a record set and append each result to the variable so I can return it .. see below:
BEGIN
DECLARE searchCat INT;
DECLARE searchProd INT;
DECLARE metas CHAR;
SET searchCat = cat;
SET searchProd = prod;
SELECT * FROM offer_metas WHERE category = searchCat AND offer_id = searchProd
gatherMeta: LOOP
metas = metas + "," + meta_option;
ITERATE gatherMeta;
END LOOP gatherMeta;
RETURN metas;
END
The function won't save because my syntax on the "metas = metas + meta_option;".
What I am looking for is the command to append the current field falue of "meta_option" to the current variable "metas" so I can return a full list at the end.
Any idea?
UPDATE - SOLUTION
BEGIN
DECLARE metas VARCHAR (300);
SELECT GROUP_CONCAT(CONCAT(mn.title,'=',offer_metas.meta_option) ORDER BY mo.cat_seq ASC) INTO metas
FROM offer_metas
LEFT JOIN meta_options as mo ON mo.id = offer_metas.meta_option
LEFT JOIN meta_names AS mn ON mn.category = mo.category AND mn.seq = mo.cat_seq
WHERE offer_metas.category = searchCat
AND offer_metas.offer_id = searchProd
ORDER BY cat_seq ASC;
RETURN metas;
END
And then I just updated my SQL query to be as follows (1 is the offer category I have in my PHPand populate into the query):
SELECT offers.*, s.short_name AS sponsorName, s.logo AS sponsorLogo, getMetas(1,offers.id) AS metas
FROM offers
LEFT JOIN sponsors AS s ON s.id=offers.carrier
GROUP BY offers.id
ORDER BY end_date ASC
Why not just
SELECT GROUP_CONCAT(meta_option SEPARATOR ',')
FROM offer_metas
WHERE category = searchCat AND offer_id = searchProd;
Option 1) use Group_Concat
Option 2) use || instead of +
Option 3) use Concat()