We have a large amount of data in an Oracle 11g server. Most of the engineers use Tableau for visualizing data, but there is currently not a great solution for visualizing straight from the Oracle server because of the structure of the database. Unfortunately, this cannot be changed, as it's very deeply integrated with the rest of our systems. There is a "dictionary" table, let's call it tab_keys
:
name | key
---------------
AB-7 | 19756
BG-0 | 76519
FY-10 | 79513
JB-2 | 18765
...
...
And there are also the tables actually containing the data. Each entry in tab_keys
has a corresponding data table named by prefixing the key with an identifier, in this case, we'll use "dat_". So AB-7 will store all its data in a table called dat_19756
. These keys are not known to the user, and are only used for tracking "behind the scenes". The user only knows the AB-7 moniker.
Tableau allows communication with Oracle servers using standard SQL select statements, but because the user doesn't know the key value, they cannot write a SQL statement to query the data.
Tableau recently added the ability for users to query Oracle Table Functions, so I started going down the road of writing a table function to query for the key, and return a table of the results for Tableau to use. The problem is that each dat_ table is basically unique with a different numbers of columns, labels, number of records, and datatypes from the next dat_ table.
What is the right way to handle this problem? Can I:
1) Write a function (which tableau can call inline in regular SQL) to return a bonified table name which is dynamically generated? I tried this:
create or replace FUNCTION TEST_FUNC
(
V_NAME IN VARCHAR2
) RETURN user_tables.table_name%type AS
V_KEY VARCHAR(100);
V_TABLE user_tables.table_name%type;
BEGIN
select KEY into V_KEY from my_schema.tab_keys where NAME = V_NAME;
V_TABLE := dbms_assert.sql_object_name('my_schema.dat_' || V_KEY);
RETURN V_TABLE;
END TEST_FUNC;
and then SELECT * from TABLE(TEST_FUNC('AB-7'));
but I get:
ORA-22905: cannot access rows from a non-nested table item
22905. 00000 - "cannot access rows from a non-nested table item"
*Cause: attempt to access rows of an item whose type is not known at
parse time or that is not of a nested table type
*Action: use CAST to cast the item to a nested table type
I couldn't figure out a good way to CAST the table as the table type I needed. Could this be done in the function before returning?
2) Write a table function? Tableau can supposedly query these like tables, but then I run into the problem of dynamically generating types (which I understand isn't easy) but with the added complication of this needing to be used by multiple users simultaneously, so each user would need a data type generated for them each time they connect to a table (if I'm understanding this correctly).
I have to think I'm missing something simple. How do I cast the return of this query as this other table's datatype?
user_tables.table_name%type
defines a variable with the same type as that column name, in this case VARCHAR2(30). It's not a record matching the projection of the table; which would beuser_tables%rowtype
but is a scalar (not a multi-row set) and anyway is a PL/SQL construct not understood by SQL. – APC