I have "read-only privileges" on a production Oracle 12c database. I can't create views or tables, even locally in my own schema. That's fine except I'd like to be able to see the column names and data-types for various queries that I'm developing.
I often need to take existing production queries (say a multi-table joins, various derived columns, etc). Obviously I have to store the query as a script, spool the results to a flat file. However I'd like to get same information available as on xxx_TAB_COLUMNS: the number of columns, data types, names of columns. Can that be obtained from the production database somehow?
NOTE: Because I do have access to a dev database, I can use the COPY command to create a table, but the real query is hundreds of lines long, so I'd have to do some manipulation to do so. I also looked at generating the XML schema (DBMS_XMLSCHEMA.GENERATESCHEMA), but it seems to just read the xxx_TAB_COLUMNS rather than parsing a query. Is it possible to get the same info directly from the production database query?
(Somewhat silly example):
PROD> create table t ( t NUMBER );
create table t ( t NUMBER )
*
ERROR at line 1:
ORA-01031: insufficient privileges
Elapsed: 00:00:00.03
PROD> ed
Wrote file c:/users/DGANOTE/sqlplusedit.sql
1 select owner, ageism, count(*) from (
2 select all_views.owner
3 , view_name
4 , created
5 , case when created > add_months(trunc(sysdate),-2)
6 then 'recent' else 'older'
7 end ageism
8 from all_views
9 join all_objects
10 on view_name = object_name
11 and all_views.owner = all_objects.owner
12 where all_views.owner like 'SYS%'
13* ) group by owner, ageism
PROD> /
OWNER AGEISM COUNT(*)
----------------------------------- ------ ------------
SYSTEM older 14
SYS older 5,760
SYS recent 16
Elapsed: 00:00:01.22
You can use DBMS_SQL to parse the query (you just change what is in l_query, or pass it as &1 in your SQL script).
The 'case' statement is approximate, but should be enough to work with.
SQL> set serverout on
SQL> declare
2 l_cur int default dbms_sql.open_cursor;
3 l_desc dbms_sql.desc_tab;
4 l_ncols int;
5 l_query long := 'select * from scott.emp';
6 begin
7 dbms_sql.parse(l_cur, l_query,dbms_sql.native);
8 dbms_sql.describe_columns(l_cur, l_ncols, l_desc);
9 dbms_sql.close_cursor(l_cur);
10 for i in 1..l_ncols loop
11 dbms_output.put_line('---------------------------');
12 dbms_output.put_line(
13 case
14 when l_desc(i).col_type = 1 then 'VARCHAR2'
15 when l_desc(i).col_type = 2 then 'NUMBER'
16 when l_desc(i).col_type = 8 then 'LONG'
17 when l_desc(i).col_type = 9 then 'VARCHAR'
18 when l_desc(i).col_type = 12 then 'DATE'
19 when l_desc(i).col_type = 23 then 'RAW'
20 when l_desc(i).col_type = 69 then 'ROWID'
21 when l_desc(i).col_type = 96 then 'CHAR'
22 when l_desc(i).col_type = 100 then 'BINARY_FLOAT'
23 when l_desc(i).col_type = 101 then 'BINARY_DOUBLE'
24 when l_desc(i).col_type = 105 then 'MLSLABEL'
25 when l_desc(i).col_type = 106 then 'MLSLABEL'
26 when l_desc(i).col_type = 112 then 'CLOB'
27 when l_desc(i).col_type = 113 then 'BLOB'
28 when l_desc(i).col_type = 114 then 'BFILE'
29 when l_desc(i).col_type = 115 then 'CFILE'
30 when l_desc(i).col_type = 178 then 'TIME'
31 when l_desc(i).col_type = 179 then 'TIME WITH TIME ZONE'
32 when l_desc(i).col_type = 180 then 'TIMESTAMP'
33 when l_desc(i).col_type = 181 then 'TIMESTAMP WITH TIME ZONE'
34 when l_desc(i).col_type = 231 then 'TIMESTAMP WITH LOCAL TIME ZONE'
35 when l_desc(i).col_type = 182 then 'INTERVAL YEAR TO MONTH'
36 when l_desc(i).col_type = 183 then 'INTERVAL DAY TO SECOND'
37 else 'OTHER'
38 end
39 );
40 dbms_output.put_line(l_desc(i).col_name);
41 dbms_output.put_line(l_desc(i).col_max_len);
42 dbms_output.put_line(l_desc(i).col_precision);
43 dbms_output.put_line(l_desc(i).col_scale);
44 end loop;
45 end;
46 /
---------------------------
NUMBER
EMPNO
22
4
0
---------------------------
VARCHAR2
ENAME
10
0
0
---------------------------
VARCHAR2
JOB
9
0
0
---------------------------
NUMBER
MGR
22
4
0
---------------------------
DATE
HIREDATE
7
0
0
---------------------------
NUMBER
SAL
22
7
2
---------------------------
NUMBER
COMM
22
7
2
---------------------------
NUMBER
DEPTNO
22
2
0
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL>
SQL>