DEV Community

Cover image for Come estrarre una singola tabella da un file dump MySQL
minnogit
minnogit

Posted on Edited on

Come estrarre una singola tabella da un file dump MySQL

A volte ho a disposizione solo il dump .sql di un intero database e mi serve una tabella. Aprire un file di svariati gigabyte con un editor di testo è scomodo, e importare tutto su un server locale per recuperare poche righe è uno spreco. Basta un piccolo script che estrae solo la tabella che interessa, con i suoi dati.

Lo script

#!/usr/bin/env bash
# uso: estrai-tabella nome_tabella dump.sql > tabella.sql
awk -v target="-- Table structure for table \`$1\`" '
  BEGIN { header = 1 }
  /^\/\*!40103 SET TIME_ZONE=@OLD_TIME_ZONE/ { footer = 1; in_t = 0 }
  /^-- (Table structure for table|Temporary view structure for view|Final view structure for view|Dumping routines|Dumping events)/ { header = 0; in_t = ($0 == target) }
  (header || in_t || footer) && !(in_t && /^DROP TABLE/)
' "$2"
Enter fullscreen mode Exit fullscreen mode

Si usa così, con il nome della tabella e il dump generato da mysqldump:

estrai-tabella nome_tabella dump_completo.sql > nome_tabella.sql
mysql nome_database < nome_tabella.sql
Enter fullscreen mode Exit fullscreen mode

Come funziona

Un dump di mysqldump è diviso in blocchi, ognuno introdotto da un commento come -- Table structure for table seguito dal nome della tabella. Lo script stampa tre parti:

  • l'intestazione, cioè le righe prima del primo blocco: impostano la codifica e disattivano il controllo delle chiavi esterne;
  • il blocco della tabella scelta, dal suo commento fino al commento del blocco successivo, quindi struttura, dati e trigger;
  • il piè di pagina, che rimette a posto le impostazioni cambiate dall'intestazione.

La riga DROP TABLE IF EXISTS del blocco viene tolta. Prima usavo un intervallo di sed tra DROP TABLE e UNLOCK TABLES, ma lasciava fuori l'intestazione e i trigger, che mysqldump scrive dopo UNLOCK TABLES. Con il DROP dentro, importare quel file cancellava la tabella esistente, e con essa anche i suoi trigger, che il file non ricreava.

Cosa succede all'import

  • Se la tabella esiste già, l'import si ferma con l'errore Table 'nome_tabella' already exists e non cancella nulla. Per sostituirla la cancello io prima con DROP TABLE. Se è referenziata da una chiave esterna, anche il DROP si ferma (Cannot drop table ... referenced by a foreign key constraint) finché non disattivo i controlli con SET FOREIGN_KEY_CHECKS=0.
  • Le chiavi esterne della tabella vengono ricreate. Grazie all'intestazione, l'import funziona anche se la tabella a cui puntano non c'è ancora.
  • I trigger della tabella vengono ricreati.

Limiti

  • Ho provato lo script con mysqldump 9.7 e un server MySQL 8.4, importando una tabella con un trigger, una con una chiave esterna e una vuota in un database nuovo. Non l'ho provato con MariaDB né con versioni più vecchie di mysqldump: i commenti di separazione dovrebbero essere gli stessi, ma è un'ipotesi.
  • Se il dump è stato creato con --skip-comments, i commenti che separano i blocchi non ci sono e lo script non trova la tabella.
  • I trigger riportano un DEFINER, cioè l'utente che li ha creati (nella mia prova root@localhost). Se importo su un altro server, quell'utente deve esistere, altrimenti la creazione del trigger fallisce. Questo non l'ho provato.
  • Viste e stored procedure non vengono estratte, anche se dipendono dalla tabella.
  • awk legge il dump fino in fondo, anche dopo aver stampato il blocco. Su file molto grandi ci mette il tempo di una lettura completa, che non ho misurato.

Top comments (0)