List of tables along with key information - Oracle - oracle

I am trying to fetch the list of tables, column information including the data type from the Oracle metadata tables. You can see the list of columns below. Somehow primary key and foreign key constraint data that I am pulling seems to be replicating for all the columns of that table in question, whereas I expect null for the columns which are not tagged as primary key or foreign key in the constraint tables.
I have used a left outer join, but seems like it is not working as expected due to the joining conditions. Any help would be appreciated.
SELECT AO.OWNER,
AO.OBJECT_NAME,
ATC.COLUMN_NAME,
ATC.DATA_TYPE,
ATC.NULLABLE,
AC.CONSTRAINT_NAME
FROM ALL_OBJECTS AO
JOIN
ALL_TAB_COLUMNS ATC
ON AO.OBJECT_NAME=ATC.TABLE_NAME
LEFT JOIN
ALL_CONS_COLUMNS ACC
ON
--ACC.column_name=ATC.column_name and
ACC.TABLE_NAME=ATC.TABLE_NAME
inner JOIN
ALL_CONSTRAINTS AC
ON
AC.TABLE_NAME=ACC.TABLE_NAME
AND
AC.CONSTRAINT_NAME=ACC.CONSTRAINT_NAME
--and atc.table_name=ac.table_name
WHERE AO.OBJECT_TYPE = 'TABLE'
AND AO.OWNER = 'XYZ'
AND AO.OBJECT_NAME='ABC'
AND CONSTRAINT_TYPE IN ('P','R')
ORDER BY AO.OBJECT_NAME, ATC.COLUMN_NAME

I think your join conditions are not proper and owner must be used in join conditions as all_ views are uses
You should try following query:
SELECT AT.OWNER,
AT.TABLE_NAME,
LISTAGG(ATC.COLUMN_NAME,',') WITHIN GROUP (ORDER BY ATC.COLUMN_ID) AS COLUMN_NAMES,
LISTAGG(ATC.DATA_TYPE,',') WITHIN GROUP (ORDER BY ATC.COLUMN_ID) AS DATA_TYPE,
LISTAGG(ATC.NULLABLE,',') WITHIN GROUP (ORDER BY ATC.COLUMN_ID) AS NULLABLE,
AC.CONSTRAINT_NAME
FROM ALL_TABLES AT
JOIN
ALL_TAB_COLUMNS ATC
ON AT.TABLE_NAME=ATC.TABLE_NAME
AND AT.OWNER = ATC.OWNER
LEFT JOIN
ALL_CONS_COLUMNS ACC
ON ATC.COLUMN_NAME = ACC.COLUMN_NAME
AND ACC.TABLE_NAME = AT.TABLE_NAME
AND AC.OWNER = ACC.OWNER
LEFT JOIN ALL_CONSTRAINTS AC
ON AT.TABLE_NAME = AC.TABLE_NAME
AND AC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME
AND AT.OWNER = AC.OWNER
WHERE AT.OBJECT_TYPE = 'TABLE'
AND AT.OWNER = 'XYZ'
AND AT.OBJECT_NAME='ABC'
AND CONSTRAINT_TYPE IN ('P','R')
GROUP BY AT.OWNER,
AT.TABLE_NAME,
AC.CONSTRAINT_NAME
Cheers!!

Related

how to get full tables and columns with relations or not in ORACLE

How can I do to (left)join user_tab_columns with user_cons_columns and user_constraints to get the result below:
Table, Column, SourceTable, SourceColumn
ORDER, ORDER_ID, null, null
ORDER, ORDER_DATE, null, null
ORDER, ORDER_CLIENT, CLIENT, CLIENT_ID
CLIENT, CLIENT_ID, null, null
ORDER_DETAIL, ORDER_ID, ORDER, ORDER_ID
ORDER_DETAIL, PRODUCT_ID, PRODUCT, PRODUCT_ID
PRODUCT PRODUCT_ID, null, null
So... I need all table and columns but once a column is a foreign key,
I need to know the table and the column (primary key) related.
Slight edits to linked answer:
List of foreign keys and the tables they reference
all_ to user sources.
Course you could just use all and then filter on owner.
SELECT a.table_name, a.column_name, a.constraint_name, c.owner,
c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM user_cons_columns a
LEFT JOIN user_constraints c
ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
LEFT JOIN user_constraints c_pk
ON c.r_owner = c_pk.owner
AND c.r_constraint_name = c_pk.constraint_name
WHERE c.constraint_type = 'R'
--AND a.table_name = :TableName
check following query :
select a.table_name,c1.column_name,b.table_name,c2.column_name from USER_constraints a,USER_constraints b,user_cons_columns c1,user_cons_columns c2
where a.r_constraint_name = b.constraint_name and a.table_name = c1.table_name and b.table_name = c2.table_name if you just need FK constraint use a.constraint_type ='R' in where clouse.

get constraint name by column name in oracle database

How to get unique constraint_name of The corresponding column in oracle database?
in other words I want to get constraint name by column name.
pseudo query for this question:
select constraint_name from table_name tname where tname.column_name = 'columnName';
is this possible?
Use the Oracle dictionary views ALL_CONS_COLUMNS or USER_CONS_COLUMNS (if you want to restrict it by column type - i.e. unique or primary key constraints - then you can join in ALL_CONSTRAINTS or USER_CONSTRAINTS):
SELECT acc.constraint_name
FROM ALL_CONS_COLUMNS acc
INNER JOIN ALL_CONSTRAINTS ac
ON ( acc.CONSTRAINT_NAME = ac.CONSTRAINT_NAME )
WHERE ac.OWNER = 'YOUR_SCHEMA_NAME'
AND ac.TABLE_NAME = 'YOUR_TABLE_NAME'
AND acc.COLUMN_NAME = 'YOUR_COLUMN_NAME'
AND ac.CONSTRAINT_TYPE IN ( 'U', 'P' ) -- Unique or primary key constraints
or:
SELECT ucc.constraint_name
FROM USER_CONS_COLUMNS ucc
INNER JOIN ALL_CONSTRAINTS uc
ON ( ucc.CONSTRAINT_NAME = uc.CONSTRAINT_NAME )
WHERE uc.OWNER = 'YOUR_SCHEMA_NAME'
AND uc.TABLE_NAME = 'YOUR_TABLE_NAME'
AND ucc.COLUMN_NAME = 'YOUR_COLUMN_NAME'
AND uc.CONSTRAINT_TYPE IN ( 'U', 'P' ) -- Unique or primary key constraints
Try this.
select CONSTRAINT_NAME from USER_CONS_COLUMNS
where table_name='YOUR_TABLE'
and column_name='YOUR_COLUMN'

List of table which don't have a primary key

Need to get the list of tables name from a schema which doesn't have a primary key. I tried the following query to get this, but it will list all other keys except primary keys.
SELECT a.constraint_name,a.table_name
FROM ALL_CONS_COLUMNS A
JOIN ALL_CONSTRAINTS C
ON A.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE not in('P')
and a.owner ='my_schema';
If you only want this for the current user, it's better to user the user_xxx views instead of the all_xxx views.
The following should do what you want:
select ut.table_name
from user_tables ut
where not exists (select 1
from user_constraints ac
where ac.table_name = ut.table_name
and ac.constraint_type = 'P'
);
If you do need this for a different user, then you can use the following.
select at.*
from all_tables at
where not exists (select 1
from all_constraints ac
where ac.owner = at.owner
and ac.table_name = at.table_name
and ac.constraint_type = 'P'
)
and at.owner = 'MY_SCHEMA';
Don't forget that Oracle is case sensitive and that user names are stored in uppercase, so a.owner ='my_schema' will most probably not return anything.
Another way:
select owner,table_name
from all_tables
where owner = 'my_schema'
MINUS
select owner,table_name
from all_constraints
where owner = 'my_schema'
and constraint_type = 'P'
Try like this,
SELECT table_name
FROM all_tables A
WHERE table_name NOT IN
(
SELECT table_name
FROM all_constraints WHERE constraint_type ='P'
)
AND a.owner = 'my_schema';
Select tables.owner || ‘.’ ||
tables.table_name
as table_owner
From all_tables tables,
(Select
owner,
TABLE_NAME,
constraint_type,
CONSTRAINT_NAME
FROM ALL_CONSTRAINTS
WHERE CONSTRAINT_TYPE = ‘P’ /* list of all tables with PK */
) constr
Where tables.owner = constr.owner (+)
And tables.table_name = constr.table_name (+)
and tables.owner <> ‘SYS’
and tables.owner <> ‘SYSTEM’
And constr.owner IS NULL
And constr.table_name IS NULL
ORDER BY 1

left outer join on nullable field with between in join condition (Oracle)

I have two tables as: table1 with fields c1 and dt(nullable); table2 with fields start_dt, end_dt and wk_id. Now I need to perform left outer join between the table1 and table2 to take wk_id such that dt falls between start_dt and end_dt. I applied following condition but some wk_id which shouldn't be NULL are pulled NULL and some rows get repeated.
where nvl(t1.dt,'x') between nvl(t2.start_dt(+), 'x') and nvl(t2.end_dt(+), 'x');
What is wrong with the condition?
select *
from table1 t1
left join table2 t2
on t1.dt between t2.start_dt and t2.end_dt
I recommend you try the new ANSI join syntax.
Also, are you just using 'x' as an example? Or are the dt columns really stored as strings?
It seems you are missing the part "table1 left outer join table2 on table1.some_field = table2.some_field"
Something like this:
select t1.c1, t1.dt, t2.start_dt, t2.end_dt, t2.wk_id
from table1 t1 left outer join table2 t2
on t1.some_field1 = t2.some_field1
where nvl(t1.dt,'x')
between nvl(t2.start_dt, 'x') and
nvl(t2.end_dt, 'x')

How to find tables having foreign key to a table in Oracle?

I plan to delete data from a table, I would like to know how many and which tables have a foreign key reference to this particular table in Oracle. As I will have to set the foreign keys to null. I would like to know list of all tables which have a FK to this particular table.
SELECT
FK.OWNER||'.'||FK.TABLE_NAME AS CHILD_TABLE,
SRC.OWNER||'.'||SRC.TABLE_NAME AS PARENT_TABLE,
FK.CONSTRAINT_NAME AS FK_CONSTRAINT,
SRC.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT
FROM ALL_CONSTRAINTS FK
JOIN ALL_CONSTRAINTS SRC ON FK.R_CONSTRAINT_NAME = SRC.CONSTRAINT_NAME
WHERE
FK.CONSTRAINT_TYPE = 'R'
AND SRC.OWNER = 'MY_SCHEMA'
AND SRC.TABLE_NAME = 'MY_TABLE';
I have a situation where the table I'm interested in isn't owned by the schema I was connecting as. So I needed to modify the query in the currently accepted answer to use ALL_CONSTRAINTS instead of USER_CONSTRAINTS. In the process, I made a mistake, and I found the accepted answer to be very difficult to read so that I could fix it. (The lack of explanation didn't help.) As a result, I ended up coming up with my own query. It's basically the same, but I think it's a bit easier to grok.
FK.CONSTRAINT_TYPE = 'R' filters down FK to a set of foreign key constraints, and the join pairs these foreign keys up with their "Referenced constraint". (The referenced constraint is usually the primary key of the "parent" table.) Finally, we filter down to the parent table we're interested in using SRC.OWNER = 'MY_SCHEMA' AND SRC.TABLE_NAME = 'MY_TABLE'.
Naturally, you can switch this to use USER_CONSTRAINTS if you wish; just remove the SRC.OWNER check and the OWNER prefixes in the SELECT.
SELECT d.table_name,
d.constraint_name "Primary Constraint Name",
b.constraint_name "Referenced Constraint Name"
FROM user_constraints d,
(SELECT c.constraint_name,
c.r_constraint_name,
c.table_name
FROM user_constraints c
WHERE table_name='EMPLOYEES' --your table name instead of EMPLOYEES
AND constraint_type='R') b
WHERE d.constraint_name=b.r_constraint_name
Below query will give all the foreign key constraints defined on TABLE_NAME:
select baseTable.* from all_constraints baseTable , all_constraints referentedTable
where baseTable.R_CONSTRAINT_NAME = referentedTable.CONSTRAINT_NAME
and baseTable.constraint_type = 'R'
and referentedTable.table_name = 'TABLE_NAME';
Maybe I misunderstood what Walker asked, but what I understood is : How to find tables that have a foreign key reference to a particular table (ex : EMPLOYEES).
If I try Kupa's answer :
select d.table_name,
d.constraint_name "Primary Constraint Name",
b.constraint_name "Referenced Constraint Name"
from user_constraints d,
(select c.constraint_name,
c.r_constraint_name,
c.table_name
from user_constraints c
where table_name='EMPLOYEES' --your table name instead of EMPLOYEES
and constraint_type='R') b
where d.constraint_name=b.r_constraint_name
I get the tables on which EMPLOYEES have a foreign key reference to.
EMPLOYEES.foreign_key => TABLES.primary_key
See below the updated sql to retrieve the tables that have a foreign key reference to EMPLOYEES.
TABLES.foreign_key => EMPLOYEES.primary_key
select b.table_name "Table Name",
b.constraint_name "Constraint Name",
d.table_name "Referenced Table Name",
d.constraint_name "Referenced Constraint Name"
from user_constraints d,
(select c.constraint_name,
c.r_constraint_name,
c.table_name
from user_constraints c
where constraint_type='R') b
where d.table_name = 'EMPLOYEES' --your table name instead of EMPLOYEES
and b.r_constraint_name = d.constraint_name;
If you also need the fields to be included:
select b.table_name "Referencing Table",
b.CONSTRAINT_NAME "Referencing Constraint",
(select wm_concat(column_name)
from all_cons_columns
where owner = b.owner
and constraint_name = b.CONSTRAINT_NAME
) "Referencing Columns",
a.CONSTRAINT_NAME "Referenced Constraint",
(select wm_concat(column_name)
from all_cons_columns
where owner = a.owner
and constraint_name = a.CONSTRAINT_NAME
) "Referenced columns"
from all_constraints a,
all_constraints b
where a.owner = b.r_owner
and a.owner = '<<OWNER>>'
and a.table_name = '<<TABLE_NAME>>'
and a.constraint_type in ('P', 'U')
and b.constraint_type = 'R'
and b.R_CONSTRAINT_NAME = a.constraint_name
There is no need to do this step manually - you can just use a cascading delete.
SELECT a.table_name, a.column_name, a.constraint_name, c.owner,
-- referenced pk
c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
AND c.r_constraint_name = c_pk.constraint_name
WHERE c.constraint_type = 'R'
AND a.table_name = :TableName
SELECT CONSTRAINT_NAME from ALL_CONSTRAINTS WHERE OWNER= sys_context('userenv','current_schema') AND CONSTRAINT_TYPE='R';

Resources