Skip to content
Advertisement

Is it possible to have a table function return null rows?

I currently have a table function that returns a table of data. This data is retrieved by 7 functions within and are all called as values in a row, which is then repeated I number of times to create a table of the rows of data. Everything works as needed when there are 12 items I need to retrieve data for. The problem is that there is a maximum number of 12 items, but at some locations the number of items changes. This causes my function to return 0 rows instead of either 12 rows with all null rows where there is no data, or only the rows with data and exclude the null rows. Either output would work.

I have tried incorporating a function that returns the count of items at the location to use as the limit for my for loop such as:

FOR i IN 0 .. get_COUNT(LOCATION) LOOP

This worked for the locations with items in order starting at I=0. This does not work for some locations where the first item is not in I=0. For example, one location has only one item in I=1. If I take out the loop and just run this function on I=1 I get the row. When I run the function, because the first row (I=0) returns all null, I get no table.

CREATE TYPE TEMPROW AS OBJECT(
VAL1 VARCHAR2(5),
VAL2 VARCHAR2(5),
VAL3 VARCHAR2(5),
VAL4 VARCHAR2(5),
VAL5 VARCHAR2(5),
VAL6 VARCHAR2(5),
VAL7 VARCHAR2(5));

CREATE TYPE TABTYPE AS TABLE OF TEMPROW;

CREATE OR REPLACE FUNCTION get_VALUES_TABLE (LOCATION IN VARCHAR2) RETURN TABLE AS
    TEMPTAB TABTYPE := TABTYPE();
BEGIN
    FOR I IN 0 .. 11 LOOP
        TEMPTAB.EXTEND;
        TEMPTAB(TEMPTAB.LAST) := TEMPROW(
                    get_VALUE(LOCATION,1,I),
                    get_VALUE(LOCATION,2,I),
                    get_VALUE(LOCATION,3,I),
                    get_VALUE(LOCATION,4,I),
                    get_VALUE(LOCATION,5,I),
                    get_VALUE(LOCATION,6,I),
                    get_VALUE(LOCATION,7,I));
    END LOOP;
    RETURN TEMPTAB;
END;

Advertisement

Answer

Of course it is possible. Here is a small example. Showing the server output only for the test query at the end.

drop type my_table_type
/

drop type my_row_type
/

create or replace type my_row_type as object(id number, str varchar2(10), dt date)
/

create or replace type my_table_type as table of my_row_type
/

create or replace function my_function(num_rows integer) return my_table_type
as
  l_tab my_table_type := my_table_type();
begin
  for i in 1 .. num_rows
  loop
    l_tab.extend;
    l_tab(l_tab.last) := my_row_type(null, null, null);
  end loop;
  return l_tab;
end;
/

select rownum, t.* from table(my_function(3)) t;

    ROWNUM         ID STR        DT        
---------- ---------- ---------- ----------
         1                                 
         2                                 
         3 

(I added ROWNUM so we can see what’s happening; of course, you can just select * from table(my_function(3)), that is what will give the output where all the rows are null, null, null.)

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement