Como posso descobrir qual restrição FOREIGN KEY faz referência a uma tabela no SQL Server?

121

Estou tentando derrubar uma mesa, mas recebo a seguinte mensagem:

Msg 3726, nível 16, estado 1, linha 3
Não foi possível descartar o objeto 'dbo.UserProfile' porque ele é referenciado por uma restrição FOREIGN KEY.
Msg 2714, nível 16, estado 6, linha 2
Já existe um objeto denominado 'UserProfile' no banco de dados.

Procurei no SQL Server Management Studio, mas não consigo encontrar a restrição. Como posso descobrir as restrições de chave estrangeira?

marc_s
fonte
2
Eu gosto de sp_help 'dbo.TableName' Veja aqui mais maneiras: stackoverflow.com/questions/483193/…
Mark Boltuc
2
Worth noticing:A resposta de @LittleSweetSeas retornará informações sobre as chaves estrangeiras PARA uma determinada tabela referenciada , no entanto, os detalhes da resposta de @Gayathri-Varma para uma determinada tabela pai . Ambos são úteis em contextos diferentes e ambos ganham sua própria corrida :-)
Izhar Aazmi

Respostas:

225

Aqui está:

SELECT 
   OBJECT_NAME(f.parent_object_id) TableName,
   COL_NAME(fc.parent_object_id,fc.parent_column_id) ColName
FROM 
   sys.foreign_keys AS f
INNER JOIN 
   sys.foreign_key_columns AS fc 
      ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN 
   sys.tables t 
      ON t.OBJECT_ID = fc.referenced_object_id
WHERE 
   OBJECT_NAME (f.referenced_object_id) = 'YourTableName'

Dessa forma, você obterá a tabela de referência e o nome da coluna.

Editado para usar sys.tables em vez de sys.objects genéricos de acordo com a sugestão de comentário. Obrigado, marc_s

LittleSweetSeas
fonte
Você deve usar o mais focado em sys.tablesvez desys.objects
marc_s
@marc_s: Obrigado, mas você poderia postar um exemplo? AFAIK em sys.tables eu não tenho referências FK
LittleSweetSeas
3
O que eu quis dizer: apenas substitua INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_idporINNER JOIN sys.tables t ON t.OBJECT_ID = fc.referenced_object_id
marc_s
@LittleSweetSeas eu executei a consulta acima e ainda não estou obtendo o object_name e o nome da coluna da tabela que tinha uma restrição de chave estrangeira
Smart003
Você poderia reforçar sua seleção com um pouco mais de informações: SELECT f.name ConstraintName, f.type_desc ConstraintType, OBJECT_NAME (f.parent_object_id) ConstrainedTable, COL_NAME (fc.parent_object_id, fc.parent_column_id) ConstrainedColumnable_object_objectable , COL_NAME (fc.referenced_object_id, fc.referenced_column_id) ReferencedColumn
DocOc
74

Outra maneira é verificar os resultados de

sp_help 'TableName'

(ou apenas destaque o TableName citado e pressione ALT + F1)

Com o passar do tempo, decidi refinar minha resposta. Abaixo está uma captura de tela dos resultados que sp_helpfornece. A usei o banco de dados AdventureWorksDW2012 para este exemplo. Existem inúmeras informações boas lá, e o que estamos procurando está no final - destacado em verde:

insira a descrição da imagem aqui

Vladislav
fonte
3
+1 Isso dá muitas informações úteis e mostra as chaves estrangeiras na parte inferior da saída
Hux
1
Isso me dá muitas informações no menor número de linhas de código
Rennish Joseph
Este é o atalho mais legal! Vence completamente o Ctl-R para atualizar o esquema!
Sr. Young
Atualizar cache local do InteliSense = Ctrl + Shift + R; Ctrl + R = mostrar / ocultar painel de resultados (ou pelo menos esses são meus padrões para SSMS2008 e SSMS2014)
Vladislav
44

Tente isto

SELECT
  object_name(parent_object_id) ParentTableName,
  object_name(referenced_object_id) RefTableName,
  name 
