Sql Server 2000 - Query a Table's Foreign Key Relationships

SQL Server 2000 - Query a Table’s Foreign Key relationships

SELECT o2.name
FROM sysobjects o
INNER JOIN sysforeignkeys fk on o.id = fk.rkeyid
INNER JOIN sysobjects o2 on fk.fkeyid = o2.id
WHERE o.name = 'foo'

SQL 2000: T-SQL to get foreign key relationships for a table

DECLARE @tableName sysname

SET @tableName = '' -- Your table name goes here

SELECT
c.name
, target.name
, targetc.name
FROM
-- source table
sysobjects t
-- source column
INNER JOIN syscolumns c ON t.id = c.id
-- general constraint
INNER JOIN sysconstraints co ON t.id = co.id AND co.colid = c.colid
-- foreign key constraint
INNER JOIN sysforeignkeys fk ON co.constid = fk.constid
-- target table
INNER JOIN sysobjects target ON fk.rkeyid = target.id
-- target column
INNER JOIN syscolumns targetc ON fk.rkey = targetc.colid AND fk.rkeyid = targetc.id
WHERE
t.name = @tableName

NOTE I have I think used only those system views available in SQL 2000 (ie the sysXXX ones rather than the SQL 2005 sys.XXX ones) but I have only actually tested this in a SQL 2005 environemnt.

Query to get all foreign key constraints in SQL Server 2000

select * from sysobjects
where xtype = 'F'

That should do the trick and be compatible with SQL Server 2000, I hope!

If you additionally need the table and column information in SQL Server 2000, it gets a bit more involved; you need to join the sysforeignkeys and syscolumns catalog views like so:

select
so.name 'foreign key name',
OBJECT_NAME(parent_obj) 'table',
OBJECT_NAME(sf.fkeyid) 'referencing table',
sc1.name 'referencing column',
OBJECT_NAME(sf.rkeyid) 'referenced table',
sc2.name 'referenced column'
from sysobjects so
inner join sysforeignkeys sf on so.id = sf.constid
inner join syscolumns sc1 on sf.fkeyid = sc1.id and sf.fkey = sc1.colid
inner join syscolumns sc2 on sf.rkeyid = sc2.id and sf.fkey = sc2.colid
where so.xtype in ('F','PK')

And if you want to leverage the INFORMATION_SCHEMA views which ARE indeed available in SQL Server 2000, use this query:

SELECT
rc.CONSTRAINT_NAME,
rcu.TABLE_NAME 'Referencing Table',
rcu.COLUMN_NAME 'Referencing Column',
rcu1.TABLE_NAME 'Referenced Table',
rcu1.COLUMN_NAME 'Referenced Column'
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
INNER JOIN
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE rcu
ON rc.CONSTRAINT_CATALOG = rcu.CONSTRAINT_CATALOG
AND rc.CONSTRAINT_NAME = rcu.CONSTRAINT_NAME
INNER JOIN
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE rcu1
ON rc.UNIQUE_CONSTRAINT_CATALOG = rcu1.CONSTRAINT_CATALOG
AND rc.UNIQUE_CONSTRAINT_NAME = rcu1.CONSTRAINT_NAME

Marc

Query a Table's Foreign Key relationships

This should work (or something close):

select table_name
from all_constraints
where constraint_type='R'
and r_constraint_name in
(select constraint_name
from all_constraints
where constraint_type in ('P','U')
and table_name='<your table here>');

given a foreign key, how do i find all tables that use that particular key?

Try this - this is the more up-to-date, SQL Server 2005 and newer version of my original answer that Mitch linked to (that was for SQL Server 2000):

SELECT
ConstraintName = fk.name,
TableName = t.name,
ColumnName = c.name
FROM
sys.foreign_keys fk
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
sys.tables t ON fk.parent_object_id = t.object_id
INNER JOIN
sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id
INNER JOIN
sys.tables tref ON fk.referenced_object_id = tref.object_id
INNER JOIN
sys.columns cref ON fkc.referenced_object_id = cref.object_id AND fkc.referenced_column_id = cref.column_id
WHERE
tref.Name = 'Person'
AND cref.Name = 'OID'

It uses the system catalog views sys.foreign_keys and sys.foreign_key_columns to find out which tables/columns reference that table and column you're interested in.

You just basically type in the table name and the column name in the WHERE clause - and you get your list of other tables/columns referencing that table/column

How can I find unindexed foreign keys in SQL Server

Here is an answer that works for SQL Server 2000 authored by a co-worker:

/*
Description:
This script outputs a table with all the current database un-indexed foreign keys.

The table has three columns ( TableName , ColumnName, ForeignKeyName )
TableName: The table containing the un-indexed foreign key
ColumnName: The foreign key column that’s not indexed
ForeignKeyName: Name of foreign key witch column doesn’t have an index
*/
DECLARE
@TableName varchar(255),
@ColumnName varchar(255),
@ForeignKeyName sysname

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DECLARE FKColumns_cursor CURSOR Fast_Forward FOR
SELECT cu.TABLE_NAME, cu.COLUMN_NAME, cu.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS ic
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON ic.CONSTRAINT_NAME = cu.CONSTRAINT_NAME
WHERE ic.CONSTRAINT_TYPE = 'FOREIGN KEY'

CREATE TABLE #temp1(
TableName varchar(255),
ColumnName varchar(255),
ForeignKeyName sysname
)

OPEN FKColumns_cursor
FETCH NEXT FROM FKColumns_cursor INTO @TableName, @ColumnName, @ForeignKeyName

WHILE @@FETCH_STATUS = 0
BEGIN

