我需要在SQL Server数据库中删除一个高度引用的表。我如何才能得到所有外键约束的列表,我将需要删除以便删除表?

(SQL比在管理工作室的GUI中点击更可取)


当前回答

以下的解决方案对我来说很有效:

--Eliminar las llaves foraneas
declare @query varchar(8000)
declare cursorRecorrerTabla cursor for

SELECT  'ALTER TABLE [PoaComFinH].['+sch.name+'].['+referencingTable.Name+'] DROP CONSTRAINT ['+foreignKey.name+']' 'query'
FROM PoaComFinH.sys.foreign_key_columns fk
JOIN PoaComFinH.sys.tables referencingTable ON fk.parent_object_id = referencingTable.object_id
JOIN PoaComFinH.sys.schemas sch ON referencingTable.schema_id = sch.schema_id
JOIN PoaComFinH.sys.objects foreignKey ON foreignKey.object_id = fk.constraint_object_id
JOIN PoaComFinH.sys.tables referencedTable ON fk.referenced_object_id = referencedTable.object_id


--3ro. abrir el cursor.
open cursorRecorrerTabla
fetch next from cursorRecorrerTabla
into @query
while @@fetch_status = 0
begin
--inicio cuerpo del cursor
    print @query
    exec(@query)
--fin cuerpo del cursor
fetch next from cursorRecorrerTabla
into @query
end
--cerrar cursor
close cursorRecorrerTabla
deallocate cursorRecorrerTabla

其他回答

最简单的方法是使用sys。SQL中的foreign_keys_columns。这里的表包含了所有外键的对象ID,包括它们的引用列ID、引用表ID以及引用列和表。由于Id保持不变,因此对于Schema和表中的进一步修改,结果将是可靠的。

查询:

SELECT    
OBJECT_NAME(fkeys.constraint_object_id) foreign_key_name
,OBJECT_NAME(fkeys.parent_object_id) referencing_table_name
,COL_NAME(fkeys.parent_object_id, fkeys.parent_column_id) referencing_column_name
,OBJECT_SCHEMA_NAME(fkeys.parent_object_id) referencing_schema_name
,OBJECT_NAME (fkeys.referenced_object_id) referenced_table_name
,COL_NAME(fkeys.referenced_object_id, fkeys.referenced_column_id) 
referenced_column_name
,OBJECT_SCHEMA_NAME(fkeys.referenced_object_id) referenced_schema_name
FROM sys.foreign_key_columns AS fkeys

我们还可以使用where添加过滤器

WHERE OBJECT_NAME(fkeys.parent_object_id) = 'table_name' AND 
OBJECT_SCHEMA_NAME(fkeys.parent_object_id) = 'schema_name'

这个答案建立在sp_fkeys的基础上,但格式化类似于sp_fkeys,适用于多个列并列出它们的顺序。

SELECT fk_obj.name    AS FK_NAME,
       pk_schema.name AS PKTABLE_OWNER,
       pk_table.name  AS PKTABLE_NAME,
       pk_column.name AS PKCOLUMN_NAME,
       fk_schema.name AS FKTABLE_OWNER,
       fk_table.name  AS FKTABLE_NAME,
       fk_column.name AS FKCOLUMN_NAME,
       ROW_NUMBER() over (
           PARTITION BY fk_obj.name, fk_schema.name
           ORDER BY fkc.constraint_column_id
           )          AS KEY_SEQ
FROM sys.foreign_key_columns fkc
         INNER JOIN sys.objects fk_obj
                    ON fk_obj.object_id = fkc.constraint_object_id
         INNER JOIN sys.tables fk_table
                    ON fk_table.object_id = fkc.parent_object_id
         INNER JOIN sys.schemas fk_schema
                    ON fk_table.schema_id = fk_schema.schema_id
         INNER JOIN sys.columns fk_column
                    ON fk_column.column_id = parent_column_id
                        AND fk_column.object_id = fk_table.object_id
         INNER JOIN sys.tables pk_table
                    ON pk_table.object_id = fkc.referenced_object_id
         INNER JOIN sys.schemas pk_schema
                    ON pk_table.schema_id = pk_schema.schema_id
         INNER JOIN sys.columns pk_column
                    ON pk_column.column_id = fkc.referenced_column_id
                        AND pk_column.object_id = pk_table.object_id;

