2009-08-24 12 views
14

En mySQL 5, ¿hay alguna forma de eliminar todas las restricciones de clave externa en una tabla con una declaración de SQL sin hacer referencia a ellas por su nombre?¿Es posible eliminar todas las restricciones de clave externa en una tabla a la vez en mySQL 5?

Estoy escribiendo un script de actualización de DB, y lamentablemente algunos de los sitios tenían restricciones creadas con nombres "incorrectos". Estoy tratando de evitar entrar y obtener los nombres de las restricciones reales de la base de datos y volver a insertarlas en las declaraciones de SQL.

Respuesta

6

Seguramente puede seleccionar * la tabla en una tabla temporal, colocarla y volver a crearla, y luego volver a copiarla.

+1

por conseguirme error como 'No se puede eliminar o actualizar una fila padre: una restricción de clave externa falla' Intenté crear cada fila, solo una fila obteniendo el error, otras eliminadas. – Pramod

+1

"Seguramente" apenas. En el mundo real, las tablas a menudo son demasiado grandes para que esto sea factible. ¿No hay una forma de manipular índices sin volver a crear toda la tabla? (Sí: ¡vea la excelente solución de Dandalf!) –

6

En su secuencia de comandos, siempre puede agregar SET FOREIGN_KEY_CHECKS = 0 si solo quiere evitar las restricciones.

limitaciones Además, siempre he suprimido en una base por restricción usando:

ALTER TABLE <table_name> DROP FOREIGN KEY <key_name>; 

creo que no se puede hacer todo a la vez y no pude encontrar ejemplos que demuestran que pueda.

6

Puede utilizar este sencillo script bash:

Run:

sh deleteForeignKeys.sh 

y deleteForeignKeys.sh es

#!/bin/bash 

dbname="databasename" 
table="tablename" 

mysqlconn="mysql -u username -ppassword -h host" 

tableschema=$($mysqlconn -N -e "SHOW CREATE TABLE $dbname.$table") 

#Foreign Keys 
fks=$(echo $tableschema | grep -oP '(?<=CONSTRAINT `).*?(?=` FOREIGN KEY)') 

for fk in $fks; 
do 
    # DROP FOREIGN KEY 
    $mysqlconn -e "ALTER TABLE $dbname.$table DROP FOREIGN KEY $fk"; 
done 
7

He aquí una selección que crea completa soltar y crear instrucciones para todas las relaciones en una mesa. No es de ninguna manera automática pero es bastante fácil de copiar/pegar desde ..

SELECT `DROP`,`CREATE` FROM (
SELECT 
CONCAT("ALTER TABLE `", `K`.`TABLE_NAME`, "` DROP FOREIGN KEY `", `K`.`CONSTRAINT_NAME`, "`;") "DROP", 
CONCAT("ALTER TABLE `", 
`K`.`TABLE_NAME`, 
"` ADD CONSTRAINT ", 
"`fk_", 
`K`.`TABLE_NAME`, 
"_", 
`K`.`REFERENCED_TABLE_NAME`, 
"1", 
"` FOREIGN KEY (`", 
`K`.`COLUMN_NAME`, 
"`) REFERENCES ", 
"`", 
`K`.`REFERENCED_TABLE_SCHEMA`, 
"`.`", 
`K`.`REFERENCED_TABLE_NAME`, 
"` (`", 
`K`.`REFERENCED_COLUMN_NAME`, 
"`) ON DELETE ", 
`C`.`DELETE_RULE`, 
" ON UPDATE ", 
`C`.`UPDATE_RULE`, 
";") "CREATE" 
FROM `information_schema`.`KEY_COLUMN_USAGE` `K` 
LEFT JOIN `information_schema`.`REFERENTIAL_CONSTRAINTS` `C` USING (`CONSTRAINT_NAME`) 
WHERE `K`.`REFERENCED_TABLE_SCHEMA` = "your_db" 
AND `K`.`REFERENCED_TABLE_NAME` = "your_table") AS DropCreateConstraints 

que lo utilizó para soltar todas las relaciones, alterar los tipos de datos en las teclas y luego restaurar las relaciones con los nombres de clave externa a La MySQL Workbench. Podría ser útil para alguien ..

11

Tengo una solución similar a la respuesta de Bing, pero se necesita un paso más para ser automática y reutilizable en un procedimiento.

DROP PROCEDURE IF EXISTS dropForeignKeysFromTable; 

delimiter /// 
create procedure dropForeignKeysFromTable(IN param_table_schema varchar(255), IN param_table_name varchar(255)) 
begin 
    declare done int default FALSE; 
    declare dropCommand varchar(255); 
    declare dropCur cursor for 
     select concat('alter table ',table_schema,'.',table_name,' DROP FOREIGN KEY ',constraint_name, ';') 
     from information_schema.table_constraints 
     where constraint_type='FOREIGN KEY' 
      and table_name = param_table_name 
      and table_schema = param_table_schema; 

    declare continue handler for not found set done = true; 

    open dropCur; 

    read_loop: loop 
     fetch dropCur into dropCommand; 
     if done then 
      leave read_loop; 
     end if; 

     set @sdropCommand = dropCommand; 

     prepare dropClientUpdateKeyStmt from @sdropCommand; 

     execute dropClientUpdateKeyStmt; 

     deallocate prepare dropClientUpdateKeyStmt; 
    end loop; 

    close dropCur; 
end/// 

delimiter ; 

Desde una declaración preparada sólo puede manejar una instrucción a la vez, el procedimiento vuelve a través de las claves externas utilizando un cursor y ejecuta cada gota de uno en uno.

para utilizar el procedimiento en una de sus mesas sólo tiene que utilizar la siguiente, en sustitución de esquema_tabla y nombre_tabla con sus valores:

call dropForeignKeysFromTable('table_schema', 'table_name'); 
+1

¡Gran procedimiento! Funciona fantásticamente! – Livewire

+0

Esto es lo que estaba buscando. Gran trabajo Dandalf! –

+0

Funciona como un encanto. Gracias !! –

Cuestiones relacionadas