I have written a query to find out column names of tables in the database.
SELECT
t.NAME AS TABLEName,
SCHEMA_NAME(schema_id) + '.' + c.name AS ColumnName
FROM
sys.tables t
INNER JOIN sys.columns c
ON c.object_id = t.object_id
WHERE OBJECT_NAME(c.object_id) LIKE '%Message%'
ORDER BY t.NAME
So far I've got the expected result, but whatever column I am looking I want to find out the dependency of column related tables. By executing the above query I am getting table names and column names.
How can I get the column related dependent tables?
Try this:
SELECT KCU1.TABLE_CATALOG,
KCU1.TABLE_SCHEMA,
KCU1.TABLE_NAME,
KCU1.COLUMN_NAME,
KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME,
KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU1
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC
ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG
AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU2
ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG
AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA
AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME
AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION
WHERE KCU1.TABLE_NAME LIKE '%Message%'
ORDER BY
KCU1.TABLE_NAME,
KCU1.COLUMN_NAME
This might help. You will however need to tweak it a bit to suit your specific need:
SELECT OBJECT_NAME(referenced_major_id) AS ReferingObject,
(SELECT o.type_Desc FROM sys.objects o
WHERE o.object_id = d.referenced_major_id) AS ReferingObjType,
CASE WHEN referenced_minor_id <> 0 THEN COL_NAME(referenced_major_id, referenced_minor_id)
ELSE '' END AS RefColumnName,
OBJECT_NAME(object_ID) AS ReferencedObject,
(SELECT o.type_Desc FROM sys.objects o
WHERE o.object_id = d.object_id) AS ReferedObjType
fROM sys.sql_dependencies d
If you're looking for all tables/columns that reference a column in the table whose name contains token Message, you can use this:
;WITH PT AS (
SELECT
tc1.TABLE_NAME,
tc2.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc1
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE tc2
ON tc1.CONSTRAINT_NAME = tc2.CONSTRAINT_NAME
WHERE tc1.CONSTRAINT_TYPE = 'PRIMARY KEY')
SELECT
FK_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME,
Constraint_Name = C.CONSTRAINT_NAME
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
JOIN PT
ON PT.TABLE_NAME = PK.TABLE_NAME
WHERE PK.TABLE_NAME LIKE '%Message%'
ORDER BY
FK.TABLE_NAME,
CU.COLUMN_NAME,
PK.TABLE_NAME,
PT.COLUMN_NAME
Related
I am writing a query to get all the tables in the db with their properties but also foreign keys and table that each reference to. I have a following query but it is taking 60 min to complete. Not sure what am I doing wrong?
SELECT
ist.table_name,
isc.column_name,
data_type,
character_maximum_length,
Columnproperty(Object_id(isc.table_name),
isc.column_name, 'IsIdentity') AS identityFlag,
is_nullable,
character_maximum_length,
numeric_scale,
(SELECT 1
FROM information_schema.table_constraints AS C
JOIN information_schema.key_column_usage AS K ON C.table_name = K.table_name
AND C.constraint_catalog = K.constraint_catalog
AND C.constraint_schema = K.constraint_schema
AND C.constraint_name = K.constraint_name
WHERE C.constraint_type = 'PRIMARY KEY'
AND C.table_name = isc.table_name
AND K.column_name = isc.column_name) AS primarykey,
(SELECT TOP 1 1
FROM information_schema.table_constraints AS C
JOIN information_schema.key_column_usage AS K ON C.table_name = K.table_name
AND C.constraint_catalog = K.constraint_catalog
AND C.constraint_schema = K.constraint_schema
AND C.constraint_name = K.constraint_name
WHERE C.constraint_type = 'FOREIGN KEY'
AND C.table_name = isc.table_name
AND K.column_name = isc.column_name) AS foreignKey,
a.parenttablename AS foreignTableName,
a.colname AS foreignColumnName
FROM
information_schema.tables ist
INNER JOIN
information_schema.columns isc ON ist.table_name = isc.table_name
LEFT OUTER JOIN
(SELECT
t.NAME AS parentTableName,
Object_name(f.parent_object_id) TableName,
Col_name(fc.parent_object_id, fc.parent_column_id) ColName
FROM
sys.foreign_keys AS f
INNER JOIN
sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
INNER JOIN
sys.tables t ON t.object_id = fc.referenced_object_id) a ON a.tablename = ist.table_name
AND a.colname = isc.column_name
It is taking time to find the foreign table names. What is the best way to get db table schema
Firstly, you should stick to the sys schema, as these catalog views are more efficient, and INFORMATION_SCHEMA is only for compatibility
You are over-complicating it. You don't need to query the foreign key twice, you can just check if the LEFT JOIN succeeded by checking for NULL
SELECT
t.name AS table_name,
c.name AS column_name,
typ.name AS data_type,
c.max_length,
c.is_identity AS identityFlag,
c.is_nullable,
c.precision,
c.scale,
CASE WHEN EXISTS (SELECT 1
FROM sys.indexes AS i
JOIN sys.index_columns AS ic
ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
WHERE i.object_id = t.object_id
AND ic.column_id = c.column_id
) THEN 1 ELSE 0 END AS primarykey,
CASE WHEN t_f.name IS NOT NULL THEN 1 ELSE 0 END AS foreignKey,
t_f.name AS foreignTableName,
c_f.name AS foreignColumnName
FROM
sys.tables t
INNER JOIN
sys.columns c ON c.object_id = t.object_id
INNER JOIN
sys.types typ ON typ.user_type_id = c.user_type_id
LEFT OUTER JOIN
sys.foreign_key_columns AS fc
INNER JOIN
sys.tables t_f ON t_f.object_id = fc.referenced_object_id
INNER JOIN
sys.columns c_f ON c_f.object_id = t_f.object_id
AND c_f.column_id = fc.referenced_column_id
ON fc.parent_object_id = t.object_id
AND fc.parent_column_id = c.column_id;
I am having a problem to list all the foreign keys in a database and show the related tables & the fields from each one.
I have tried this query:
SELECT OBJECT_NAME(parent_object_id)
,OBJECT_NAME(referenced_object_id)
,OBJECT_NAME(object_id)
,*
FROM sys.foreign_keys
But this returns just the parent table and field. I need more information. Can anybody help me here?
You can try the below query from the reference also the reference.
-- using sys tables to enumerate foreign keys
-- returns 45 constraint rows
SELECT
f.name constraint_name
,OBJECT_NAME(f.parent_object_id) referencing_table_name
,COL_NAME(fc.parent_object_id, fc.parent_column_id) referencing_column_name
,OBJECT_NAME (f.referenced_object_id) referenced_table_name
,COL_NAME(fc.referenced_object_id, fc.referenced_column_id) referenced_column_name
,delete_referential_action_desc
,update_referential_action_desc
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.object_id = fc.constraint_object_id
ORDER BY f.name
-- using INFORMATION_SCHEMA to enumerate foreign keys
-- returns 45 constraint rows
SELECT
C.CONSTRAINT_NAME [constraint_name]
,C.TABLE_NAME [referencing_table_name]
,KCU.COLUMN_NAME [referencing_column_name]
,C2.TABLE_NAME [referenced_table_name]
,KCU2.COLUMN_NAME [referenced_column_name]
,RC.DELETE_RULE delete_referential_action_desc
,RC.UPDATE_RULE update_referential_action_desc
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
ON C.CONSTRAINT_SCHEMA = KCU.CONSTRAINT_SCHEMA
AND C.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
ON C.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
AND C.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C2
ON RC.UNIQUE_CONSTRAINT_SCHEMA = C2.CONSTRAINT_SCHEMA
AND RC.UNIQUE_CONSTRAINT_NAME = C2.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2
ON C2.CONSTRAINT_SCHEMA = KCU2.CONSTRAINT_SCHEMA
AND C2.CONSTRAINT_NAME = KCU2.CONSTRAINT_NAME
AND KCU.ORDINAL_POSITION = KCU2.ORDINAL_POSITION
WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY'
ORDER BY C.CONSTRAINT_NAME
To answer your (underlying) question, you can find everything you need in the following system tables:
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
Good luck!
I need to get a list of all foreign keys, which schema/table they belong to, which schema/table they reference, and the name of the column that is referenced. This is what I have so far but the column being returned is not correct. Any ideas?
select distinct
ParentSchema.name as PARENT_SCHEMA_NAME,
ParentTable.name as PARENT_TABLE_NAME,
TheSchema.name as TABLE_SCHEMA,
TheTable.name as TABLE_NAME,
fks.name as KEY_NAME ,
COL_NAME(ParentTable.OBJECT_ID,fkcs.constraint_column_id) as CHILD_COLUMN_NAME
from
sys.foreign_keys fks
inner join
Sys.foreign_key_columns fkcs
on
fks.parent_object_id = fkcs.parent_object_id
inner join
sys.tables TheTable
on
fks.parent_object_id = TheTable.object_id
inner join
sys.tables ParentTable
on
fks.referenced_object_id = ParentTable.object_id
inner join
sys.schemas TheSchema
on
TheTable.schema_id = TheSchema.schema_id
inner join
sys.schemas ParentSchema
on
ParentTable.schema_id = ParentSchema.schema_id
order by
fks.name
I use the following script for getting the information I need related to foreign keys, could be useful for you too:
SELECT KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME
, KCU1.TABLE_NAME AS FK_TABLE_NAME
, KCU1.COLUMN_NAME AS FK_COLUMN_NAME
, KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME
, KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME
, KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU1 ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU2 ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION
WHERE KCU1.TABLE_NAME = 'PurchaseOrders'
For the table PurchaseOrders, in the WideWorldImporters database it shows the following information:
You can check out all the columns included in the information_schema.referential_constraints and
information_schema.key_column_usage and then change the query to fit your needs.
i want to get all columns of table vs an extra column that determine field is Primary Key or not.i'm using this code:
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
in this example tablename is "register".
this code is correct but for primary key field return two records:1
What's the problem?
Added one more required column as details.
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK,
ISNULL(tblCon.CONSTRAINT_TYPE,'') as Detail
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN (select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where (CONSTRAINT_NAME like 'PK_%' or CONSTRAINT_NAME like 'FK_%') and TABLE_NAME='register') AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
This should work
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN (select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_NAME like 'PK_%' and TABLE_NAME='register') AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
Taking the answer from Sagar and cleaning it up considerably. There were two extra joins, I change the subquery to a left join and modified some of the join conditions so the table name only need to be entered once.
SELECT c.column_id AS ID
, c.name AS ItemName
, CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END AS ISPK
FROM sys.tables tb
JOIN sys.columns c ON
tb.object_id = c.object_id
AND tb.[object_id] = c.[object_id]
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K on
CONSTRAINT_NAME like 'PK_%'
and TABLE_NAME = tb.name
AND c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon ON
tblCon.TABLE_NAME = tb.name
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
where tb.name = 'register'
If I have a pair of SQL tables, one of these tables has a pk on one column and a unique index on another (maybe a guid and id or some other unique key).
The other table has an fk to the unique index, not the pk. Is there a way I can query information schema to find the column targeted by the fk?
If I get you right, you want to use metadatabase:
SELECT
K_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME,
Constraint_Name = C.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
SELECT i1.TABLE_NAME, i2.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT ON PT.TABLE_NAME = PK.TABLE_NAME
Source: http://blog.sqlauthority.com/2006/11/01/sql-server-query-to-display-foreign-key-relationships-and-name-of-the-constraint-for-each-table-in-database/
Try this one -
SELECT
column_name = c.name
, table_name = OBJECT_NAME(k.parent_object_id)
, referenced_column_name = rc.name
, referenced_table_name = OBJECT_NAME(k.referenced_object_id)
FROM sys.foreign_key_columns k
JOIN sys.columns c ON c.[object_id] = k.parent_object_id AND c.column_id = k.parent_column_id
JOIN sys.columns rc ON rc.[object_id] = k.referenced_object_id AND rc.column_id = k.referenced_column_id
select object_name(fk.REFERENCED_OBJECT_ID) object_name,
i.name index_name,
ic.index_column_id sequence,
c.name column_name
from sys.foreign_keys fk
join sys.indexes i on i.object_id = fk.REFERENCED_OBJECT_ID
and i.index_id = fk.KEY_INDEX_ID
join sys.index_columns ic on ic.object_id = fk.REFERENCED_OBJECT_ID
and ic.index_id = fk.KEY_INDEX_ID
join sys.columns c on c.object_id = fk.REFERENCED_OBJECT_ID
and c.column_id = ic.column_id
where fk.name = 'fk_tbl2_to_tbl1';
e.g.
Setup:
create table tbl1 (
a int constraint pk_tbl1 primary key,
b int constraint uq_tbl1 unique,
c int);
create table tbl2 (
b int constraint fk_tbl2_to_tbl1 references tbl1(b),
d int);
Results:
| OBJECT_NAME | INDEX_NAME | SEQUENCE | COLUMN_NAME |
-----------------------------------------------------
| tbl1 | uq_tbl1 | 1 | b |
SQL Fiddle Demo
--FIND COLUMNS THAT ARE PRIMARY KEY AS WELL AS FOREIGN KEY - SQL SERVER 2008
SELECT
CU.TABLE_NAME, CU.COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
WHERE CU.CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY') AND
COLUMN_NAME IN (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = CU.TABLE_NAME AND
COLUMN_NAME = CU.COLUMN_NAME AND
CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'))
Source: here