下面是我将使用的SQL代码。

SELECT 
   f.name AS 'Name of Foreign Key',
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Fieldname',
   OBJECT_NAME(t.object_id) AS 'References Table name',
   COL_NAME(t.object_id,fc.referenced_column_id) AS 'References fieldname',

   'ALTER TABLE [' + OBJECT_NAME(f.parent_object_id) + ']  DROP CONSTRAINT [' + f.name + ']' AS 'Delete foreign key',

   'ALTER TABLE [' + OBJECT_NAME(f.parent_object_id) + ']  WITH NOCHECK ADD CONSTRAINT [' + 
        f.name + '] FOREIGN KEY([' + COL_NAME(fc.parent_object_id,fc.parent_column_id) + ']) REFERENCES ' + 
        '[' + OBJECT_NAME(t.object_id) + '] ([' +
        COL_NAME(t.object_id,fc.referenced_column_id) + '])' AS 'Create foreign key'
    -- , delete_referential_action_desc AS 'UsesCascadeDelete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
AND OBJECT_NAME(t.object_id) = 'Employees'      --  Just show the FKs which reference a particular table
ORDER BY 2

这不是特别清晰的SQL,所以让我们看一个例子。

所以,假设我想删除Microsoft心爱的Northwind数据库中的Employees表,但是SQL Server告诉我一个或多个外键阻止我这样做。

上面的SQL命令将返回这些结果…

它显示有3个外键引用雇员表。换句话说,除非先删除这三个外键,否则不允许删除(删除)这个表。

在结果中,第一行是以下外键约束在结果中的显示方式。

ALTER TABLE [dbo].[Employees]  WITH NOCHECK 
ADD CONSTRAINT [FK_Employees_Employees] FOREIGN KEY([ReportsTo])
REFERENCES [dbo].[Employees] ([EmployeeID])

倒数第二列显示了我需要使用的SQL命令来删除这些外键之一,例如:

ALTER TABLE [Employees] DROP CONSTRAINT [FK_Employees_Employees]

...右边一列显示了创建它的SQL…

ALTER TABLE [Employees] WITH NOCHECK 
ADD CONSTRAINT [FK_Employees_Employees] 
FOREIGN KEY([ReportsTo]) REFERENCES [Employees] ([EmployeeID])

使用所有这些命令,您就拥有了删除相关外键所需的一切,从而可以删除表,然后再重新创建它们。

唷。希望这能有所帮助。

最初的问题要求将所有外键的列表放入一个高度引用的表中,以便可以删除表。

这个小查询返回将所有外键放入特定表所需的“drop foreign key”命令:

SELECT 
   'ALTER TABLE ['+sch.name+'].['+referencingTable.Name+'] DROP CONSTRAINT ['+foreignKey.name+']' '[DropCommand]'
FROM sys.foreign_key_columns fk
    JOIN sys.tables referencingTable ON fk.parent_object_id = referencingTable.object_id
    JOIN sys.schemas sch ON referencingTable.schema_id = sch.schema_id
    JOIN sys.objects foreignKey ON foreignKey.object_id = fk.constraint_object_id
    JOIN sys.tables referencedTable ON fk.referenced_object_id = referencedTable.object_id
WHERE referencedTable.name = 'MyTableName'

示例输出:

[DropCommand]
ALTER TABLE [dbo].[OtherTable1] DROP CONSTRAINT [FK_OtherTable1_MyTable]
ALTER TABLE [dbo].[OtherTable2] DROP CONSTRAINT [FK_OtherTable2_MyTable]

省略where -子句以获取当前数据库中所有外键的删除命令。

第一个

EXEC sp_fkeys 'Table', 'Schema'

然后使用NimbleText处理你的结果