我正在尝试识别从数据库中删除表格的风险。
数据库很大,包含数百个表。
我有一个返回与表关联的外键的查询。所以我可以提供我想要删除的表名,它告诉我哪些表依赖于它拥有的列。所以我还必须删除返回的表。
我的问题是,因为我需要删除这些表,我希望看到任何其他表依赖于初始结果。
因此我相信我需要我的查询来循环调用自己的最后一次运行的结果,直到没有更多的独特结果。
这可能吗?有没有更简单的方法呢?
编辑:这是查询:
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
答案 0 :(得分:2)
您可以尝试使用CTE。我发现在最终的select语句中编写实际的where子句更容易,但如果性能是个问题,我建议你在relations
CTE (在UNION ALL上面)上写where子句
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
答案 1 :(得分:0)
我想你可以创建一个全局临时表,其中包含表名和已处理标志的字段,并添加初始表名。使用要删除的表的初始种子调用代码。将结果插入临时表。然后迭代临时表中的值,将结果添加到临时表中,确保不会在完成时插入重复项并将每个重复项标记为已处理。继续,直到处理表中的每个记录。
答案 2 :(得分: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>
它只是一个想法来解决你的场景而不是完整的解决方案。