Restrição de chave estrangeira SQL DROP TABLE


154

Se eu quiser excluir todas as tabelas do meu banco de dados como esta, ele cuidará da restrição de chave estrangeira? Se não, como eu cuido disso primeiro?

GO
IF OBJECT_ID('dbo.[Course]','U') IS NOT NULL
    DROP TABLE dbo.[Course]
GO
IF OBJECT_ID('dbo.[Student]','U') IS NOT NULL
    DROP TABLE dbo.[Student]


2
Verifique esta resposta, ele me ajudou;) stackoverflow.com/a/5488670/2205144
xatz

Respostas:


335

Não, isso não descartará sua tabela se houver realmente chaves estrangeiras fazendo referência a ela.

Para obter todos os relacionamentos de chave estrangeira que fazem referência à sua tabela, você pode usar este SQL (se você estiver no SQL Server 2005 e acima):

SELECT * 
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

e, se houver alguma, com esta instrução aqui, você pode criar instruções SQL para realmente eliminar essas relações FK:

SELECT 
    'ALTER TABLE [' +  OBJECT_SCHEMA_NAME(parent_object_id) +
    '].[' + OBJECT_NAME(parent_object_id) + 
    '] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

Nota: a tabela gerada contém as instruções para excluir as restrições individuais a serem executadas em uma consulta diferente. Isso fez maravilhas no meu caso, já que eu precisava me livrar de uma tabela inútil (para fins de teste), mantendo o restante das tabelas que tinham o FK intacto.
Mauricio Quintana

1
Eu tive que usar parent_object_id vez de referenced_object_id
Tom Robinson

2
Uma alternativa à instrução SELECT para obter todas as tabelas de referência é: EXEC sp_fkeys 'Student';
Buggieboy

ajuste pequeno nesta consulta SELECT 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [nome]' FROM sys.foreign_keys WHERE referenced_object_id = object_id ('Student') substitui [name] com nome CONSTRAINT
Stas Svishov

1
Como atribuir sua última seleção como variável e executá-la?
precisa

44

No SQL Server Management Studio 2008 (R2) e mais recente, você pode clicar com o botão direito do mouse no

DB -> Tarefas -> Gerar scripts

  • Selecione as tabelas que você deseja DROP.

  • Selecione "Salvar na nova janela de consulta".

  • Clique no botão Avançado.

  • Defina Script DROP e CREATE como Script DROP.

  • Defina chaves estrangeiras de script como True.

  • Clique OK.

  • Clique em Avançar -> Avançar -> Concluir.

  • Veja o script e depois execute.


12
ainda é o mesmo 'Não foi possível descartar o objeto' minha_tabela 'porque é referenciado por uma restrição FOREIGN KEY.
FrenkyB

6
Como esta resposta tem 28 + classificação é além de mim ... ainda não trabalho mate
AltF4_

1
Embora ele gere o script - esse script não resolve o problema, que é soltar a tabela referenciada por restrições de chave estrangeira.
Alexey Shevelyov

Caiu como uma luva para mim.
Johan

21

Se você soltar a tabela "filho" primeiro, a chave estrangeira será descartada também. Se você tentar soltar a tabela "pai" primeiro, você receberá uma mensagem "Não foi possível soltar o objeto 'a' porque é referenciada por uma restrição FOREIGN KEY". erro.


2
Verdade, mas não há solução. Criança pode ter chaves estrangeiras para outras tabelas e / ou você pode não querer descartá-la em primeiro lugar.
214/09 MaR

4
É verdade, e uma solução se o objetivo é, como afirmou, "Se eu quiser excluir todas as tabelas no meu banco de dados ..."
Philip Kelley

4
esta é uma resposta muito melhor do que o aceite, dado que o interlocutor quer "excluir todas as tabelas no meu banco de dados"
lukkea

17

Aqui está outra maneira de descartar todas as tabelas corretamente, usando o sp_MSdropconstraintsprocedimento O código mais curto que consegui pensar:

exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";

Homem incrível ............
edCoder 15/06

2

Se for o SQL Server, você deve eliminar a restrição antes de poder soltar a tabela.


2

Versão ligeiramente mais genérica do que @mark_s postou, isso me ajudou

SELECT 
'ALTER TABLE ' +  OBJECT_SCHEMA_NAME(k.parent_object_id) +
'.[' + OBJECT_NAME(k.parent_object_id) + 
'] DROP CONSTRAINT ' + k.name
FROM sys.foreign_keys k
WHERE referenced_object_id = object_id('your table')

basta conectar o nome da tabela e executar o resultado.


