ziggy
ziggy

Reputation: 15876

Dynamic query with columns and table names from multiple tables using SQL or PL/SQL

Lets assume (for simplicity) i have two tables:

Product
 product_id
 CreatedDate
 LastEditedBy
 EditedDate

Entity
 entity_id
 CreatedDate
 LastEditedBy
 EditedDate

Both tables have the same column names but only the ID column has a different name. I would like to run a query so that when i run it from SQL plus i just give it a parameter and it gets the data from one of the tables. In the above example i could run the query like this

@archiveHistory.sql product
@archiveHistory.sql entity

Here is my attempt but it always failed to recognise one of the columns, i.e. if i run it with product, it says entity_id does not exist. if i run it with entity it says product_id does not exist.

Note that i am using the passed in parameter on both the column selection and the table name selection.

define identifier = '&1'

Select * from (
 Select case lower('&identifier')
  when product then product_id 
  when entity then entity_id
  end ID, CreatedDate, LastEditedBy, EditedDate
 From &identifier
)

I think it will work if the column list in the CASE statement were all from the same table.

Questions

Upvotes: 2

Views: 1748

Answers (1)

Lukas Eder
Lukas Eder

Reputation: 221370

For this particular case, I think the following SQL-only solution might work best:

SELECT product_id AS the_field
     , CreatedDate, LastEditedBy, EditedDate
FROM   Product
WHERE  LOWER('&identifier') = 'product'
UNION ALL
SELECT entity_id AS the_field
     , CreatedDate, LastEditedBy, EditedDate
FROM   Entity
WHERE  LOWER('&identifier') = 'entity'

The query planner will pre-evaluate your '&identifier' = ... predicates, which prevents execution of the unneeded union subquery.

If that's not an option (because your real-world use-case is much more complex), there are plenty of answers on Stack Overflow already regarding the execution of dynamic SQL from PL/SQL:

You could use dynamic SQL to insert your data into a temp table, and then simply SELECT * FROM temp_table

Upvotes: 2

Related Questions