FROM sys.foreign_keys
WHERE parent_object_id = object_id('Tablename')
Gayathri L
fonte
1
Curto e elegante, mais funciona para mim! A única coisa é que o namevalor retornado é um nome interno (methinks), e não o nome da coluna real na tabela pai. Algum jeito de arrumar isso?
Hamman Samuel
O que eu vejo aqui é que o ParentTableNameseria sempre o mesmo que o ' Tablename' fornecido na cláusula where (se incluído). Isso pode ser intencional e será mais útil quando consultado por mais de uma tabela.
Izhar Aazmi
28

Achei essa resposta muito simples e fiz o que eu precisava: https://stackoverflow.com/a/12956348/652519

Um resumo do link, use esta consulta:

EXEC sp_fkeys 'TableName'

Rápido e simples. Consegui localizar todas as tabelas de chave estrangeira, respectivas colunas e nomes de chave estrangeira de 15 tabelas muito rapidamente.

Como @mdisibio observado abaixo, aqui está um link para a documentação que detalha os diferentes parâmetros que podem ser usados: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp- fkeys-transact-sql

Michael
fonte
1
Existem cinco outros parâmetros para filtrar, o mais útil dos quais saber é o segundo onde você pode especificar um esquema não padrão, por exemploEXEC sp_fkeys 'Payroll', 'accounting'
mdisibio
8

Estou usando este script para encontrar todos os detalhes relacionados à chave estrangeira. Estou usando o INFORMATION.SCHEMA. Abaixo está um script SQL:

SELECT 
    ccu.table_name AS SourceTable
    ,ccu.constraint_name AS SourceConstraint
    ,ccu.column_name AS SourceColumn
    ,kcu.table_name AS TargetTable
    ,kcu.column_name AS TargetColumn
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
    INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
        ON ccu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
        ON kcu.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME  
ORDER BY ccu.table_name
Anvesh
fonte
2
Eu estava procurando uma maneira de ver as colunas que são chaves estrangeiras e as tabelas relacionadas que a coluna faz referência, e isso resume tudo muito bem. Obrigado!
Nate Kindrew,
Faltavam algumas chaves estrangeiras em algumas das minhas tabelas enquanto a resposta de @LittleSweetSeas as mostrava
Seafish
7

se você quiser ir via SSMS na janela do explorador de objetos, clique com o botão direito do mouse no objeto que deseja soltar e visualize as dependências.

Luis LL
fonte
7

Esta é a melhor maneira de descobrir o relacionamento de chave estrangeira em todos os bancos de dados.

exec sp_helpconstraint 'Table Name'

e mais uma forma

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME='Table Name'
--and left(CONSTRAINT_NAME,2)='FK'(If you want single key)
Vinoth_S
fonte
Esta solução exec sp_helpconstraint 'Table Name'é a única que retorna alguma linha para mim. No entanto, o nome da restrição é jargão. PRIMARY KEY (clustered) PK__org_soft__3213E83FE6B07364
Tor
5
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;
Murali_DBA
fonte
1

--O que se segue pode dar-lhe mais do que procura:

