Как я могу перечислить все внешние ключи, ссылающиеся на данную таблицу в SQL Server? - PullRequest
647 голосов
/ 27 января 2009

Мне нужно удалить таблицу с высокими ссылками в базе данных SQL Server. Как я могу получить список всех ограничений внешнего ключа, которые мне нужно будет удалить, чтобы удалить таблицу?

(ответы на SQL предпочтительнее, чем нажатие в графическом интерфейсе студии управления.)

Ответы [ 22 ]

1001 голосов
/ 18 октября 2012

Не знаю, почему никто не предложил, но я использую sp_fkeys для запроса внешних ключей для данной таблицы:

EXEC sp_fkeys 'TableName'

Вы также можете указать схему:

EXEC sp_fkeys @pktable_name = 'TableName', @pktable_owner = 'dbo'

Без указания схемы в docs указано следующее:

Если pktable_owner не указан, правила видимости таблицы по умолчанию применяются базовые СУБД.

В SQL Server, если текущий пользователь владеет таблицей с указанным name, столбцы этой таблицы возвращаются. Если pktable_owner нет указан и текущий пользователь не владеет таблицей с указанным pktable_name, процедура ищет таблицу с указанным pktable_name принадлежит владельцу базы данных. Если существует, эта таблица столбцы возвращаются.

214 голосов
/ 27 января 2009

Я бы использовал функцию создания диаграмм базы данных в SQL Server Management Studio, но так как вы исключили это - это сработало для меня в SQL Server 2008 (нет 2005).

Чтобы получить список имен ссылающихся таблиц и столбцов ...

select 
    t.name as TableWithForeignKey, 
    fk.constraint_column_id as FK_PartNo, c.
    name as ForeignKeyColumn 
from 
    sys.foreign_key_columns as fk
inner join 
    sys.tables as t on fk.parent_object_id = t.object_id
inner join 
    sys.columns as c on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id
where 
    fk.referenced_object_id = (select object_id 
                               from sys.tables 
                               where name = 'TableOthersForeignKeyInto')
order by 
    TableWithForeignKey, FK_PartNo

Чтобы получить имена ограничений внешнего ключа

select distinct name from sys.objects where object_id in 
(   select fk.constraint_object_id from sys.foreign_key_columns as fk
    where fk.referenced_object_id = 
        (select object_id from sys.tables where name = 'TableOthersForeignKeyInto')
)
159 голосов
/ 21 сентября 2013

Это дает вам:

  • Сам ФК
  • Схема, к которой принадлежит ФК
  • « справочная таблица » или таблица с FK
  • " ссылающийся столбец " или столбец внутри ссылочной таблицы, который указывает на FK
  • « ссылочная таблица » или таблица с ключевым столбцом, на который указывает ваш FK
  • « ссылка на столбец » или столбец, который является ключом, на который указывает ваш FK

Код ниже:

SELECT  obj.name AS FK_NAME,
    sch.name AS [schema_name],
    tab1.name AS [table],
    col1.name AS [column],
    tab2.name AS [referenced_table],
    col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
    ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
    ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
    ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
    ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
    ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
    ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
138 голосов
/ 27 января 2009

Попробуйте это:

sp_help 'TableName'
47 голосов
/ 01 апреля 2013

Вы также должны учитывать ссылки на другие объекты.

Если на таблицу ссылались другие таблицы, чем на нее, вероятно, ссылаются другие объекты, такие как представления, хранимые процедуры, функции и т. Д.

Я бы действительно порекомендовал инструмент GUI, такой как диалоговое окно «Просмотр зависимостей» в SSMS, или бесплатный инструмент, такой как ApexSQL Search , для этого, потому что поиск зависимостей в других объектах может быть подвержен ошибкам, если вы хотите это сделать только с SQL.

Если SQL является единственным вариантом, вы можете попробовать сделать это следующим образом.

select O.name as [Object_Name], C.text as [Object_Definition]
from sys.syscomments C
inner join sys.all_objects O ON C.id = O.object_id
where C.text like '%table_name%'
21 голосов
/ 12 февраля 2015

Исходный вопрос, заданный для получения списка всех внешних ключей в таблицу с высокими ссылками, чтобы ее можно было удалить.

