0

我需要列出所有相互依赖的表

例子

TableA 与 TableB 具有外键关系 TableB 与 TableA 具有外键关系

到目前为止,我得到了查找表的外键关系的脚本,但是如何过滤它们以仅获取交叉表引用之一。

我的脚本是:

SELECT  CAST(p.name AS VARCHAR(255)) AS [Primary Table] ,
            CAST(c.name AS VARCHAR(255)) AS [Foreign Table]
    FROM    sysobjects f
            INNER JOIN sysobjects c ON f.parent_obj = c.id
            INNER JOIN sysreferences r ON f.id = r.constid
            INNER JOIN sysobjects p ON r.rkeyid = p.id
            INNER  JOIN syscolumns rc ON r.rkeyid = rc.id
                                         AND r.rkey1 = rc.colid
            INNER  JOIN syscolumns fc ON r.fkeyid = fc.id
                                         AND r.fkey1 = fc.colid
            LEFT JOIN syscolumns rc2 ON r.rkeyid = rc2.id
                                        AND r.rkey2 = rc.colid
            LEFT JOIN syscolumns fc2 ON r.fkeyid = fc2.id
                                        AND r.fkey2 = fc.colid
    WHERE   f.type = 'F'
    ORDER BY CAST(p.name AS VARCHAR(255))
4

1 回答 1

0

这个简单的 select 语句返回数据库中的循环直接外键引用:

IF OBJECT_ID('dbo.d') IS NOT NULL DROP TABLE dbo.d;
IF OBJECT_ID('dbo.c') IS NOT NULL DROP TABLE dbo.c;
IF OBJECT_ID('dbo.b') IS NOT NULL 
BEGIN
  ALTER TABLE dbo.a DROP CONSTRAINT [dbo.a(bid)->dbo.b(bid)];
  DROP TABLE dbo.b;
END
IF OBJECT_ID('dbo.a') IS NOT NULL DROP TABLE dbo.a;
CREATE TABLE dbo.a(aid INT PRIMARY KEY CLUSTERED, bid INT);
CREATE TABLE dbo.b(aid INT CONSTRAINT [dbo.b(aid)->dbo.a(aid)] REFERENCES dbo.a(aid), bid INT PRIMARY KEY CLUSTERED);
ALTER TABLE dbo.a ADD CONSTRAINT [dbo.a(bid)->dbo.b(bid)] FOREIGN KEY(bid) REFERENCES dbo.b(bid);
CREATE TABLE dbo.c(cid INT PRIMARY KEY CLUSTERED);
CREATE TABLE dbo.d(did INT PRIMARY KEY CLUSTERED, cid INT CONSTRAINT [dbo.d(cid)->dbo.c(cid)] REFERENCES dbo.c(cid));

SELECT * 
 FROM sys.foreign_keys fk1
 JOIN sys.foreign_keys fk2
 ON fk1.parent_object_id = fk2.referenced_object_id
 AND fk2.parent_object_id = fk1.referenced_object_id;

从这里您可以加入 DMVsys.tablessys.columns获取其他信息,例如表和列名称。

有两点需要注意:

  1. 您应该停止使用兼容性视图。它们用于支持为 SQL 2000 编写的旧脚本,不应在新开发中使用。

  2. 外键中最多可以有 16 列。您的脚本仅支持两个。但是,您甚至没有返回列名,因此如果您不需要列名,则根本不应该加入 sys.columns。

如果您只需要表的名称,则可以使用以下 select 语句而不需要额外的连接:

SELECT 
   QUOTENAME(OBJECT_SCHEMA_NAME(fk1.parent_object_id))+'.'+QUOTENAME(OBJECT_NAME(fk1.parent_object_id))+
   ' <-> '+
   QUOTENAME(OBJECT_SCHEMA_NAME(fk1.referenced_object_id))+'.'+QUOTENAME(OBJECT_NAME(fk1.referenced_object_id))
  FROM sys.foreign_keys fk1
  JOIN sys.foreign_keys fk2
  ON fk1.parent_object_id = fk2.referenced_object_id
  AND fk2.parent_object_id = fk1.referenced_object_id
  AND fk1.parent_object_id < fk1.referenced_object_id;

我还在查询的 WHERE 子句中添加了一个附加条件,以使每对只包含一次。

于 2013-08-12T02:30:11.653 回答