Archiv der Kategorie: MySQL

MySQL: RENAME SCHEMA or DATABASE Workarounds

Leider ist es nicht möglich ein Schema bzw. Datenbank in MySQL mittels eines SQL-Standard-Befehls umzubennen. Hier folgen einige Workarounds:

SQL-Kommando in einer Bash-Schleife

mysql [OPTIONS] old_schema -sNe 'show tables' | 
while read table; 
  do mysql [OPTIONS] -sNe 
    "RENAME TABLE old_schema.$table TO old_schema.$table"; 
  done

mysqldump

mysqldump [OPTIONS] --database oldSchema > oldSchema.sql
mysql new_schema < oldSchema.sql

ein SQL-Kommando bauen

SET SESSION group_concat_max_len = 4294967295;

SELECT 
    CONCAT(
      'RENAME TABLE ', 
      GROUP_CONCAT( 
        table_schema,'.',table_name, ' TO ','new_schema.',table_name,' '
      ),
      ';'
    ) as stmt 
  FROM information_schema.TABLES 
  WHERE table_schema LIKE 'oldSchema' 
  GROUP BY table_schema;

Welche Alternative man jetzt nimmt, ist zum einen Geschmacksache und zum Anderen hängt es von der Datenbank ab, z.B. ist sie Groß, steht sie unter Dampf etc.

MySQL: Nachverfolgung von Änderungen der Datenbankstruktur

Es kommt immer irgendwann ein Zeitpunkt, wo man wissen möchte, wann sich Tabelle X bzw. Prozedur Y wie geändert hat.

In der Softwareentwicklung wird für die Code-Änderungen ein Versionierungstool (z.B. GIT) eingesetzt. Nach dem gleichen Prinzip sind auch Datenbankstrukturänderungen versionierbar.

Der einfachste Weg ist, sich mit mysqldump (per cron-job einmal täglich) einen Datenbank-Dump zu ziehen und einzuchecken. Der Nachteil dabei ist, dass immer nur die komplette Datei versioniert ist. Somit ist schlecht sichtbar, wann ein spezielles Datenbankobjekt sich wie geändert hat.

Um diesen Nachteil zu bereinigen, ist der Dump in die einzelnen Datenbankobjekte zu unterteilen, so dass für jede Tabelle, jede Prozedur etc. eine Datei existiert. Diese vielen kleinen Dateien werden dann eingecheckt.

#!/bin/bash 
HOST= 
PORT= 
USER=
DATABASE=

# jede Tabelle eine Datei
mysqldump -h $HOST -P $PORT -u $USER --tab=../dump/table --skip-dump-date --no-data --skip-opt $DATABASE 

# Prozeduren und danach mittels Perl-Skript in kleine Dateien aufteilen
mysqldump -h $HOST -P $PORT -u $USER  --routines --no-create-info --no-data --no-create-db --compact $DATABASE | ./seperate_proc.pl

Und hier noch das kleine Perl-Skript

#!/usr/bin/perl
#
use strict;
use warnings;
use utf8;

my $output_dir = "../dump/procedure";

sub getProcName() {
    (my $name = $_) =~ s/^CREATE\s+([^\s]+)\s+`([^\s`(]+)`\s*\(?.*/$2/eg;
    return $name;
}

## main
my %procs = ();

my $proc_name = "";
my $delimiter = ';';

while (<>) {
    if (/^DELIMITER\s+/) {
        $delimiter = $_;
        $delimiter =~ s/^DELIMITER\s+(.+)$/$1/eg;
    }

    if (/^CREATE\s+/) {
        if (/DEFINER=/) {
            # remove DEFINER
            s/^(.+\s+)DEFINER=`[^\s]+`\s+(.+)$/$1$2/;
        }
        if (/^CREATE\s+(FUNCTION|PROCEDURE)/) {
            $proc_name = "$1." . &getProcName($_);
            # append DELIMITER to first line
            $procs{$proc_name} .= "DELIMITER $delimiter\n";
        }
    }

    if ($proc_name) {
        $procs{$proc_name} .= $_;
    }

    if (/END\s+$delimiter/) {
        $proc_name = "";
    }
}

# store files
mkdir($output_dir);
for (keys %procs) {
    my $key = $_;
    chomp;
    my $filename = "$output_dir/$_.sql";
    print "Dump $_ -> $filename\n";
    open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
    print $fh $procs{$key};
    close $fh;
}

print "done\n";