Этот небольшой запрос возвращает все команды «удаления внешнего ключа», необходимые для удаления всех внешних ключей в конкретную таблицу:

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, чтобы получить команды удаления для всех внешних ключей в текущей базе данных.

17 голосов
/ 03 мая 2017

Вот код 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, поэтому давайте рассмотрим пример.

Итак, предположим, что я хотел удалить таблицу Employees в любимой базе данных Microsoft Northwind, но SQL Server сказал мне, что один или несколько внешних ключей мешали мне сделать это.

Команда SQL, приведенная выше, вернет эти результаты ...

Foreign Keyes

Это показывает, что есть 3 внешних ключа, которые ссылаются на таблицу Employees. Другими словами, мне не разрешили бы удалить (удалить) эту таблицу, пока эти три внешних ключа не будут сначала удалены.

В результатах первая строка показывает, как в результатах будет показано следующее ограничение внешнего ключа.

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 для create it ...

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

Со всеми этими командами у вас есть все, что нужно для удаления соответствующих внешних ключей, чтобы вы могли удалить таблицу, а затем воссоздать их позже.

Уф. Надеюсь, это поможет.

16 голосов
/ 06 августа 2009
SELECT PKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       PKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O1.SCHEMA_ID)),
       PKTABLE_NAME = CONVERT(SYSNAME,O1.NAME),
       PKCOLUMN_NAME = CONVERT(SYSNAME,C1.NAME),
       FKTABLE_QUALIFIER = CONVERT(SYSNAME,DB_NAME()),
       FKTABLE_OWNER = CONVERT(SYSNAME,SCHEMA_NAME(O2.SCHEMA_ID)),
       FKTABLE_NAME = CONVERT(SYSNAME,O2.NAME),
       FKCOLUMN_NAME = CONVERT(SYSNAME,C2.NAME),
       -- Force the column to be non-nullable (see SQL BU 325751)
       --KEY_SEQ             = isnull(convert(smallint,k.constraint_column_id), sysconv(smallint,0)),
       UPDATE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsUpdateCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       DELETE_RULE = CONVERT(SMALLINT,CASE OBJECTPROPERTY(F.OBJECT_ID,'CnstIsDeleteCascade') 
                                        WHEN 1 THEN 0
                                        ELSE 1
                                      END),
       FK_NAME = CONVERT(SYSNAME,OBJECT_NAME(F.OBJECT_ID)),
       PK_NAME = CONVERT(SYSNAME,I.NAME),
       DEFERRABILITY = CONVERT(SMALLINT,7)   -- SQL_NOT_DEFERRABLE
FROM   SYS.ALL_OBJECTS O1,
       SYS.ALL_OBJECTS O2,
       SYS.ALL_COLUMNS C1,
       SYS.ALL_COLUMNS C2,
       SYS.FOREIGN_KEYS F
       INNER JOIN SYS.FOREIGN_KEY_COLUMNS K
         ON (K.CONSTRAINT_OBJECT_ID = F.OBJECT_ID)
       INNER JOIN SYS.INDEXES I
         ON (F.REFERENCED_OBJECT_ID = I.OBJECT_ID
             AND F.KEY_INDEX_ID = I.INDEX_ID)
WHERE  O1.OBJECT_ID = F.REFERENCED_OBJECT_ID
       AND O2.OBJECT_ID = F.PARENT_OBJECT_ID
       AND C1.OBJECT_ID = F.REFERENCED_OBJECT_ID
       AND C2.OBJECT_ID = F.PARENT_OBJECT_ID
       AND C1.COLUMN_ID = K.REFERENCED_COLUMN_ID
       AND C2.COLUMN_ID = K.PARENT_COLUMN_ID
12 голосов
/ 04 ноября 2011
SELECT
  object_name(parent_object_id),
  object_name(referenced_object_id),
  name 
FROM sys.foreign_keys
WHERE parent_object_id = object_id('Table Name')
10 голосов
/ 22 октября 2018

Самый простой способ - использовать sys.foreign_keys_columns в SQL. Здесь таблица содержит идентификаторы объектов всех внешних ключей по идентификатору ссылочной колонки, идентификатору ссылочной таблицы, а также ссылочным столбцам и таблицам. Поскольку идентификатор остается постоянным, результат будет надежным для дальнейших изменений в схеме и таблицах.

Запрос:

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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...