IF ( SELECT COUNT(*)
FROM sysobjects o
INNER JOIN sysindexes x ON x.id = o.id
INNER JOIN syscolumns c ON o.id = c.id
INNER JOIN sysindexkeys xk ON c.colid = xk.colid AND o.id = xk.id AND x.indid = xk.indid
WHERE o.type in ('U')
AND xk.keyno <= x.keycnt
AND permissions(o.id, c.name) <> 0
AND (x.status&32) = 0
AND o.name = @TableName
AND c.name = @ColumnName
) = 0
BEGIN
INSERT INTO #temp1 SELECT @TableName, @ColumnName, @ForeignKeyName
END

FETCH NEXT FROM FKColumns_cursor INTO @TableName, @ColumnName, @ForeignKeyName
END
CLOSE FKColumns_cursor
DEALLOCATE FKColumns_cursor

SELECT * FROM #temp1 ORDER BY TableName

Know relationships between all the tables of database in SQL Server

Sometimes, a textual representation might also help; with this query on the system catalog views, you can get a list of all FK relationships and how the link two tables (and what columns they operate on).

SELECT
fk.name 'FK Name',
tp.name 'Parent table',
cp.name, cp.column_id,
tr.name 'Refrenced table',
cr.name, cr.column_id
FROM
sys.foreign_keys fk
INNER JOIN
sys.tables tp ON fk.parent_object_id = tp.object_id
INNER JOIN
sys.tables tr ON fk.referenced_object_id = tr.object_id
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
sys.columns cp ON fkc.parent_column_id = cp.column_id AND fkc.parent_object_id = cp.object_id
INNER JOIN
sys.columns cr ON fkc.referenced_column_id = cr.column_id AND fkc.referenced_object_id = cr.object_id
ORDER BY
tp.name, cp.column_id

Dump this into Excel, and you can slice and dice - based on the parent table, the referenced table or anything else.

I find visual guides helpful - but sometimes, textual documentation is just as good (or even better) - just my 2 cents.....

SQLServer: How to sort table names ordered by their foreign key dependency

Thank you for a working solution NXC. You put me on the right track to solve the problem using a recursive CTE.

WITH 
TablesCTE(TableName, TableID, Ordinal) AS
(
SELECT
OBJECT_SCHEMA_NAME(so.id) +'.'+ OBJECT_NAME(so.id) AS TableName,
so.id AS TableID,
0 AS Ordinal
FROM dbo.sysobjects so INNER JOIN sys.all_columns ac ON so.ID = ac.object_id
WHERE
so.type = 'U'
AND
ac.is_rowguidcol = 1
UNION ALL
SELECT
OBJECT_SCHEMA_NAME(so.id) +'.'+ OBJECT_NAME(so.id) AS TableName,
so.id AS TableID,
tt.Ordinal + 1 AS Ordinal
FROM
dbo.sysobjects so
INNER JOIN sys.all_columns ac ON so.ID = ac.object_id
INNER JOIN sys.foreign_keys f
ON (f.parent_object_id = so.id AND f.parent_object_id != f.referenced_object_id)
INNER JOIN TablesCTE tt ON f.referenced_object_id = tt.TableID
WHERE
so.type = 'U'
AND
ac.is_rowguidcol = 1
)
SELECT DISTINCT
t.Ordinal,
t.TableName
FROM TablesCTE t
INNER JOIN
(
SELECT
TableName as TableName,
Max (Ordinal) as Ordinal
FROM TablesCTE
GROUP BY TableName
) tt ON (t.TableName = tt.TableName AND t.Ordinal = tt.Ordinal)
ORDER BY t.Ordinal, t.TableName

For thoose wondering what this is useable for: I will use it to safely empty a database without violating any foreign key relations. (By truncating in descending order)
I will also be able to safely fill the tables with data from another database by filling the tables in ascending order.

How to Create a real one-to-one relationship in SQL Server

I'm pretty sure it is technically impossible in SQL Server to have a True 1 to 1 relationship, as that would mean you would have to insert both records at the same time (otherwise you'd get a constraint error on insert), in both tables, with both tables having a foreign key relationship to each other.

That being said, your database design described with a foreign key is a 1 to 0..1 relationship. There is no constraint possible that would require a record in tableB. You can have a pseudo-relationship with a trigger that creates the record in tableB.

So there are a few pseudo-solutions

First, store all the data in a single table. Then you'll have no issues in EF.

Or Secondly, your entity must be smart enough to not allow an insert unless it has an associated record.

Or thirdly, and most likely, you have a problem you are trying to solve, and you are asking us why your solution doesn't work instead of the actual problem you are trying to solve (an XY Problem).

UPDATE

To explain in REALITY how 1 to 1 relationships don't work, I'll use the analogy of the Chicken or the egg dilemma. I don't intend to solve this dilemma, but if you were to have a constraint that says in order to add a an Egg to the Egg table, the relationship of the Chicken must exist, and the chicken must exist in the table, then you couldn't add an Egg to the Egg table. The opposite is also true. You cannot add a Chicken to the Chicken table without both the relationship to the Egg and the Egg existing in the Egg table. Thus no records can be every made, in a database without breaking one of the rules/constraints.

Database nomenclature of a one-to-one relationship is misleading. All relationships I've seen (there-fore my experience) would be more descriptive as one-to-(zero or one) relationships.

UPDATE EF 5.0 - one-to-one Support

While SQL Server will still allow the dependent row to be null. Entity Framework Core 5.0 now allows you to configure dependent properties as required. EF 5 What's new

Excerpt:

In EF Core 5.0, a navigation to an owned entity can be configured as a required dependent. For example:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>(b =>
{
b.OwnsOne(e => e.HomeAddress,
b =>
{
b.Property(e => e.City).IsRequired();
b.Property(e => e.Postcode).IsRequired();
});
b.Navigation(e => e.HomeAddress).IsRequired();
});
}


Related Topics



Leave a reply



Submit