If I have a table, TableA:
Id
1
2
3
...
And two other tables:
TableB:
Id, TableAId
1 1
2 1
TableC:
Id, TableAId
1, 1
2, 2
Where TableAId is a FK relationship with TableA.Id.
How do I determine that TableA, Id 1, has three rows pointing to it? And that TableA, Id 2 has one row pointing to it? And more specifically, how do I identify what those rows are? (their table name and Id)
You can use the INFORMATION_SCHEMA
views to generate select statements to display the rows in question. I have only tested this against the tables provided in the question, but it could be expanded to work in cases where the keys are multiple columns.
declare @table_schema nvarchar(50) = 'dbo',
@table_name nvarchar(50) = 'TableA',
@id int = 1
select fk_col.TABLE_SCHEMA, fk_col.TABLE_NAME, fk_col.COLUMN_NAME,
'select * from ' + fk_col.TABLE_SCHEMA + '.' + fk_col.TABLE_NAME + ' t1 '
+ ' inner join ' + @table_schema + '.' + @table_name + ' t2 '
+ ' on t1.' + fk_col.COLUMN_NAME + ' = t2.' + pk_col.COLUMN_NAME
+ ' where t2.' + pk_col.COLUMN_NAME + ' = ' + cast(@id as nvarchar)
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE pk_col
on pk.CONSTRAINT_SCHEMA = pk_col.CONSTRAINT_SCHEMA
and pk.CONSTRAINT_NAME = pk_col.CONSTRAINT_NAME
join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS fk
on pk.CONSTRAINT_SCHEMA = fk.UNIQUE_CONSTRAINT_SCHEMA
and pk.CONSTRAINT_NAME = fk.UNIQUE_CONSTRAINT_NAME
join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE fk_col
on fk_col.CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA
and fk_col.CONSTRAINT_NAME = fk.CONSTRAINT_NAME
where pk.TABLE_SCHEMA = @table_schema
and pk.TABLE_NAME = @table_name
and pk.CONSTRAINT_TYPE = 'PRIMARY KEY'
The select statements generated:
select * from dbo.TableB t1 inner join dbo.TableA t2 on t1.TableAId = t2.Id where t2.Id = 1
select * from dbo.TableC t1 inner join dbo.TableA t2 on t1.TableAId = t2.Id where t2.Id = 1
and the query results:
Id TableAId Id
----------- ----------- -----------
1 1 1
2 1 1
Id TableAId Id
----------- ----------- -----------
1 1 1
I don't have SQL on this computer so I can't give You exact code but here is the way you should go. Please, note that I will use SQL Server terminology.
I see no way to do this without dynamic sql, at least in SQL Server.
FK_TBL_NM
, FK_CLMN_VAL
.It should not be difficult to get all the fk relationships for pk of TableA:
SELECT * FROM sys.foreign_keys
WHERE referenced_object_id = OBJECT_ID('TableA')
Use a cursor to iterate thru the result of this query and for each generate and execute dynamic sql that will join TableA
and table retrieved from cursor and returns FK_TBL_NM
(TableB, TableC, ...) and value of fk column.
Insert the result into #t (it is tricky to get dynamic sql result into table but do a research on stackoverflow)
Now you have the table that contains one row for each row in TableB
, TableC
, ...
I know this is feasible because I wrote the code with similar logic for my current project at work just few days ago.
Note that you should probably make your code work with pk/fk with more that one column. Also there are different data types for columns. It complicates things a bit but it is possible.
Every step I listed above is not difficult to implement. However, if you have any difficulties, search on stackoverflow :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With