SQL DROP TABLE restricción de clave externa

154

Si quiero eliminar todas las tablas de mi base de datos de esta manera, ¿se encargará de la restricción de clave externa? Si no, ¿cómo me encargo de eso primero?

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]
Sam
fuente
Mira este enlace
Yordan Georgiev
2
Comprueba esta respuesta, me ayudó;) stackoverflow.com/a/5488670/2205144
xatz

Respuestas:

335

No, esto no eliminará su tabla si de hecho hay claves foráneas que la hacen referencia.

Para obtener todas las relaciones de clave externa que hacen referencia a su tabla, puede usar este SQL (si está en SQL Server 2005 y versiones posteriores):

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

y si hay alguna, con esta declaración aquí, podría crear instrucciones SQL para descartar esas relaciones 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')
marc_s
fuente
Nota: la tabla generada contiene las declaraciones para eliminar las restricciones individuales que se ejecutarán en una consulta diferente. Funcionó de maravilla en mi caso ya que necesitaba deshacerme de una tabla inútil (para fines de prueba) mientras mantenía el resto de las tablas que tenían FK intacta.
Mauricio Quintana
1
Tuve que usar parent_object_id en lugar de referenced_object_id
Tom Robinson
2
Una alternativa a la instrucción SELECT para obtener todas las tablas de referencia es: EXEC sp_fkeys 'Student';
Buggieboy
pequeño ajuste esta consulta SELECCIONE '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') reemplaza [name] con nombre CONSTRAINT
Stas Svishov
1
¿Cómo asignar su última selección como variable y ejecutarla?
Hrvoje T
44

En SQL Server Management Studio 2008 (R2) y versiones posteriores, puede hacer clic derecho en el

DB -> Tareas -> Generar scripts

  • Seleccione las tablas que desea DROP.

  • Seleccione "Guardar en nueva ventana de consulta".

  • Haga clic en el botón Avanzado.

  • Establezca Script DROP y CREATE en Script DROP.

  • Establezca Script Foreign Keys en True.

  • Haga clic en Aceptar.

  • Haga clic en Siguiente -> Siguiente -> Finalizar.

  • Ver el script y luego ejecutar.

Riaan
fuente
12
sigue siendo el mismo 'No se pudo soltar el objeto' my_table 'porque está referenciado por una restricción FOREIGN KEY.
FrenkyB
66
Cómo esta respuesta tiene una calificación de
28+
1
Si bien genera el script, ese script no resuelve el problema, que es descartar la tabla a la que hacen referencia las restricciones de clave externa.
Alexey Shevelyov
Funcionó como un encanto para mí.
Johan
21

Si primero descarta la tabla "secundaria", también se descartará la clave externa. Si intenta descartar primero la tabla "principal", obtendrá un "No se pudo descartar el objeto 'a' porque está referenciado por una restricción FOREIGN KEY". error.

Philip Kelley
fuente
2
Es cierto, pero no hay solución. El niño puede tener claves foráneas para otras mesas y / o puede que no quiera soltarlas en primer lugar.
Marzo
44
Es cierto, y una solución si el objetivo es, como se dijo, "Si quiero eliminar todas las tablas de mi base de datos ..."
Philip Kelley
44
esta es una respuesta mucho mejor que la aceptada, dado que el interlocutor quiere "eliminar todas las tablas de mi base de datos"
lukkea
17

Aquí hay otra forma de soltar todas las tablas correctamente, utilizando el sp_MSdropconstraintsprocedimiento. El código más corto que se me ocurrió:

exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";
Krait
fuente
Awesome man ............
edCoder
2

Si se trata de SQL Server, debe eliminar la restricción antes de poder eliminar la tabla.

Shiraz Bhaiji
fuente
2

Versión un poco más genérica de lo que @mark_s publicó, esto me ayudó

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')

simplemente conecte el nombre de su tabla y ejecute el resultado.

Stas Svishov
fuente
1
Hola, he estado tratando de eliminar mis restricciones de clave externa por lo anterior, pero cuando voy a soltar una tabla después, sigue diciendo "No se pudo eliminar el objeto porque todavía está siendo referenciado por una restricción de clave externa ... cualquier idea, gracias por adelantado?.
daniness
1

