6

Is there any setting or method I can use to get Oracle to return results in <table>.<column> format? For example:

Query:

SELECT     *
FROM       foo f
INNER JOIN bar b
ON         b.foo_id = f.id

Desired results:

F.ID  F.BLAH  B.ID  B.FOO_ID  B.BLAH
--------------------------------------------------------
1     blah    7     1         blah
2     blah    8     2         blah
3     blah    9     2         blah

The obvious solution is to individually alias each column SELECT f.id AS F_ID, ...; however, I'm needing to export some very large legacy tables (300+ columns), so using this method would cause the queries to be enormous and impractical.

2
  • İ'm not competent in PL/SQL, but perhaps you may try to rename columns of tables before joining them. Commented Sep 1, 2012 at 19:30
  • How are you exporting the data? Maybe this logic belongs in that export tool, instead of the individual statements? Commented Sep 1, 2012 at 19:40

2 Answers 2

8

There is no "option" in Oracle to do this; you may be able to find a client that allows you to do so as this is a job that would normally be done in the client; I don't know of one.

To expand upon tbone's answer you're going to have to do this dynamically. This does not mean that you have to list every column. You would use the data dictionary, specifically all_tab_columns or user_tab_columns to create your query. It would be easier to create a view with the exact definition you want so that you can re-use it if you want.

The aim is to use the fact that the columns existence is stored in a table as a string in order to create a query to use that column. As the column names and table names are stored as strings you can use string aggregation techniques to easily create a query or DDL statement that you can then manually, or dynamically, execute.

If you're using Oracle 11g Release 2 the listagg function is available to help you:

select 'create or replace view my_view as 
        select '
      || listagg( table_name || '.' || column_name 
               || ' as ' 
               || substr(table_name,1,1) || '_' 
               || column_name, ', ')
        within group 
         ( order by case when table_name = 'FOO' then 0 else 1 end
                  , column_id
          )
       || ' from foo f
            join bar b
              on f.id = b.foo_id'
  from user_tab_columns
 where table_name in ('FOO','BAR')
        ;

Assuming this table structure:

create table foo ( id number, a number, b number, c number);
create table bar ( foo_id number, a number, b number, c number);

This single query produces the following:

create or replace view my_view as 
 select FOO.ID as F_ID, FOO.A as F_A, FOO.B as F_B, FOO.C as F_C
      , BAR.FOO_ID as B_FOO_ID, BAR.A as B_A, BAR.B as B_B, BAR.C as B_C 
   from foo f 
   join bar b on f.id = b.foo_id

and here's a SQL Fiddle to prove it.

In you're not using 11.2 you can achieve exactly the same results using the undocumented function wm_concat or the user-defined function stragg, which was created by Tom Kyte. Oracle Base has an article on string aggregation techniques and there are many posts on Stack Overflow.

As a little addendum you can actually create exactly what you're looking for with a small change to the above query. You can use a quoted identifier to create a column in the TABLE_NAME.COLUMN_NAME format. You have to quote it as . is not a valid character for an object name in Oracle. The benefit of this is that you gain exactly what you want. The downside is that querying the created view is a huge pain if you don't use select * from ...; selecting named columns will require them to be quoted.

select 'create or replace view my_view as
        select '
      || listagg( table_name || '.' || column_name 
               || ' as ' 
               || '"' || table_name || '.'
               || column_name || '"', ', ')
        within group 
         ( order by case when table_name = 'FOO' then 0 else 1 end
                  , column_id
          )
       || ' from foo f
            join bar b
              on f.id = b.foo_id'
  from user_tab_columns
 where table_name in ('FOO','BAR')
        ;

This query returns:

create or replace view my_view as 
 select FOO.ID as "FOO.ID", FOO.A as "FOO.A", FOO.B as "FOO.B", FOO.C as "FOO.C"
      , BAR.FOO_ID as "BAR.FOO_ID", BAR.A as "BAR.A"
      , BAR.B as "BAR.B", BAR.C as "BAR.C"
   from foo f 
   join bar b on f.id = b.foo_id
Sign up to request clarification or add additional context in comments.

Comments

3

Using aliases wouldn't make the queries become impractical, its just not nearly as convenient as typing *. Use dynamic SQL to generate the columns for you:

select 'f.' || column_name || ' as F_' || column_name || ','
from all_tab_columns
where table_name = 'FOO'
order by column_id;

Do the same for any other wide tables you need, and copy/paste into your query. Also note the 30 char limit, hopefully none of your columns are over 28 in size.

1 Comment

Thank you for the suggestion, but I was specifically asking for a solution that does not involve explicitly listing the columns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.