show the schema of a table in oracle - oracle

The following mysql query returns the constraints and the default values along with column_name, is_null and other details -
mysql query - select TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLUMN_TYPE, COLUMN_KEY, EXTRA from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = 'DB_NAME'
I want to write a similar query in Oracle, the following query returns data_type and is_null but doesn't return constraints and default values -
Oracle query - SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, NULLABLE FROM DBA_TAB_COLUMNS where owner = 'USERNAME'
How can I extract those information from an oracle table.
Note: I don't want to use describe table

Select tc.TABLE_NAME, tc.COLUMN_NAME, tc.DATA_TYPE, tc.NULLABLE, tc.DATA_DEFAULT,
con.cons
from DBA_TAB_COLUMNS tc
left join
( select listagg( cc.constraint_name, ',') within group (order by cc.constraint_name) cons,
table_name, owner , column_name
from DBA_CONS_COLUMNS cc
group by table_name, owner , column_name ) con
on con.table_name = tc.table_name and
con.owner = tc.owner and
con.column_name = tc.column_name
where tc.owner = 'USERNAME'
order by 1 ,2
There can be multiple constraints (or none) for each column. Because of that left join is used and listagg function to display all constraint in one column.
TABLE_NAME COLUMN_NAME DATA_TYPE NULLABLE DATA_DEFAULT CONS
AQ$_QUEUE_TABLES OBJNO NUMBER N AQ$_QUEUE_TABLES_PRIMARY,SYS_C001643
AQ$_QUEUE_TABLES SCHEMA VARCHAR2 N SYS_C001640
AQ$_QUEUE_TABLES SORT_COLS NUMBER N SYS_C001645
AQ$_QUEUE_TABLES TABLE_COMMENT VARCHAR2 Y
AQ$_QUEUE_TABLES TIMEZONE VARCHAR2 Y

You can still try to use this below snippet to get the requested details. Hope this helps.
Note : This is for indexed columns as I thought you might need this too
SELECT DISTINCT col.owner,
col.table_name,
col.DATA_TYPE,
Col.Column_Name,
DECODE(nullable,'Y','Yes','N','No') nullable,
high_value(col.table_name,col.column_name), -- This is own created function to deal with LONG datatype columns
Ind.Index_Name
FROM SYS.All_Tab_Cols col,
All_Ind_Columns ind
WHERE Col.Table_Name = Ind.Table_Name
AND Col.Column_Name = Ind.Column_Name(+)
AND Col.Table_Name = UPPER('<TABLE_NAME>')
AND Col.Owner = '<SCHEMA_NAME>';

Related

SQL to count number of partitions that has statistics and with missing statistics

I am on Oracle11g.
For each table, I want to check the number of partitions that has been analyzed and the number of partitions that has not been analyzed.
At the moment, I am using the SQL below:
COMPUTE SUM OF "UNANALYZED" ON REPORT
COMPUTE SUM OF "ANALYZED" ON REPORT
COMPUTE SUM OF "TOTAL" ON REPORT
BREAK ON REPORT
select t1.table_name,
decode(t2.unanalyzed,null,0,t2.unanalyzed) unanalyzed,
decode(t3.analyzed,null,0,t3.analyzed) analyzed,
t1.total
from
( SELECT table_name, count(1) total
FROM DBA_TAB_PARTITIONS p
WHERE 1=1
AND table_owner = 'ABC'
GROUP BY table_name ) t1 ,
( SELECT table_name, count(1) unanalyzed
FROM DBA_TAB_PARTITIONS p
WHERE 1=1
AND table_owner = 'ABC'
AND last_analyzed is NULL
GROUP BY table_name ) t2 ,
( SELECT table_name, count(1) analyzed
FROM DBA_TAB_PARTITIONS p
WHERE 1=1
AND table_owner = 'ABC'
AND last_analyzed is NOT NULL
GROUP BY table_name ) t3
where t1.table_name = t2.table_name (+)
and t1.table_name = t3.table_name (+)
order by t1.table_name
;
It is working like I would have wanted it to.
I just want to know if there is alternative to this SQL that will give the same result?
Something shorter or simpler maybe or something that uses analytic function?
Thanks.
I would do it like that :
SELECT
table_owner,
table_name,
SUM(DECODE(last_analyzed, NULL, 1, 0)) AS unanalyzed,
SUM(DECODE(last_analyzed, NULL, 0, 1)) AS analyzed,
COUNT(*) as total
FROM
dba_tab_partitions
WHERE
table_owner = 'ABC'
GROUP BY
table_owner,
table_name;
Ps: I kept your logic, but if last_analysed was 5 years ago, is it really analysed ?

