3

我正在尝试确定从数据库中删除表的风险。

数据库很大,包含数百个表。

我有一个返回与表关联的外键的查询。所以我可以给它提供我想删除的表名,它会告诉我哪些表依赖于它拥有的列。所以我还必须删除返回的表。

我的问题是,因为我需要删除这些表,所以我想查看依赖于初始结果的任何其他表。

因此,我相信我需要我的查询循环调用它上次运行的结果,直到没有更多独特的结果。

这可能吗?有没有更简单的方法来做到这一点?

编辑:这是查询:

SELECT
      PK.TABLE_NAME AS PrimaryTable,
      FK.TABLE_NAME AS ForeignTable,
      PT.COLUMN_NAME AS PrimaryColumn,
      CU.COLUMN_NAME AS ForeignColumn,
      C.CONSTRAINT_NAME AS ConstraintName
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
WHERE PK.TABLE_NAME IN
('Table1','Table2')
ORDER BY
1,2,3,4
4

3 回答 3

2

您可以尝试使用 CTE。我发现在最终的 select 语句上编写实际的 where 子句更容易,但如果性能是一个问题,我建议您在relationsCTE上编写 where 子句(在 UNION ALL 之上)

CTE 选择语句

;WITH q AS (
  SELECT
        PK.TABLE_NAME AS PrimaryTable,
        FK.TABLE_NAME AS ForeignTable,
        PT.COLUMN_NAME AS PrimaryColumn,
        CU.COLUMN_NAME AS ForeignColumn,
        C.CONSTRAINT_NAME AS ConstraintName
  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
)
, Relations AS (
  SELECT  PrimaryTable AS Root
          , *
  FROM    q
  UNION ALL
  SELECT  r.Root
          , q.PrimaryTable
          , q.ForeignTable
          , q.PrimaryColumn
          , q.ForeignColumn
          , q.ConstraintName
  FROM    q
          INNER JOIN Relations r ON r.ForeignTable = q.PrimaryTable
)
SELECT  *
FROM    Relations
WHERE   Root IN ('Table1','Table2')
ORDER BY
1,2,3,4
于 2013-02-04T14:09:01.717 回答
0

我想你可以创建一个全局临时表,其中包含表名字段和已处理标志,并添加初始表名。使用要删除的表的初始种子调用您的代码。将结果插入临时表。然后遍历临时表中的值,将结果添加到临时表中,确保不插入重复项,并在完成后将每个项标记为已处理。继续,直到处理完表中的每条记录。

于 2013-02-04T12:32:06.363 回答
0

试试这样的..

DECLARE @tablename varchar
DECLARE @flag bit
SET @tablename = 'some_table_name'
SET @flag-1
WHILE EXISTS(SELECT PK.TABLE_NAME AS PrimaryTable,
  FK.TABLE_NAME AS ForeignTable,
  PT.COLUMN_NAME AS PrimaryColumn,
  CU.COLUMN_NAME AS ForeignColumn . . . where PK.TABLE_NAME = @tablename)
  begin
   SET @flag=0
   SET @tablename=<assign the tables with fk referred by primarykey tables>
  end
IF(@flag=1)
 <delete query>

它只是解决您的场景的一个想法,而不是完整的解决方案。

于 2013-02-04T13:51:38.797 回答