2009-08-24 16 views
14

In mySQL 5, c'è un modo per rilasciare tutti i vincoli di chiave esterna su una tabella con un'istruzione SQL senza fare riferimento ad essi per nome?È possibile rilasciare tutti i vincoli di chiave esterna su una tabella in una volta in mySQL 5?

Sto scrivendo uno script di aggiornamento del DB e, sfortunatamente, alcuni siti hanno dei vincoli creati con nomi "errati". Sto cercando di evitare di entrare e ottenere i nomi dei vincoli effettivi dal DB e inserirli nuovamente nelle istruzioni SQL.

risposta

6

È possibile selezionare * la tabella su una tabella temporanea, rilasciarla e ricrearla, quindi ricopiarla.

+1

Per me errore ottenendo come 'Impossibile eliminare o aggiornare una riga padre: un vincolo di chiave esterna fails'. Ho provato a creare ogni riga quindi solo per una riga ottenendo un errore, altri eliminati. – Pramod

+1

"Sicuramente" difficilmente. Nel mondo reale le tabelle sono spesso troppo grandi perché ciò sia fattibile. Non c'è un modo per manipolare gli indici senza ricreare l'intera tabella? (Sì: vedi l'eccellente soluzione di Dandalf!) –

6

Nel tuo script puoi sempre aggiungere SET FOREIGN_KEY_CHECKS = 0 se vuoi solo aggirare i vincoli.

vincoli Inoltre, ho sempre cancellati su una base per vincolo di utilizzo:

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

non credo si può fare tutto in una volta e non ho trovato nessun esempi che mostrano che puoi.

6

È possibile utilizzare questo semplice script bash:

Run:

sh deleteForeignKeys.sh 

e deleteForeignKeys.sh è

#!/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

Ecco una selezione che crea completa drop e creare istruzioni per tutti i rapporti su un tavolo Non automatica in alcun modo, ma abbastanza facile da copiare/incollare da ..

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 

ho usato per eliminare tutti i rapporti, modificare i tipi di dati sui tasti e quindi ripristinare i rapporti con i nomi di chiave esterna alla MySQL Workbench. Potrebbe essere utile a qualcuno ..

11

Ho una soluzione simile alla risposta di Bing, ma ci vuole un ulteriore passo per essere automatici e riutilizzabili in una procedura.

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 ; 

Poiché un'istruzione preparata può gestire una sola istruzione alla volta, la procedura loop attraverso le chiavi esterne utilizzando un cursore ed esegue ogni goccia alla volta.

Per utilizzare la procedura a una delle vostre tabelle basta usare il seguente, sostituendo TABLE_SCHEMA e table_name con i propri valori:

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

Ottima procedura! Funziona in modo fantastico! – Livewire

+0

Questo è quello che stavo cercando. Ottimo lavoro Dandalf! –

+0

Funziona come un fascino. Grazie !! –

Problemi correlati