get an column name from the table by passing value in oracle

I want a query in oracle to get the column name from the table by passing value.
Means that In most of the case - We write the query like that - select * from table where column = 'value'. But in my case i don't know the column name.
Can any one suggest me.
Thanks in advance...
You can try to build a dynamic query to check all the tables of your DB.
setup:
create table tab1 ( v1 varchar2(100), n1 number, v1b varchar2(100));
create table tab2 ( v2 varchar2(100), n2 number, v2b varchar2(100));
create table tab3 ( v3 varchar2(100), n3 number, v3b varchar2(100));
insert into tab1 values ('Maria', 1, 'aa');
insert into tab1 values ('xx', 2, 'bb');
insert into tab2 values ('yy', 3, 'Maria');
insert into tab2 values ('zz', 3, 'cc');
insert into tab3 values ('WW', 4, 'DD');
build the dynamic query:
select 'select table_name,
matches from (' || listagg(statement, ' UNION ALL ') within group (order by table_name) || ')
where matches > 0'
from (
select 'select ''' || table_name ||
''' as TABLE_NAME, count(1) as MATCHES from ' || table_name || ' WHERE ' ||
listagg(column_name || ' = ''Maria''', ' OR ') within group (order by column_name) as statement,
table_name
from user_tab_columns col
where data_type = 'VARCHAR2'
group by table_name
)
This will return a query, that you can run to check all the tables; in my example, this will build the query (not formatted) :
SELECT table_name, matches
FROM (SELECT 'TAB1' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB1
WHERE V1 = 'Maria'
OR V1B = 'Maria'
UNION ALL
SELECT 'TAB2' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB2
WHERE V2 = 'Maria'
OR V2B = 'Maria'
UNION ALL
SELECT 'TAB3' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB3
WHERE V3 = 'Maria'
OR V3B = 'Maria')
WHERE matches > 0;
Running this query will give:
TABL MATCHES
---- ----------
TAB1 1
TAB2 1
Please notice that I used USER_TAB_COLUMNS, thus searching only in the tables of the login schema; if you want to search in different schemas, you can use ALL_TAB_COLUMNS or DBA_TAB_COLUMNS, depending on what you need and on the privileges of you user; see here for something more.
Also, consider that USER_TAB_COLUMNS will get the colums of tables and views; if you want to limit your search to tables, you can join USER_TAB_COLUMNS(ALL_TAB_COLUMNS, DBA_TAB_COLUMNS) to USER_TABLES (ALL_TABLES, DBA_TABLES) by TABLE_NAME, or TABLE_NAME and OWNER If you decide to use ALL or DBA tables:
SQL> create view vTab1 as select * from tab1;
View created.
SQL> select count(1)
2 from user_tab_columns
3 where table_name = 'VTAB1';
COUNT(1)
----------
3
SQL> select count(1)
2 from user_tab_columns
3 inner join user_tables using(table_name)
4 where table_name = 'VTAB1';
COUNT(1)
----------
0
SQL>
select table_name from user_Tables where table_name = 'bogus';

How to get the Data Type of a Specific Column in H2 Database

