Exportar SQL Server a MySQL Server

Existen herramientas ETL, y front-end de BD que pueden hacer esta tarea de forma automática, pero a mi me interesa programarlo para poder tener flexibilidad a la hora de programar la ejecución, controlar errores, ahorrar recursos, etc. Así que lo haremos con 2 scripts: uno en Power Shell para extraer los datos de SQL Server y otro en Shell Script para cargarlos en un MySQL que corre sobre Linux.

Exportar toda las tablas de la BD a ficheros .CSV

Para esta tarea podemos contar con la maravillosa herramienta de Power Shell. Gracias a ella podremos crear scripts avanzados en un entorno Windows de manera casi tan flexible como lo hacemos en entornos UX. Ojo, tenéis que sustituir las constantes de las dos primeras líneas por su valor correspondiente (suponiendo que vuestro SQL Server se autentique a través del usuario de Windows, si no tendréis que aportar también estos datos a la cadena de conexión).

También deberéis modificar la ruta a la que se vuelcan los ficheros. En este script es: C:\mssql\export\, y dentro de ella se guardarán los ficheros en tablas CSV cuyo nombre coincide con el de la tabla origen en SQL Server.

$server = "SERVERNAME\INSTANCE"
$database = "DATABASE_NAME"
$tablequery = "SELECT name from sys.tables"

#Delcare Connection Variables
$connectionTemplate = "Data Source={0};Integrated Security=SSPI;Initial Catalog={1};"
$connectionString = [string]::Format($connectionTemplate, $server, $database)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString

$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $tablequery
$command.Connection = $connection

#Load up the Tables in a dataset
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$connection.Close()



# Loop through all tables and export a CSV of the Table Data
foreach ($Row in $DataSet.Tables[0].Rows)
{
    $queryData = "SELECT * FROM [$($Row[0])]"

    #Specify the output location of your dump file
    $extractFile = "C:\mssql\export\$($Row[0]).csv"

    $command.CommandText = $queryData
    $command.Connection = $connection

    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $command
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $connection.Close()

    $DataSet.Tables[0]  | Export-Csv $extractFile -NoTypeInformation
}


Ahora, vamos a llevarnos esos ficheros a MySQL

Una vez hemos generado esos ficheros, tendríamos que moverlos a través de FTP (o lo que tengamos) a la ruta donde realizaremos el segundo paso: importar el contenido de cada uno de estos ficheros a tablas MySQL cuyo nombre coincide con el de las tablas SQL SERVER.

La gracia de tener cada tabla en un fichero .csv, es que podemos, por ejemplo, utilizar PhpMyAdmin: seleccionamos una Base de Datos para ejecutar la consulta, para este ejemplo tenemos creada la base de datos: "sqlserver". Luego nos vamos a la pestaña SQL, y lanzamos esta consulta:

LOAD DATA INFILE D:\clientes.csv INTO TABLE clientes FIELDS TERMINATED BY ,;


Veamos esto, por ejemplo, automatizado en un script bash:. A este script se le especifica una ruta concreta e importa cada fichero CSV a una nueva tabla MySQL.

#!/bin/bash

# show commands being executed, per debug
set -x

# define database connectivity
_db="csv_imports"
_db_user="csv_imports"
_db_password="changeme"

# define directory containing CSV files
_csv_directory="/path/to/the/csv/files"

# go into directory
cd $_csv_directory

# get a list of CSV files in directory
_csv_files=`ls -1 *.csv`

# loop through csv files
for _csv_file in ${_csv_files[@]}
do

  # remove file extension
  _csv_file_extensionless=`echo $_csv_file | sed 's/\(.*\)\..*/\1/'`

  # define table name
  _table_name="${_csv_file_extensionless}"

  # get header columns from CSV file
  _header_columns=`head -1 $_csv_directory/$_csv_file | tr ',' '\n' | sed 's/^"//' | sed 's/"$//' | sed 's/ /_/g'`
  _header_columns_string=`head -1 $_csv_directory/$_csv_file | sed 's/ /_/g' | sed 's/"//g'`

  # ensure table exists
  mysql -u $_db_user -p$_db_password $_db << eof
    CREATE TABLE IF NOT EXISTS \`$_table_name\` (
      id int(11) NOT NULL auto_increment,
      PRIMARY KEY  (id)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1
eof

  # loop through header columns
  for _header in ${_header_columns[@]}
  do

    # add column
    mysql -u $_db_user -p$_db_password $_db --execute="alter table \`$_table_name\` add column \`$_header\` text"

  done

  # import csv into mysql
  mysqlimport --fields-enclosed-by='"' --fields-terminated-by=',' --lines-terminated-by="\n" --columns=$_header_columns_string -u $_db_user -p$_db_password $_db $_csv_directory/$_csv_file

done
exit

¿Funciona? ¡Voila! Base de Datos migrada.

Ojo, esto no migrará los PK, las Foreign Key, índices, etc. Esos tendréis que crearlos manualmente.