Link to home
Start Free TrialLog in
Avatar of DuMonde
DuMondeFlag for United States of America

asked on

Column reference in Oracle user function

My question is a general one regarding if and how I can refer to a database column in a select statement from within a user-defined function.  I know I can write a select statement in my function (or any PL/SQL procedure). In my case, I am calling my function as part of a select statement, and would like to refer to columns in the selected table directly, rather than including them as parameters to my function.  I will be calling the function a number of times, and only one of its parameters will change.. so rather than passing 3 inputs, I'd prefer to pass one.

Here are the specifics:
I have created a user-defined function to calculate the number of days between two dates that fall within a quarter.
The function works fine, but I would like to be able to reference columns that are in the table.
As you will see in the code, my input variables are DT1, DT2, and QE, representing my two columns, and a constant quarter-end date, respectively.
I derive QB, as the quarter-begin date.
The function works fine, but when I call the function, I need to pass the two columns as inputs for DT1 and DT2 every time, in addition to the value for QE.
I have tried to find documentation on how (and if) I can write the function to refer to columns in the calling select statement, to no avail.
I'm using Oracle 8.1.7.
Function code (current version):
CREATE OR REPLACE FUNCTION DAYS_IN_Q(DT1 in date, DT2 in date, QE in date) RETURN number 
AUTHID CURRENT_USER AS
DAYS number;
QB date := trunc(QE,'Q');
begin 
if DT1>QE or DT2<QB 
  then DAYS := 0;
  else DAYS := least(QE,DT2) - greatest(QB,DT1);
end if;
RETURN DAYS;
end;
 
 
 
--Select statement:
select
 START_DATE
,END_DATE
,DAYS_IN_Q(START_DATE,END_DATE,to_date('2009-06-30','YYYY-MM-DD'))  as "DAYS_IN_Q209"
,DAYS_IN_Q(START_DATE,END_DATE,to_date('2009-09-30','YYYY-MM-DD'))  as "DAYS_IN_Q309"
--What I want to do is simply my function so when I call it, it looks like:
--,DAYS_IN_Q(to_date('2009-09-30','YYYY-MM-DD'))  as "DAYS_IN_Q309"
--(Obviously I need to write it so it only requires one parameter - That's not my problem.)
from MY_TABLE

Open in new window

Avatar of awking00
awking00
Flag of United States of America image

Given that the values in those columns are necessary to do the calculation, they need to be passed in as parameters to the function. What is it that bothers you about including them?
Avatar of DuMonde

ASKER

Thank you for your response.
Many things may be necessary for a calculation, but that doesn't imply that they must be included as arguments.
They could be selected within the procedure itself in a separate select statement, for example.

Why I would prefer to not have to specify these two parameters is because, as I said, I'd be passing the same value every time I call the function. The only value that would change is the third parameter, which in my case is a quarter-end date. The other two parameters are effectively constants for each row that is selected.
My code will be simpler if I can pass just what in fact changes, e.g.:

select
START_DATE
,END_DATE
,DAYS_IN_Q(to_date('2009-03-31','YYYY-MM-DD'))  as "DAYS_IN_Q109"
,DAYS_IN_Q(to_date('2009-06-30','YYYY-MM-DD'))  as "DAYS_IN_Q209"
,DAYS_IN_Q(to_date('2009-09-30','YYYY-MM-DD'))  as "DAYS_IN_Q309"
from MY_TABLE

instead of having to include the columns START_DATE and END_DATE as arguments in my function call, as I do now:
select
START_DATE
,END_DATE
,DAYS_IN_Q(START_DATE,END_DATE,to_date('2009-03-31','YYYY-MM-DD'))  as "DAYS_IN_Q109"
,DAYS_IN_Q(START_DATE,END_DATE,to_date('2009-06-30','YYYY-MM-DD'))  as "DAYS_IN_Q209"
,DAYS_IN_Q(START_DATE,END_DATE,to_date('2009-09-30','YYYY-MM-DD'))  as "DAYS_IN_Q309"
from MY_TABLE

The code works fine; I simply want to keep my code as lean as possible.  As I mentioned as well, I'd like to understand whether this capability exists in general, beyond just this application.
My question remains, then, is whether Oracle's PL/SQL language provide a mechanism to reference a column that is part of the select statement in which the function is called.
Thank you very much!
The problem is that you're not passing in a value, you're passing in an expression (in this case two attributes) that are needed to do a calculation along with a fixed value (the QE parameter) that is also needed for each record. If you want to make the select statement "leaner", you could pass in the QE parameter simply as '200903' and modify your function to convert that to the correct date using variable_QE := last_day(to_date(QE,'yyyymm'));
Avatar of DuMonde

ASKER

Hi again, awking00,
Thanks again for your thoughts.
It's funny you suggested supplying just year and month. I actually made that change this weekend!

So in sum, are you saying that there's no way to reference, from within a function, a column that is selected in the calling select statement?
It could be done within a procedure, but not within a function as far as I can tell.
Avatar of DuMonde

ASKER

What would it look like syntactically within a procedure?
See attached.
procedure.txt
ASKER CERTIFIED SOLUTION
Avatar of awking00
awking00
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of DuMonde

ASKER

Thanks again very much for your thoughts on this.
I agree with you that passing the dates is simpler.
Best regar