Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Oracle column names in table.column format?

Tags:

oracle

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.

like image 802
FtDRbwLXw6 Avatar asked Sep 01 '12 19:09

FtDRbwLXw6


2 Answers

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
like image 89
Ben Avatar answered Sep 25 '22 15:09

Ben


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.

like image 26
tbone Avatar answered Sep 25 '22 15:09

tbone