I can get all column data by using the following query.
SHOW COLUMNS FROM table_name;
I want to get data of "column_name" only.
i tried the following query as well. but still didnt work.
SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'table_name' AND COLUMN_NAME = 'column_name';
Your help is greatly appreciated.
Try this:
select type_name
from information_schema.columns
where table_name='Table_name' and column_name='columnName';
The right query for the latest H2 is:
show columns from table_name
You need to add a join with table INFORMATION_SCHEMA.TYPE_INFO , the correct query is:
SELECT i.type_name FROM INFORMATION_SCHEMA.COLUMNS c, INFORMATION_SCHEMA.TYPE_INFO i
WHERE c.data_type=i.data_type AND c.table_name = 'table_name' AND c.column_name = 'column_name';
For the sake of uniqueness you also want to extend selection by schema name:
SELECT TYPE_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE UPPER ( TABLE_SCHEMA ) = UPPER ( 'my_schemaname' )
AND UPPER ( TABLE_NAME ) = UPPER ( 'my_tablename' )
AND UPPER ( COLUMN_NAME ) = UPPER ( 'my_columnname' )

What is the difference between column_name and qualified_col_name?

The following query on the standard view user_tab_col:
select * from user_tab_cols;
returns on Oracle the columns column_name and qualified_col_name.
What is the difference?
qualified_col_name indicates full column path for XML tables. Basically it stores the expression for this column. For regular columns it will be equal to column_name.
If you run:
select owner, table_name, column_name, data_type, qualified_col_name
from all_tab_cols
where column_name <> qualified_col_name;
you will see returned columns from XML tables in XDB schema.
For example:
OWNER TABLE_NAME COLUMN_NAME DATA_TYPE QUALIFIED_COL_NAME
XDB XDB$SIMPLE_TYPE SYS_NC00074$ XDB$APPINFO_LIST_T "XMLDATA"."RESTRICTION"."MIN_INCLUSIVE"."ANNOTATION"."APPINFO"
Update:
For object tables qualified_col_name stores expression of type casting and accessing to attribute. For example:
create or replace type test1_obj as object(
n1 number,
n2 number,
s1 varchar2(10),
s2 varchar2(20)
)
not final;
create or replace type test2_obj under test1_obj(
d1 date,
d2 date
)
not final;
create table object_table of test1_obj;
select column_name, data_type, qualified_col_name
from user_tab_cols
where table_name = 'OBJECT_TABLE'
order by internal_column_id;
For last 2 hidden system columns reserved for instances of type test2_obj we can see:
COLUMN_NAME DATA_TYPE QUALIFIED_COL_NAME
SYS_NC00010$ DATE TREAT(SYS_NC_ROWINFO$ AS "TEST"."TEST2_OBJ")."D1"
SYS_NC00011$ DATE TREAT(SYS_NC_ROWINFO$ AS "TEST"."TEST2_OBJ")."D2"

Function based Indexes and user_tab_cols

Why an entry is created in user_tab_cols when we create a function based on a column of a table?
create table t1(a varchar2(100), b number);
select * from user_tab_cols where table_name = 'T1'; -- Two rows coming
create index idx1 on t1(upper(a));
select * from user_tab_cols where table_name = 'T1'; -- Three rows coming
What is the reason to put an entry in user_tab_cols?
The extra column is a virtual column that Oracle has added to store the value of the indexed expression. From the Oracle documentation:
Oracle Database represents the index expression as a virtual column
You can easily verify in SQL*Plus that the extra column is virtual. In fact, it is also a 'hidden' column:
SQL> select column_name, hidden_column, virtual_column from user_tab_cols where table_name = 'T1';
COLUMN_NAME HID VIR
------------------------------ --- ---
A NO NO
B NO NO
SYS_NC00003$ YES YES
The name of the virtual column may be different on your machine.
user_tab_columns filters out hidden columns, as explained in the Oracle documentation for user_tab_cols. So, if you don't wish to see this column, you can query user_tab_columns instead of user_tab_cols:
SQL> select column_name from user_tab_columns where table_name = 'T1';
COLUMN_NAME
------------------------------
A
B
SQL>

Resources