1
Oi, Eu tenho tentado eliminar minhas restrições de chave estrangeira pelo que foi dito acima, mas quando vou soltar uma tabela depois, ele continua dizendo "Não foi possível soltar o objeto porque ele ainda está sendo referenciado por uma restrição de Chave estrangeira ... Obrigado, desde já.
daniness

1

Aqui está outra maneira de excluir todas as restrições seguidas pelas próprias tabelas, usando um truque de concatenação FOR XML PATH('')que permite mesclar várias linhas de entrada em uma única linha de saída. Deve funcionar em qualquer coisa SQL 2005 e posterior.

Deixei os comandos EXECUTE comentados por segurança.

DECLARE @SQL NVARCHAR(max)
;WITH fkeys AS (
    SELECT quotename(s.name) + '.' + quotename(o.name) tablename, quotename(fk.name) constraintname 
    FROM sys.foreign_keys fk
    JOIN sys.objects o ON fk.parent_object_id = o.object_id
    JOIN sys.schemas s ON o.schema_id = s.schema_id
)
SELECT @SQL = STUFF((SELECT '; ALTER TABLE ' + tablename + ' DROP CONSTRAINT ' + constraintname
FROM fkeys
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

SELECT @SQL = STUFF((SELECT '; DROP TABLE ' + quotename(TABLE_SCHEMA) + '.' + quotename(TABLE_NAME) 
FROM INFORMATION_SCHEMA.TABLES 
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

Isso não funciona bem porque nem todos os FK serão descartados (apenas aqueles em que nossas tabelas são usadas como pai, onde também devemos eliminar restrições onde nossa tabela foi usada como "referenciada").
Roman Pokrovskij

Roman, a postagem original é sobre a exclusão de restrições de chave estrangeira. Minha resposta não visa cobrir nada além disso.
Warren Rumak

1

Aqui está um script completo para implementar uma solução:

create Procedure [dev].DeleteTablesFromSchema
(
    @schemaName varchar(500)
)
As 
begin
    declare @constraintSchemaName nvarchar(128), @constraintTableName nvarchar(128),  @constraintName nvarchar(128)
    declare @sql nvarchar(max)
    -- delete FK first
    declare cur1 cursor for
    select distinct 
    CASE WHEN t2.[object_id] is NOT NULL  THEN  s2.name ELSE s.name END as SchemaName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  t2.name ELSE t.name END as TableName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  OBJECT_NAME(d2.constraint_object_id) ELSE OBJECT_NAME(d.constraint_object_id) END as ConstraintName
    from sys.objects t 
        inner join sys.schemas s 
            on t.[schema_id] = s.[schema_id]
        left join sys.foreign_key_columns d 
            on  d.parent_object_id = t.[object_id]
        left join sys.foreign_key_columns d2 
            on  d2.referenced_object_id = t.[object_id]
        inner join sys.objects t2 
            on  d2.parent_object_id = t2.[object_id]
        inner join sys.schemas s2 
            on  t2.[schema_id] = s2.[schema_id]
    WHERE t.[type]='U' 
        AND t2.[type]='U'
        AND t.is_ms_shipped = 0 
        AND t2.is_ms_shipped = 0 
        AND s.Name=@schemaName
    open cur1
    fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    while @@fetch_status = 0
    BEGIN
        set @sql ='ALTER TABLE ' + @constraintSchemaName + '.' + @constraintTableName+' DROP CONSTRAINT '+@constraintName+';'
        exec(@sql)
        fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    END
    close cur1
    deallocate cur1

    DECLARE @tableName nvarchar(128)
    declare cur2 cursor for
    select s.Name, p.Name
    from sys.objects p
        INNER JOIN sys.schemas s ON p.[schema_id] = s.[schema_id]
    WHERE p.[type]='U' and is_ms_shipped = 0 
    AND s.Name=@schemaName
    ORDER BY s.Name, p.Name
    open cur2

    fetch next from cur2 into @schemaName,@tableName
    while @@fetch_status = 0
    begin
        set @sql ='DROP TABLE ' + @schemaName + '.' + @tableName
        exec(@sql)
        fetch next from cur2 into @schemaName,@tableName
    end

    close cur2
    deallocate cur2

end
go

1
Removing Referenced FOREIGN KEY Constraints
Assuming there is a parent and child table Relationship in SQL Server:

--First find the name of the Foreign Key Constraint:
  SELECT * 
  FROM sys.foreign_keys
  WHERE referenced_object_id = object_id('States')

--Then Find foreign keys referencing to dbo.Parent(States) table:
   SELECT name AS 'Foreign Key Constraint Name', 
           OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id) AS 'Child Table'
   FROM sys.foreign_keys 
   WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
              OBJECT_NAME(referenced_object_id) = 'dbo.State'

 -- Drop the foreign key constraint by its name 
   ALTER TABLE dbo.cities DROP CONSTRAINT FK__cities__state__6442E2C9;

 -- You can also use the following T-SQL script to automatically find 
 --and drop all foreign key constraints referencing to the specified parent 
 -- table:

 BEGIN

DECLARE @stmt VARCHAR(300);

-- Cursor to generate ALTER TABLE DROP CONSTRAINT statements  
 DECLARE cur CURSOR FOR
 SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.' + 
 OBJECT_NAME(parent_object_id) +
                ' DROP CONSTRAINT ' + name
 FROM sys.foreign_keys 
 WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
            OBJECT_NAME(referenced_object_id) = 'states';

 OPEN cur;
 FETCH cur INTO @stmt;

 -- Drop each found foreign key constraint 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    EXEC (@stmt);
    FETCH cur INTO @stmt;
  END

  CLOSE cur;
  DEALLOCATE cur;

  END
  GO

--Now you can drop the parent table:

 DROP TABLE states;
--# Command(s) completed successfully.

0

Usando o SQL Server Manager, você pode eliminar restrições de chave estrangeira da interface do usuário. Se você deseja excluir a tabela, Diarymas a tabela Usuário possui uma chave estrangeira DiaryIdapontando para a Diarytabela, você pode expandir (usando o símbolo de mais) a Usertabela e, em seguida, expandir a Foreign Keysseção. Clique com o botão direito na chave estrangeira que aponta para a tabela do diário e selecione Delete. Você pode expandir a Columnsseção, clicar com o botão direito e excluir a coluna DiaryIdtambém. Então você pode simplesmente executar:

drop table Diary

Sei que sua pergunta real é sobre a exclusão de todas as tabelas, portanto isso pode não ser útil para esse caso. No entanto, se você quiser excluir algumas tabelas, isso é útil, acredito (o título não menciona explicitamente a exclusão de todas as tabelas).


0

Se você estiver em um servidor mysql e não se importar de perder suas tabelas, poderá usar uma consulta simples para excluir várias tabelas de uma vez:

SET foreign_key_checks = 0;
DROP TABLE IF EXISTS table_a,table_b,table_c,table_etc;
SET foreign_key_checks = 1;

Dessa forma, não importa em que ordem você usa a tabela na sua consulta.

Se alguém vai dizer algo sobre o fato de que essa não é uma boa solução se você tiver um banco de dados com muitas tabelas: eu concordo!


ReceboIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt

@ Matt Bit difícil de adivinhar em qual '=' você recebe esse erro.
Els den Iep 8/08/16

3
foreign_key_checksnão funcionará no servidor MSSQL. Eu acho que é uma variável específica do MySQL.
OoXei1sh 11/11

1
@ ooXei1sh Não, não no MSSQL. É por isso que digo no início do meu post: "Se você estiver em um servidor MYSQL".
Els den Iep

0

execute o código abaixo para obter o nome da restrição de chave estrangeira que bloqueia sua queda. Por exemplo, eu pego a rolesmesa.

      SELECT *
      FROM sys.foreign_keys
      WHERE referenced_object_id = object_id('roles');

      SELECT name AS 'Foreign Key Constraint Name',
      OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id)
      AS 'Child Table' FROM sys.foreign_keys
      WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo'
      AND OBJECT_NAME(referenced_object_id) = 'dbo.roles'

você receberá o nome FK como abaixo: FK__Table1__roleId__1X1H55C1

Agora execute o código abaixo para remover a referência FK obtida de cima.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Feito!


-4

Se eu quiser excluir todas as tabelas no meu banco de dados

Então é muito mais fácil descartar o banco de dados inteiro:

DROP DATABASE WorkerPensions

71
Dar -1 para isso, pois não é uma resposta válida para a pergunta, por dois motivos importantes: 1) Exclui muito mais do que tabelas! Procedimentos armazenados, funções, UDTs, segurança, assemblies .NET etc. etc. desaparecem com um DROP DATABASE. 2) Você pode não ter permissão para criar bancos de dados, por exemplo, ambiente de desenvolvimento gerenciado centralmente, onde os bancos de dados são provisionados pela TI e têm requisitos adicionais no momento da criação que você não conhece.
Warren Rumak

-4

Se você deseja DROPuma tabela que tenha sido referenciada por outra tabela usando a chave estrangeira, use

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Eu acho que deveria funcionar para você.


1
não existe cascade constraintsno servidor sql
JackyJohnson 15/02
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.