Skip to content

Instantly share code, notes, and snippets.

@turicas
Created May 4, 2012 07:29
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save turicas/2592877 to your computer and use it in GitHub Desktop.
Save turicas/2592877 to your computer and use it in GitHub Desktop.
Convert a MDB (Access) file to SQL
#!/bin/bash
# Convert a MDB file (Access) to SQL
# Needs mdbtools[http://mdbtools.sourceforge.net/]
# run 'aptitude install mdbtools' on Debian/Ubuntu
# Created by Álvaro Justen <https://github.com/turicas>
# License: GPLv2
mdb=$1
sql=$2
if [ -z "$2" ]; then
echo 'This script convert a MDB file to SQL file. You need to specify the name of both'
echo "Usage: $0 <mdb_file> <sql_file>"
exit 1
fi
if [ -z "$(which mdb-tables)" ]; then
echo 'You need mdbtools installed.'
echo 'Learn more at http://mdbtools.sourceforge.net/'
echo 'If you use Debian/Ubuntu, just execute:'
echo ' sudo aptitude install mdbtools'
exit 2
fi
mdb-schema $mdb > $sql
sed -i 's/Long Integer/INT(11)/g; s/Text /VARCHAR/g' $sql
for table in $(mdb-tables $mdb); do
mdb-export -I -R ';' $mdb $table >> $sql
done
sed -i '/^-\{2,\}/d; s/DROP TABLE /DROP TABLE IF EXISTS /' $sql
@MikiDi
Copy link

MikiDi commented Oct 24, 2015

Using the current version of mdbtools the mdb-export -I -R ';' $mdb $table >> $sql command fails as the -I-option needs an argument. I also think the -R option seems to be no longer needed (; is automatically appended).

@douglasfernandes
Copy link

line 28:
mdb-export -I postgres $mdb "$table" >> $sql
postgres, mysql are ok.

@franco999
Copy link

It works correctly for me as @douglasfernandes says.
line 28: mdb-export -I mysql $mdb "$table" >> $sql

@thomst
Copy link

thomst commented Aug 18, 2020

Newer versions of mdb-schema needs mysql to be explicitly specified as database-backend:
line 25: mdb-schema $mdb mysql > $sql

@anentropic
Copy link

Something goes wrong here if the table name has spaces in it

for table in $(mdb-tables $mdb); do
    mdb-export -I -R ';' $mdb $table >> $sql
done

@kurahaupo
Copy link

kurahaupo commented May 29, 2023

@anentropic Yes it's fairly common for shell scripts to be missing quotes, and to make other dubious assumptions (for var in $( ... ) is usually a bad idea, as is checking the output of which).

It is also missing the database type after the -I option to mdb-export, which will cause (some versions of?) mdb-export to fail.

The default string quote used by (some versions of?) mdb-export is ", which is not standard SQL; we need to add -q\' to get the correct behaviour.

My suggestion below incorporates these:

  1. add quotes where needed to ensure correct behaviour
  2. allow the user to specify the preferred SQL format (default to mysql)
  3. allow output to go to stdout without forcing the user to add /dev/stdout to the end of the script invocation
    • avoid opening the output multiple times
  4. get rid of unnecessary sed commands
    • ask mdb-schema to output the correct format to begin with
    • tell mdb-export which database type
    • leave SQL "--" comments alone; they might actually be useful to a future reader
  5. avoid depending on "word splitting": use cmd | while read x ; do ... instead of for x in $( cmd ) ; do ...
  6. if mdb-schema fails, skip the remaining steps
  7. use command instead of which, and check all required commands
  8. informative exit values taken from /usr/include/sysexits.h (but if you don't like them you can just use exit 1)

Normally I would point out the necessity to adjust the #! line to match wherever you have bash installed on your system, but that would be pointless in this case since it can only run on Linux (where the mdb-tools package is available, and where/bin/bash is more reliable than /usr/bin/env bash).

#!/bin/bash

[[ $* = --help || $* = -h ]] && exec cat <<-EndOfHelp
$0 INPUT-FILE [OUTPUT-FILE [DIALECT [FLUSH]]]
  INPUT-FILE    source MDB file
  OUTPUT-FILE   target SQL file, use '-' for stdout; default stdout
  DIALECT       one of 'access', 'mysql', 'oracle', 'postgres', 'sqlite', or 'sybase'; default 'mysql'.
  FLUSH         one of 'drop', 'truncate', or 'none'; default 'none'
EndOfHelp

#### Check prerequisites

for c in  mdb-schema  mdb-sql mdb-tables
command -v "$c" >/dev/null || { printf >&2 'The "%s" command appears to be missing; please ensure that mdb-tools is installed\n' "$c" ; exit 72 ; }

#### Check CLI options

(($# >= 1)) || { printf >&2 'Not enough args\n' ; exit 64 ; }
(($# <= 4)) || { printf >&2 'Too many args\n'   ; exit 64 ; }

mdb=$1
output=${2:--}
dialect=${3:-mysql}
flush=${4:-none}

[[ -n $mdb && -f $mdb ]] || { printf >&2 'Invalid input file (%s)\n' "$mdb" ; exit 66 ; }

# Edit this to match the list of dialects supported by your version of mdb-tools
case $dialect in
  access ) quote=\" ;;
  mysql | oracle | postgres | sqlite | sybase ) quote=\' ;;
  * ) printf >&2 'Invalid output database type (%s)\n' "$dbtype" ; exit 64 ;;
esac

case $flush in
  drop | truncate | none ) ;;
  * ) printf >&2 'Invalid table clearing method (%s)\n' "$flush" ; exit 64 ;;
esac

#### Last prerequisite: can read the MDB file to get list of tables

readarray -t Tables < <(
    mdb-tables -1 "$mdb"
)
(( ${#Tables[@]} > 0 )) || { printf >&2 'Cannot read list of tables from %s\n' "$mdb" ; exit 65 ; }

#### Establish the output file

# If output filename given, then all stdout from remainder of this script goes into it.
# This will truncate any existing file, so do this after all prerequisites have been checked.

[[ $output != - ]] && exec >"$output"

#### Ok, good to go

case $flush in
  drop )        printf 'drop table if exists %s;\n' "${Tables[@]}" ;;
  truncate )    printf 'truncate table %s;\n' "${Tables[@]}" ;;
esac

mdb-schema "$mdb" "$dialect" |
case $flush in
  truncate )    sed 's/^create table /&if not exists /i' ;;
  * )           cat ;;
esac
    ((PIPESTATUS[0] == 0)) || { printf >&2 'Cannot generate schema from "%s"\n' "$mdb" ; exit 65 ; }

for table in "${Tables[@]}"
do
    mdb-export -I "$dialect" -q "$quote" -boctal -D%F "$mdb" "$table"
done

@kurahaupo
Copy link

The same thing with all error checking removed:

#!/bin/bash

mdb=$1
output=${2:--}
dialect=${3:-mysql}

[[ $output != - ]] && exec >"$output"

mdb-schema "$mdb" "$dialect"

mdb-tables -1 "$mdb" |
while read -r table
do
    mdb-export -I "$dialect" -q\' -boctal -D%F "$mdb" "$table"
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment