How to find constraints for existing table? - sql

How to find integrity constraints (such as primary key)
for an existing table? I am using Oracle 10g.

To find constraints on a table:
select constraint_name, constraint_type
from user_constraints
where table_name = 'YOUR_TABLE'
There are matching dictionary views , ALL_ and DBA_, if you need to find constraints on tables in other schemas.
The four constraint types are
P Primary key
U Unique
R Foreign key (reference)
C Check
Check constraints include things which we don't immediately think of as constraints, such as NOT NULL.
So, to find the primary key on a table...
select constraint_name, constraint_type
from user_constraints
where table_name = 'YOUR_TABLE'
and c.constraint_type = 'P'
To find the table referenced in a foreign key:
select c.constraint_name as foreign_key
, c.r_constraint_name as referenced_constraint
, p.table_name
from user_constraints c
join user_constraints p
on p.constraint_name = c.r_constraint_name
where c.table_name = 'YOUR_TABLE'
and c.constraint_type = 'R'
/

You need to query the data dictionary, specifically the USER_CONS_COLUMNS view to see the table columns and corresponding constraints:
SELECT * FROM user_cons_columns WHERE table_name = '<your table name in caps>';

It you are trying to find info about the data model, use a tool built for the job.
Download SQL Developer

Related

How to know if a foreign key has cascade on delete clause

Due to a misconception of the PostgreSQL database I work with everyday, on the 155 tables that the schema of the database contains, some tables with foreign key doesn't have the 'on delete cascade' clause which cause serious trouble as you can expect.
I would like to correct this and with PGAdmin I'm able to see all FK of a table but not if the FK as the clause. Instead of, for each tables, dropping manually each FK and creating new ones with the 'on delete cascade', I would like to know how, for a specific table, the full definition of the foreign keys. Like this I will not drop foreign keys that already has the clause.
You can look in pg_constraint:
postgres=# create table car (id int primary key, name text);
CREATE TABLE
postgres=# create table driver (id int, car int references car(id) on delete cascade);
CREATE TABLE
postgres=# select connamespace, conname, c.relname as child_table, p.relname as parent_table, confdeltype
from pg_constraint
join pg_class c on c.oid=conrelid
join pg_class p on p.oid=confrelid;
connamespace | conname | child_table | parent_table | confdeltype
--------------+-----------------+-------------+--------------+-------------
2200 | driver_car_fkey | driver | car | c
(1 row)
This will show you all the foreign keys (along with their source and target tables) that do not have ON DELETE CASCADE:
select connamespace, conname, c.relname as child_table, p.relname as parent_table, confdeltype
from pg_constraint
join pg_class c on c.oid=conrelid
join pg_class p on p.oid=confrelid
where confdeltype <> 'c';
More information in the documentation
Disclosure: I work for EnterpriseDB (EDB)
This query will show all foreign constraints that are defined without cascading delete and the tables on which they are defined:
SELECT conname AS constraint_name,
conrelid::regclass AS table
FROM pg_constraint
WHERE contype = 'f'
AND confdeltype <> 'c';
Constraints can be queried from pg_constraint. Foreign key constraints have an 'f' in the column contype. The delete action can be taken from the column confdeltype. For cascading action it holds a 'c'. So you want all constraints where contype is 'f' and confdeltype isn't 'c'.
You can join pg_class for the involved tables and pg_namespace for their schemas. That way you can also limit the search to the tables of a specific schema.
In conkey the referencing and in confkey the referenced are stored as array of the ordinal numbers of the columns in the respective table. You can get the names from pg_attribute.
The following query would give you all foreign key constraints on any table in the schema public which's delete action isn't cascade along with the tables' schema names and the columns involved in the constraint.
SELECT con.conname,
con.confdeltype,
nsp.nspname,
rel.relname,
(SELECT array_agg(att.attname ORDER BY un.ord)
FROM unnest(con.conkey) WITH ORDINALITY un (attnum, ord)
INNER JOIN pg_attribute att
ON att.attnum = un.attnum
WHERE att.attrelid = rel.oid) conkeyattnames,
fnsp.nspname,
frel.relname,
(SELECT array_agg(att.attname ORDER BY un.ord)
FROM unnest(con.confkey) WITH ORDINALITY un (attnum, ord)
INNER JOIN pg_attribute att
ON att.attnum = un.attnum
WHERE att.attrelid = frel.oid) confkeyattnames
FROM pg_constraint con
INNER JOIN pg_class rel
ON rel.oid = con.conrelid
INNER JOIN pg_namespace nsp
ON nsp.oid = rel.relnamespace
INNER JOIN pg_class frel
ON frel.oid = con.confrelid
INNER JOIN pg_namespace fnsp
ON fnsp.oid = frel.relnamespace
WHERE con.contype = 'f'
AND con.confdeltype <> 'c'
AND nsp.nspname = 'public';

How to sort inserts on multiple tables on Oracle so that no FK constraint is broken

I need to bring a DB from Oracle 12 to Oracle 11. I created all DDL for objects using SQL Explorer and after some minor adjustments it worked fine. But as I exported the data I got a bunch of inserts sorted by table name as shown bellow.
#C:\Users\RubensdoAmaralNeto\DBScripts\TABLE_A.sql
#C:\Users\RubensdoAmaralNeto\DBScripts\TABLE_B.sql
#C:\Users\RubensdoAmaralNeto\DBScripts\TABLE_C.sql
...
If I try to run it as is, it won't work because it breaks many FK constraints.
Is there a way to sort those inserts, other then manually doing the job? Maybe using SQL Explorer or SQLPlus. There are more then 150 tables that are related each other.
Here's a recursive CTE that I think should list all your tables in the order that you should do the inserts. Assuming that all tables are in your current schema. Anything with a lvl of 0 can be run in any order.
with t (table_name, lvl) as (
-- tables with no foreign keys on them
select table_name, 0 as lvl from user_tables where table_name not in (select table_name from user_constraints where constraint_type = 'R')
union all -- tables with foreign keys pointing to previous tables
select c.table_name as table_name, t.lvl+1 as lvl
from t
join user_constraints r on r.table_name = t.table_name
join user_constraints c
on c.constraint_type = 'R'
and r.constraint_name = c.r_constraint_name
) cycle table_name set is_cycle to 1 default 0
select table_name, lvl,
'#C:\Users\RubensdoAmaralNeto\DBScripts\' || table_name || '.sql' as script
from t
order by lvl;
Just copy & paste the third column into a text file and save the script.

ORACLE SQL get all target table columns where source table is referenced as a FK

Using: Oracle SQL Developer
Hi I try to explain my Problem with a simple example:
I need a Oracle SQL Query that returns me all Foreign Key related columns from all child tables ( Table Employee and Table Building) that reference the parent table Table Organizational unit
The result for my example would look like this:
SELECT All COLUMNS OF All Tables THAT have an entry referenced as foreign key for table Table Organizational unit
WHERE Table Organizational unit.Code = 'HR'
--Result
Table Building
ID , ORG_UNIT_REF, Building Type
152, 2 , Main Building
Table Employee
ID, ORG_UNIT_REF, Employee Name
13, 2 , Max Doe
This means all Tables with their table name, column names and matching column contents have to be printed out.
I already found all the Referening tables and Constraint names by using this answer
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
For my example the above query gives me something like that:
"TABLE_NAME","CONSTRAINT_NAME","STATUS","OWNER"
"Table Employee","FK_CONSTRAINT","ENABLED","TESTSCHEMA"
"Table Building","FK_CONST","ENABLED","TESTSCHEMA"
Now I know all the child tables that reference my parent table Organizational unit. Now I also want a query that fetches me all the rows in all the tables where the foreign key matches.

How can I get Database name, Size, Table name, Objects, Indexes, Check Constraints, Foreign keys in a single query

I am looking for a query to get all the details as mentioned in Subject. I am sure there should be one developed with the same requirement.
select user schema,'1.FIELDS' obj, null name, c.TABLE_NAME,c.COLUMN_ID col_order,c.COLUMN_NAME,
c.DATA_TYPE,c.DATA_LENGTH,c.DATA_PRECISION,c.DATA_SCALE,c.NULLABLE,null condition
from user_tab_columns c
union all
select user,'2.INDEX '||uniqueness,index_name,table_name,i.column_position, i.column_name,null,
null,null,null,null,null
from user_ind_columns i inner join user_indexes using(table_name,index_name)
union all
select user,'3.CONSTR', constraint_name, table_name, csc.position, csc.column_name,null,null,
null,null,null,cs.search_condition
from user_constraints cs inner join user_cons_columns csc using (table_name,constraint_name)
where constraint_type='C'
union all
select user,'4.FK', constraint_name, table_name, csc.position, csc.column_name||'->'||r_constraint_name,
null,null,null,null,null,cs.search_condition
from user_constraints cs inner join user_cons_columns csc using (table_name,constraint_name)
where constraint_type='R'
order by 4, 2, 3, 5
This will show information regarding to all tables in the curren schema. For each table it shows 1) fields 2) indexes 3) constraints 4) foreign keys

Find referenced field(s) of foreign key constraint

I have a table Users with a field called org_id which is a foreign key to a table organisation, with primary key field organisation_id. Knowing the table name (users) and the field name (users.org_id), is there a query that can tell me the name and field that org_id references?
I've found a Stackoverflow post similar to this where a query was provided to determine the referenced table name, but I also need to know the field name that is referenced:
SELECT c.confrelid::regclass::text AS referenced_table
,c.conname AS fk_name
,pg_get_constraintdef(c.oid) AS fk_definition
FROM pg_attribute a
JOIN pg_constraint c ON (c.conrelid, c.conkey[1]) = (a.attrelid, a.attnum)
WHERE a.attrelid = '"Schema"."Users"'::regclass -- table name
AND a.attname = 'org_id' -- column name
AND c.contype = 'f'
ORDER BY conrelid::regclass::text, contype DESC;
So the above query would return the name of the table (organisation), the fk name and fk definition. Is there a way to also get the name of the field that is referenced? I know I could probably perform another query to determine the name of pk given a table but I would like to avoid performing multiple queries for this.
This query adds the referenced column(s) for the foreign key constraint:
SELECT c.confrelid::regclass::text AS referenced_table
,string_agg(f.attname, ', ') AS referenced_columns
,c.conname AS fk_name
,pg_get_constraintdef(c.oid) AS fk_definition
FROM pg_attribute a
JOIN pg_constraint c ON (c.conrelid, c.conkey[1]) = (a.attrelid, a.attnum)
JOIN pg_attribute f ON f.attrelid = c.confrelid
AND f.attnum = ANY (confkey)
WHERE a.attrelid = '"Schema"."Users"'::regclass -- table name
AND a.attname = 'org_id' -- column name
AND c.contype = 'f'
GROUP BY c.confrelid, c.conname, c.oid;
A fk constraint can reference multiple columns. That's the reason for the aggregate function string_agg() in the query.