You'll need to use dynamic SQL if you are programmatically determining object names. Putting dynamic SQL together and executing it simple, figuring out how you want to get the data back to your calling program or client requires a bit more thought, as there are multiple options. Here's one:
CREATE TYPE whatever_rectype IS OBJECT (col1 integer, etc..);
CREATE TYPE whatever_tabtype IS TABLE OF whatever_rectype;
CREATE OR REPLACE FUNCTION whatever (paramA IN varchar2)
RETURN whatever_tabtype PIPELINED
AS
var_sql varchar2(32767);
rec_results whatever_rectype;
BEGIN
var_sql := '
SELECT *
FROM TABLE_A A';
IF paramA IS NOT NULL
THEN
var_sql := var_sql ||',
(SELECT whatever_rectype(col1,col2,etc..)
FROM TABLE_B
) B';
END IF;
var_sql := var_sql || '
WHERE 1=1';
IF paramA IS NOT NULL
THEN
var_sql := var_sql ||'
AND A.key = B.key';
END IF;
OPEN cur_whatever FOR var_sql;
FETCH cur_whatever INTO rec_results;
WHILE cur_whatever%FOUND
LOOP
PIPE ROW(rec_results);
FETCH cur_whatever INTO rec_results;
END LOOP;
END;
To execute:
SELECT *
FROM TABLE(whatever('myparamAValue'))
In recent versions you can dispense with the TABLE keyword:
SELECT *
FROM whatever('myparamAValue')