create Procedure spShowRelationShips 
( 
    @Table varchar(250) = null,
    @RelatedTable varchar(250) = null
)
as
begin
    if @Table is null and @RelatedTable is null
        select  object_name(k.constraint_object_id) ForeginKeyName, 
                object_name(k.Parent_Object_id) TableName, 
                object_name(k.referenced_object_id) RelatedTable, 
                c.Name RelatedColumnName,  
                object_name(rc.object_id) + '.' + rc.name RelatedKeyField
        from sys.foreign_key_columns k
        left join sys.columns c on object_name(c.object_id) = object_name(k.Parent_Object_id) and c.column_id = k.parent_column_id
        left join sys.columns rc on object_name(rc.object_id) = object_name(k.referenced_object_id) and rc.column_id = k.referenced_column_id
        order by 2,3

    if @Table is not null and @RelatedTable is null
        select  object_name(k.constraint_object_id) ForeginKeyName, 
                object_name(k.Parent_Object_id) TableName, 
                object_name(k.referenced_object_id) RelatedTable, 
                c.Name RelatedColumnName,  
                object_name(rc.object_id) + '.' + rc.name RelatedKeyField
        from sys.foreign_key_columns k
        left join sys.columns c on object_name(c.object_id) = object_name(k.Parent_Object_id) and c.column_id = k.parent_column_id
        left join sys.columns rc on object_name(rc.object_id) = object_name(k.referenced_object_id) and rc.column_id = k.referenced_column_id
        where object_name(k.Parent_Object_id) =@Table
        order by 2,3

    if @Table is null and @RelatedTable is not null
        select  object_name(k.constraint_object_id) ForeginKeyName, 
                object_name(k.Parent_Object_id) TableName, 
                object_name(k.referenced_object_id) RelatedTable, 
                c.Name RelatedColumnName,  
                object_name(rc.object_id) + '.' + rc.name RelatedKeyField
        from sys.foreign_key_columns k
        left join sys.columns c on object_name(c.object_id) = object_name(k.Parent_Object_id) and c.column_id = k.parent_column_id
        left join sys.columns rc on object_name(rc.object_id) = object_name(k.referenced_object_id) and rc.column_id = k.referenced_column_id
        where object_name(k.referenced_object_id) =@RelatedTable
        order by 2,3



end
Mike
fonte
1

Você também pode retornar todas as informações sobre Foreign Keysadaptando a resposta @LittleSweetSeas:

SELECT 
   OBJECT_NAME(f.parent_object_id) ConsTable,
   OBJECT_NAME (f.referenced_object_id) refTable,
   COL_NAME(fc.parent_object_id,fc.parent_column_id) ColName
FROM 
   sys.foreign_keys AS f
INNER JOIN 
   sys.foreign_key_columns AS fc 
      ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN 
   sys.tables t 
      ON t.OBJECT_ID = fc.referenced_object_id
order by
ConsTable
usuário1
fonte
1

No SQL Server Management Studio, você pode clicar com o botão direito do mouse na tabela no explorador de objetos e selecionar "Exibir dependências". Isso lhe daria um bom ponto de partida. Ele mostra tabelas, visualizações e procedimentos que fazem referência à tabela.

Darrel Lee
fonte
0

tente a seguinte consulta.

select object_name(sfc.constraint_object_id) AS constraint_name,
       OBJECT_Name(parent_object_id) AS table_name ,
       ac1.name as table_column_name,
       OBJECT_name(referenced_object_id) as reference_table_name,      
       ac2.name as reference_column_name
from  sys.foreign_key_columns sfc
join sys.all_columns ac1 on (ac1.object_id=sfc.parent_object_id and ac1.column_id=sfc.parent_column_id)
join sys.all_columns ac2 on (ac2.object_id=sfc.referenced_object_id and ac2.column_id=sfc.referenced_column_id) 
where sfc.parent_object_id=OBJECT_ID(<main table name>);

isso dará o constraint_name, column_names que estará se referindo e as tabelas que dependerão da restrição estarão lá.

Smart003
fonte
0

Você pode usar esta consulta para exibir as Foreign keyrestrições:

SELECT
K_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME,
Constraint_Name = C.CONSTRAINT_NAME
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
---- optional:
ORDER BY
1,2,3,4
WHERE PK.TABLE_NAME='YourTable'

Retirado de http://blog.sqlauthority.com/2006/11/01/sql-server-query-to-display-foreign-key-relationships-and-name-of-the-constraint-for-each-table- no banco de dados /

usuário1
fonte
0

A maneira mais fácil de obter Primary Keye obter Foreign Keyuma mesa é:

/*  Get primary key and foreign key for a table */
USE DatabaseName;

SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE CONSTRAINT_NAME LIKE 'PK%' AND
TABLE_NAME = 'TableName'

SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE CONSTRAINT_NAME LIKE 'FK%' AND
TABLE_NAME = 'TableName'
Ashraf Abusada
fonte
0

No Object Explorer, expanda a tabela e expanda as Chaves:

insira a descrição da imagem aqui

Hank Z
fonte