Aquí hay otra forma de eliminar todas las restricciones seguidas por las tablas mismas, utilizando un truco de concatenación FOR XML PATH('')que permite combinar múltiples filas de entrada en una sola fila de salida. Debería funcionar en cualquier cosa SQL 2005 y posterior.

He dejado los comandos EJECUTAR comentados por seguridad.

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)
Warren Rumak
fuente
Esto no funciona bien porque no se eliminarán todos los FK (solo aquellos en los que nuestras tablas se usan como padre, donde también deberíamos eliminar la restricción donde nuestra tabla se usó como "referenciada").
Roman Pokrovskij
Romano, la publicación original se trata de eliminar restricciones de clave externa. Mi respuesta no tiene como objetivo cubrir nada más que eso.
Warren Rumak
1

Aquí hay un script completo para implementar una solución:

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
Roman Pokrovskij
fuente
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.
CodeTzu
fuente
0

Con el Administrador de SQL Server, puede eliminar las restricciones de clave externa de la interfaz de usuario. Si desea eliminar la tabla Diarypero la tabla Usuario tiene una clave externa que DiaryIdapunta a la Diarytabla, puede expandir (usando el símbolo más) la Usertabla y luego expandir la Foreign Keyssección. Haga clic derecho en la clave externa que apunta a la tabla del diario y luego seleccione Delete. Luego puede expandir la Columnssección, hacer clic derecho y eliminar la columna DiaryIdtambién. Entonces puedes simplemente ejecutar:

drop table Diary

Sé que su pregunta real es sobre la eliminación de todas las tablas, por lo que esto puede no ser útil para ese caso. Sin embargo, si solo desea eliminar algunas tablas, creo que esto es útil (el título no menciona explícitamente la eliminación de todas las tablas).

Hazza
fuente
0

Si está en un servidor mysql y no le importa perder sus tablas, puede usar una consulta simple para eliminar varias tablas a la vez:

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

De esta manera, no importa en qué orden use la tabla en su consulta.

Si alguien va a decir algo sobre el hecho de que esta no es una buena solución si tiene una base de datos con muchas tablas: ¡estoy de acuerdo!

Els den Iep
fuente
ObtengoIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt
@Matt Bit difícil de adivinar en qué '=' obtienes ese error.
Els den Iep
3
foreign_key_checksno funcionará en el servidor MSSQL. Creo que es una variable específica de MySql.
ooXei1sh
1
@ ooXei1sh No, no en MSSQL. Por eso digo al comienzo de mi publicación: "Si estás en un servidor MYSQL".
Els den Iep
0

ejecute el siguiente código para obtener el nombre de restricción de clave externa que bloquea su caída. Por ejemplo, tomo la 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'

Obtendrá el nombre FK algo como a continuación: FK__Table1__roleId__1X1H55C1

ahora ejecute el siguiente código para eliminar la referencia FK obtenida desde arriba.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

¡Hecho!

jithil
fuente
-4

Si quiero eliminar todas las tablas de mi base de datos

Entonces es mucho más fácil descartar toda la base de datos:

DROP DATABASE WorkerPensions
Andomar
fuente
71
Dándole un -1 por esto, ya que no es una respuesta válida a la pregunta, por dos razones importantes: 1) ¡Elimina mucho más que las tablas! Los procedimientos almacenados, las funciones, los UDT, la seguridad, los ensamblados .NET, etc., todo desaparece con una BASE DE DATOS DROP. 2) Es posible que no se le permita crear bases de datos, por ejemplo, un entorno de desarrollo administrado centralmente donde las bases de datos son aprovisionadas por TI y tienen requisitos adicionales en el momento de la creación que desconoce.
Warren Rumak
-4

Si desea DROPuna tabla a la que otra tabla ha hecho referencia utilizando la clave externa, use

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Creo que debería funcionar para ti.

Nitish
fuente
1
no hay cascade constraintsen el servidor SQL
JackyJohnson