Leitfaden zur Migration von Microsoft SQL Server nach MySQL Ein technisches MySQL® White Paper September 2007 Copyright © 2007, MySQL AB Inhaltsverzeichnis 1 Einleitung .........................................................................................................................4 2 Warum die Migration von SQL Server unternehmerisch sinnvoll ist..........................4 3 4 2.1 Bemessung der Kosten für die Nutzung von SQL Server im Vergleich zu MySQL......4 2.2 Ein kurzer Blick auf MySQL AB ...................................................................................6 Die technische Seite der Migration von SQL Server nach MySQL..............................6 3.1 MySQL unter Windows? Natürlich! ..............................................................................7 3.2 Genau die richtigen Funktionen ...................................................................................7 3.3 Untersuchung der Leistung und Skalierbarkeit von MySQL ........................................9 3.4 MySQL – Immer betriebsbereit, immer funktionsfähig .................................................9 Praktische Vorschläge für die einfache Migration von SQL Server zu MySQL........10 4.1 Alles oder nichts? ......................................................................................................10 4.2 1. Schritt – Dokumentation des SQL Server-Quellcodes ...........................................10 4.3 2. Schritt – Entwurf der MySQL-Zieldatenbanken......................................................12 4.4 3. Schritt - Durchführung der Migration nach MySQL ................................................12 4.5 Validierung der Migration von SQL Server nach MySQL...........................................13 4.6 Ratschläge zur gemeinsamen Handhabung von SQL Server und MySQL................15 5 Fazit ................................................................................................................................16 6 Weitere Informationsquellen.........................................................................................17 7 8 6.1 MySQL Migrationshilfen.............................................................................................17 6.2 Anwenderberichte......................................................................................................17 6.3 White Paper ...............................................................................................................18 Anhang A – MSSQL to MySQL - Datatypes .................................................................19 7.1 Overview....................................................................................................................19 7.2 Comparable Datatypes ..............................................................................................19 7.3 Datatypes Requiring Conversion ...............................................................................19 Anhang B – SQL Server to MySQL – Predicates.........................................................20 8.1 Overview....................................................................................................................20 8.2 Synopsis ....................................................................................................................20 8.3 Boolean conditions ....................................................................................................20 8.4 Comparison conditions ..............................................................................................20 8.5 Exists conditions ........................................................................................................22 8.6 In conditions...............................................................................................................22 Copyright © 2007, MySQL AB Seite 2 von 49 8.7 Null conditions ...........................................................................................................22 8.8 Pattern matching conditions.......................................................................................23 8.9 Range conditions .......................................................................................................23 9 Anhang C – SQL Server to MySQL – Operators and Date Functions .......................24 9.1 Overview....................................................................................................................24 9.2 Arithmetic operators...................................................................................................24 9.3 Concatenation operators ...........................................................................................24 9.4 Hierarchical query operators......................................................................................25 9.5 Set operators .............................................................................................................25 9.6 Date Functions...........................................................................................................26 10 Anhang D – T-SQL Conversion Suggestions ...........................................................27 10.1 Overview.................................................................................................................27 10.2 Getting T-SQL Code out of SQL Server .................................................................27 10.3 Procedure Formats .................................................................................................27 10.4 Error Handling.........................................................................................................27 10.5 Use LIMIT instead of TOP ......................................................................................28 10.6 LIMIT and Optimization...........................................................................................29 10.7 IF THEN … ELSE … END IF ;................................................................................30 10.8 DATETIME with default values ...............................................................................30 10.9 Index Name Length Differences .............................................................................30 10.10 Support for SQL Server Declared Tables ............................................................31 10.11 Obtaining Row Counts .........................................................................................31 10.12 Default Values for Parameters.............................................................................31 10.13 Use of SELECT INTO ..........................................................................................31 10.14 Uses of IFNULL ...................................................................................................31 10.15 Replace DATEADD with ADDDATE()..................................................................31 10.16 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ....................32 10.17 Replace SET ROWCOUNT = @rows with SQL_SELECT_LIMIT .......................32 10.18 Perl Script to Help with Conversion of T-SQL to MySQL .....................................32 10.18.1 11 Perl Conversion Script ...................................................................................34 Anhang E – Sample Migration ...................................................................................36 11.1 Sample SQL Server Schema..................................................................................36 11.2 Moving the SQL Server Database to MySQL with the Migration Toolkit .................40 11.3 Sample MySQL Schema Generated from SQL Server...........................................45 11.4 Sample Code Migration ..........................................................................................46 Copyright © 2007, MySQL AB Seite 3 von 49 1 Einleitung Mit dem raschen Wachstum von MySQL auf dem Datenbankmarkt haben viele Unternehmen, Regierungsbehörden, Bildungseinrichtungen und andere begonnen, sich von ihren kostspieligen und proprietären Datenbanken zu verabschieden. Eine Datenbankmigration ist natürlich niemals auf die leichte Schulter zu nehmen, und deshalb denken zahllose Unternehmen nun über ihre Optionen für die Migration hin zu MySQL nach. Viele MySQL-Kunden migrieren von SQL Server, denn Sie haben festgestellt, daß die Kombination aus Kosteneinsparung, Plattformunabhängigkeit und der Funktionsumfang von MySQL eine unwiderstehliche Gelegenheit darstellen, einen Teil oder die Gesamtheit ihrer datenbankgetriebenen Anwendungen auf den MySQL Datenbankserver zu migrieren. Dieses Dokument liefert einen Einblick in die Überlegungen, die für einen Wechsel von SQL Server zu MySQL notwendig sind und stellt Ihnen eine Reihe von Möglichkeiten vor, die dabei helfen werden, den Übergang einfacher zu gestalten. Dieses White Paper betrachtet sowohl die geschäftliche als auch die technische Seite der Migration zu MySQL, Sie werden also unabhängig davon, ob Sie Manager oder erfahrener Datenbankadministrator sind, die erforderlichen Antworten auf die Fragen finden, die sich rund um die Migration hin zur weltweit populärsten Open-Source-Datenbank MySQL drehen. 2 Warum die Migration von SQL Server unternehmerisch sinnvoll ist Moderne Unternehmen, die sich im großen Umfang für eine Technologie engagieren wollen, müssen zunächst einmal hinter die technischen Versprechen der Lieferanten blicken und die unternehmerische Seite des Erwerbs einer neuen Technologie betrachten. Jedes Geschäft verfügt über seine eigene Methode zur Bewilligung einer bestimmten Software, dennoch sind die wichtigsten Faktoren für die Akzeptanz normalerweise das Ergebnis der Kalkulation der Gesamtbetriebskosten, die über den kompletten Lebenszyklus hinweg anfallen sowie die Bewertung der Integrität des Softwarehändlers. Lassen Sie uns jeden dieser beiden oben erwähnten Faktoren etwas genauer anschauen und feststellen, wie MySQL bei der Kalkulation der Gesamtbetriebskosten des MySQL Datenbankservers und der Bewertung des Unternehmens, das hinter der Datenbank steht, abschneidet. 2.1 Bemessung der Kosten für die Nutzung von SQL Server im Vergleich zu MySQL Zu den wichtigsten Faktoren, die für die große Beliebtheit und Akzeptanz von Open-SourceSoftware in den Unternehmen verantwortlich sind, gehören unter anderem auch die hohen Kosteneinsparungen, die der Einsatz einer solchen Software mit sich bringt. Wenn man bedenkt, daß viele große Global 2000- Unternehmen jährlich zwischen 500.000 und 10.000.000 € für neue Lizenzen und die Wartung für proprietäre Datenbanksoftware aufwenden, wird MySQL zu einer unglaublich attraktiven Alternative, denn durch die Verwendung von MySQL sowohl für neue Anwendungsprojekte als auch für die Erweiterung bestehender Systeme anstelle kostspieligerer proprietärer Alternativen können die meisten Unternehmen ihre Kosten um etwa 80 – 90 % senken. Da SQL Server im Vergleich zu anderen Datenbanken wie Oracle im Hinblick auf Kosteneinsparungen im Allgemeinen gut abschneidet, erscheint es möglicherweise überraschend, daß eine Migration von SQL Server zu MySQL dennoch zu erheblichen Kosteneinsparungen führen kann. Schauen Sie sich einmal den folgenden Dreijahresvergleich der Gesamtbetriebskosten zwischen MySQL, SQL Server und Oracle an: Copyright © 2007, MySQL AB Seite 4 von 49 Gesamtbetriebskosten über 3 Jahre $1.400.000 $1.200.000 $1.000.000 $800.000 $600.000 $400.000 $200.000 $0 MySQL MS SQL Server Oracle Beispiel einer Hardware-Konfiguration für einen kleinen Online-Händler: - Anzahl an Servern: 10 (standardmäßige x86-Maschinen) - Anzahl an CPUs (pro Maschine): 2 (Dual CPU) - Anzahl an Kernels (pro CPU): 2 (Dual Core) - Gesamtzahl der eingesetzten CPUs: 20 - Gesamtzahl der eingesetzten Kernels: 40 Microsoft SQL Server Enterprise: - Softwarelizenz: $24.995 pro CPU - Support & Wartung pro Jahr: 22% der Softwarelizenz Oracle Enterprise: - Softwarelizenz: $40.000 pro Kernel - Support & Wartung pro Jahr: 22% der Softwarelizenz MySQL Enterprise Gold: - Softwarelizenz: KEINE (bei MySQL fallen keine Datenbank-Lizenzgebühren an) - Jährliches MySQL Enterprise-Abonnement: 2.399 € pro Server Gesamtbetriebskosten über 3 Jahre Microsoft Oracle $0 $499.900 $800.000 3 Jahre Support & Wartung $89.850 $329.934 $528.000 Gesamtkosten $89.850 $829.834 $1,328.000 Softwarelizenzen Einsparung über 3 Jahre: MyQL anstatt MS SQL Server Einsparung über 3 Jahre: MySQL anstatt Oracle $ 739.984 (89%) $ 1.238.150 (93%) Wie Sie sehen können, ist durch einen Wechsel von SQL Server zu MySQL eine Kostensenkung von fast 90 % realisierbar. Solch deutliche Vergleichsergebnisse sind der Grund dafür, warum sich so viele Unternehmen für eine horizontale Skalierung mit MySQL zur Erweiterung ihrer Geschäfte entscheiden - und zwar unabhängig davon, ob das Unternehmen bei Microsoft Windows bleiben oder auf ein anderes Betriebssystem wie Linux umsteigen möchte. Unternehmen wie Weather Channel halten MySQL für das perfekte Instrument bei ihrem Streben nach hoher Datenbankleistung und geringstmöglichen Betriebskosten: Copyright © 2007, MySQL AB Seite 5 von 49 „Weather Channel ist heute die zehntgrößte Webseite der Welt und läuft fast zu 100 Prozent auf der Open-Source-Datenbank MySQL. Mit dem Wechsel von einer Sun Solaris-Umgebung zu Linux oder Intel, dem Wegfall der Hardwarewartung, dem Austausch der kommerziellen Software gegen quelloffene Software sowie dem niedrigeren Preis und der besseren Leistung einer Intel-Plattform reduzierten wir die Kosten um ein Drittel und konnten die Prozessorkapazität der Website um 30 Prozent steigern“, berichtet Dan Agronow, CTO von The Weather Channel Interactive.“1 2.2 Ein kurzer Blick auf MySQL AB Die Migration zu einer neuen Datenbankplattform bedeutet im Allgemeinen ein langfristiges Engagement; moderne Unternehmen, die über einen Wechsel zu MySQL nachdenken, möchten deshalb nicht nur die Geschichte der Datenbank kennen lernen, sondern auch erfahren, wer sie wie verwendet. Branchenumfragen zufolge bestehen die wichtigsten Bedenken der Unternehmen, die über den Einsatz einer quelloffenen Software nachdenken, im möglichen Mangel an Support2. Natürlich wird kein großes Unternehmen seine kritischen Geschäftssysteme auf Software stützen, die nicht von einem angesehenen Lieferanten unterstützt wird – einem Lieferanten, der über einen lang anhaltenden und ausgezeichneten Ruf in der Branche verfügt und erstklassigen Support bietet. Viele Unternehmen wundern sich bei Ihrer ersten Berührung mit MySQL, daß MySQL AB seit mehr als 10 Jahren im Geschäft ist. Mit elf Millionen aktiven Installationen expandiert MySQL immer weiter und entwickelte sich so zur populärsten Open-Source-Datenbanken der Welt. Jeden Tag laden über 50.000 Nutzer weltweit MySQL-Software für ihre geschäftlichen Anwendungen herunter. Forrester Research stellte in einer Studie fest, daß im Jahr 2006 74% der Unternehmen eine Umstellung auf Open-Source in Betracht zogen und 53% den Einsatz von MySQL als eine der Datenbankplattformen vorsahen. Aufgrund des ständig anwachsenden Bestands an Firmenkunden bietet MySQL Kunden, welche erstklassige Support- und Dienstleistungen auf Unternehmensniveau wünschen, MySQL Enterprise an. MySQL Enterprise bietet diesem Klientel unter anderem Supportleistungen rund um die Uhr, Benachrichtigungssysteme, und einen professionellen Monitor- und Advisordienst. Bekannte Anbieter von IT-Systemen und –Lösungen haben inzwischen die Popularität von MySQL Enterprise erkannt und sich mit MySQL zusammengeschlossen, um MySQL Enterprise an ihren großen Kundenstamm weiterzuveräußern. Unter den MySQL-Wiederverkäufern befinden sich heute Unternehmen wie HP, Novell, Dell und andere. Unternehmen, die Referenzen wünschen und sich absichern möchten, daß MySQL auch für kritische Anwendungsbedürfnisse zuverlässig arbeitet, brauchen sich nur den rasch wachsenden MySQL-Kundenstamm anzuschauen: er liest sich wie das Who’s-Who der Geschäftswelt. Im MySQL-Kundenstamm sind moderne Unternehmen wie Yahoo, Google, Amazon, Siemens, neckermann.de, OBI, die HypoVereinsbank und viele andere vertreten. Weitere Informationen finden Sie auf http://www.mysql.de/customers/. 3 Die technische Seite der Migration von SQL Server nach MySQL MySQL hat seine Bewährungsprobe im geschäftlichen Umfeld mit Bravour bestanden. Die nächste Hürde, ob von SQL Server zu MySQL migriert werden kann ist die Überprüfung der Datenbank-Funktionalitäten und deren Fähigkeiten. Mit anderen Worten: Wie gut kann eine OpenSource-Datenbank sein? 1 2 http://www.cio.com/archive/090105/forum.html, September 2005 Forrester Research, Februar 2004. Copyright © 2007, MySQL AB Seite 6 von 49 3.1 MySQL unter Windows? Natürlich! MySQL kann auf eine umfangreiche Vergangenheit mit vielen Open-Source-Betriebssystemen wie Linux zurückblicken, und deshalb überrascht es möglicherweise zu sehen, wie beliebt MySQL mit seiner Datenbankserver-Plattform bei den Anwendern von Microsoft Windows ist. In einer Umfrage3 unter MySQL-Anwendern gaben 58% an, daß bei ihnen MySQL unter Windows läuft. 46% sagten, daß sie von einem Microsoft-Datenbankprodukt (SQL Server und Access) zu MySQL migriert hatten. Warum ist MySQL bei den Windows-Anwendern so beliebt? Zunächst einmal ist MySQL unter Windows extrem einfach zu installieren und betreiben. Die Installation und Konfiguration mit der grafischen Benutzerschnittstelle von MySQL dauert unter Windows weniger als 5 Minuten, und das ist schneller und einfacher als mit SQL Server. Es ist auch ganz leicht, mehrere Instanzen von MySQL auf demselben Windowsserver zu installieren, denn jede Instanz läuft als eigener, separater Dienst und akzeptiert eingehende Verbindungen über einen eigenen, separaten Port. Wie bei SQL Server ist es ausgesprochen einfach, MySQL-Instanzen auf einem Windows-Server entweder über das Windows Dienstprogramm oder aber über den von MySQL mitgelieferten systray-System Manager zu starten/anzuhalten. Auch die Treiber für MySQL lassen sich auf jeden WindowsServer oder auf der Entwickler-Workstation einfach installieren und konfigurieren, und dabei sind ODBC- und .NET-Treiber verfügbar. MySQL stellt darüber hinaus kostenlose grafische Management-, Entwicklungs- und Migrations-Werkzeuge zur Verfügung, so daß die Entwickler oder DBAs ihre MySQL-Datenbanken, Tabellen, Indizes, die gespeicherten Prozeduren und andere Objekte ganz einfach per Mausklick erstellen können. Es ist also ganz einfach, MySQL auf der Microsoft Windows-Plattform zu betreiben. Wir möchten jedoch auch betonen, daß MySQL anders als SQL Server darüber hinaus auf über 2 Dutzend weiteren Plattformen verwendet werden kann, so daß bei der Arbeit mit MySQL niemals eine Abhängigkeit von einer bestimmten Plattform entsteht. 3.2 Genau die richtigen Funktionen Niemand wird abstreiten, daß SQL Server mehr Funktionalität aufzuweisen hat als der MySQLDatenbankserver. MySQL wurde jedoch auch nicht konzipiert, um SQL Server zu ersetzen, sondern die Absicht bestand darin, einen Hochleistungs-Datenbankserver zu schaffen, der die meisten Funktionen enthält, die moderne Unternehmen für ihre Geschäfte benötigen. Viele MySQL-Kunden (einer kürzlich durchgeführten Umfrage zufolge 44%) setzen sowohl SQL Server als auch MySQL im selben Rechenzentrum ein und verwenden dann das jeweils passende Produkt. Was die Kernfunktionen anbelangt, werden sich sowohl Datenbankadministratoren als auch ITLeiter darüber freuen, daß MySQL über alle notwendigen Funktionen verfügt, um die große Mehrheit der Anwendungsanforderungen zu erfüllen: 3 MySQL-Anwenderumfrage – Dezember 2005. Copyright © 2007, MySQL AB Seite 7 von 49 Leistungsmerkmal Quelloffen Verfügbar für zwei Dutzend Plattformen (32- und 64-Bit), einschließlich Windows: (RedHat, SuSE, Fedora, Solaris, HPUS, AIX, SCO, FreeBSD, Mac OS, Windows) Modulare Speicher-Engine-Architektur (MyISAM, InnoDB, Merge, Memory, Archive, Cluster) Geclusterte, hochverfügbare Datenbank ANSI SQL, SubQueries, Joins, Cursors, Prepared Statements Gespeicherte Prozeduren, Trigger, SQL und benutzerdefinierte Funktionen Aktualisierbare Views ACID-Transaktionen mit Commit, Rollback Verteilte Transaktionen Sperren auf Datensatzebene Snapshots/konsistente, wiederholbare Lesezugriffe (beim Lesen wird der Schreibzugriff nicht gesperrt und umgekehrt) Vom Server erzwungene, referenzielle Integrität Breite Datentypunterstützung (numerisch, VARCHAR, BLOB, etc.) Hochpräzise numerische Datentypen Robuste Indizierung (geclustered, b-tree, hash, Volltext) Dynamische Speichercaches Zentraler Abfragecache Kostenbasierter Optimizer Unicode, UTF-8 XML, XPath Geographische Datentypen Replikation (zeilen- und befehlsbasiert) Partitionierung (Bereich, Liste, Hash, Schlüssel, kombiniert) VLDB-Unterstützung (Terabytes) Hochperformantes Dienstprogramm zum parallelen Laden von Daten Online-Backup mit Point-in-Time-Wiederherstellung Automatischer Neustart/Crash-Recovery Automatisches Speichermanagement (Auto-Expanision, UndoManagement) Komprimierte Tabellen und Archivtabellen Informationsschema/Data Dictionary) Sicherheitsfunktionalitäten (SLL,detailierte Objektprivilegien) Integrierte Datenver- und entschlüsselung Integrierter Task Scheduler Treiber (ODBC, JDBC, .NET, PHP, usw.) GUI-Werkzeuge (Workbench, Administrator, Query-Browser, Migration Toolkit) Tabelle 1 – Die wichtigsten Funktionen des MySQL-Datenbankservers Verfügbarkeit in MySQL √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ Wie oben dargestellt enthält MySQL sehr leistungsstarke Funktionen und übertrifft SQL Server in einigen Bereichen. SQL Server 2005 unterstützt zum Beispiel nur die bereichsbasierte Partitionierung, während MySQL 5.1 Unterstützung für Bereichs-, Hash-, Schlüssel-, Listen- und gemischte Partitionierung einführte. Copyright © 2007, MySQL AB Seite 8 von 49 3.3 Untersuchung der Leistung und Skalierbarkeit von MySQL Eines der Kennzeichen von MySQL war immer die ausgesprochen hohe Leistung in allen Bereichen, unabhängig davon, ob es um die Transaktionsverarbeitung, um Data Warehousing oder um stark frequentierte Websites geht. Wie bereits erwähnt können viele moderne Unternehmen durch den Einsatz einer horizontalen Skalierungsarchitektur in Verbindung mit MySQL unglaubliche Leistungsgewinne verzeichnen, bei denen Daten über zahlreiche MySQLStandardserver vervielfältigt und so verteilt werden, so daß auch die größten Belastungen durch den Endanwender in extrem kurzen Reaktionszeiten verarbeitet werden können. Kunden wie Friendster verarbeiten mit MySQL täglich über 1,5 Milliarden Abfragen auf einer Datenbasis von 24 Terabytes. Andere Kunden wie Craigslist und Sabre Holdings bedienen mit Hilfe von MySQL täglich unzählige Kundenanfragen. Los Alamos Labs verwaltet 7 Terabyte an Daten mit MySQL, Cox Communications registriert innerhalb von zwei Stunden 4 Millionen neue Einträge an Kundendaten – beide Unternehmen stellen hinsichtlich des Data Warehouse fest, daß sich MySQL in punkto Leistungsfähigkeit und Skalierbarkeit mehr als bewährt hat. Alan Walker, Vizepräsident von Sabre äußerte sich so: „MySQL läuft schneller oder zumindest genauso schnell wie jede kommerzielle Datenbank, die wir getestet haben.“ 3.4 MySQL – Immer betriebsbereit, immer funktionsfähig Zuverlässigkeit und verfügbare Betriebszeit sind zwei wichtige technische Anforderungen für jede Software, dies gilt jedoch insbesondere für Datenbanksoftware. MySQL enttäuscht auch in diesem Bereich nicht und bietet viele Funktionen, die dabei helfen, einen kontinuierlichen Datenbankbetrieb zu gewährleisten. Eine eigenständige MySQL-Installation ist extrem zuverlässig, und viele MySQL-Installationen erleben über mehrere Jahre hinweg nur wenige oder gar keine Ausfälle. Wie bereits weiter oben besprochen, setzen viele große Unternehmen die MySQL-Replikation zur Implementierung von horizontalen Skalierungsarchitekturen ein, die eine sehr hohe Redundanz liefert. Das Ergebnis ist ein vollständig unterbrechungsfreier Betrieb über Dutzende und sogar Hunderte von Servern hinweg, so daß oft gar kein Bedarf mehr z.B. an SQL Server Clustering oder Log Shipping besteht. Für Unternehmen, die höchstmögliche Betriebszeiten benötigen, kann MySQL Cluster verwendet werden, um Lösungen für eine 99,999%ige Verfügbarkeit einzurichten. Bei Verwendung einer Shared-Nothing-Architektur wird MySQL Cluster von Kunden eingesetzt, die es sich einfach nicht leisten können, daß ihre Systeme ausfallen. MySQL Cluster ist besonders für Anwendungen wie Transaktions- und Katalogsysteme in den Bereichen Telekommunikation und eCommerce geeignet. MySQL Cluster ist derzeit nur für Linux und Unix verfügbar. Copyright © 2007, MySQL AB Seite 9 von 49 4 Praktische Vorschläge für die einfache Migration von SQL Server zu MySQL In der folgenden Abbildung werden die drei grundlegenden Schritte für die Migration von SQL Server nach MySQL dargestellt: Abbildung 1 – Die drei grundlegenden Schritte bei der Migration von SQL Server zu MySQL 4.1 Alles oder nichts? Vor der Arbeit an jedem einzelnen Migrationsschritt möchten wir auf eine sehr erfolgreiche MySQL-Einsatzstrategie der Kunden hinweisen: Wenn kein Bedarf an speziellen SQL ServerFunktionen besteht kommt bei neuen Projekten MySQL zum Einsatz oder es werden bestehende Anwendungen migriert, während bei ganz besonderen Datenbankanforderungen SQL Server eingesetzt wird. Wie aus Tabelle 1 in diesem Dokument hervorgeht, bietet MySQL das perfekte Gleichgewicht aus Anwenderfreundlichkeit und leistungsstarken Funktionalitäten für die Handhabung der meisten Datenbankanforderungen einer jeden Anwendung. MySQL kann in jeder IT-Infrastruktur auch in Verbindung mit SQL Server oder jeder anderen Datenbankplattform eingesetzt werden, denn seine große Anwenderfreundlichkeit verursacht wenn überhaupt - einen nur sehr geringen Verwaltungsaufwand. Ein Beispiel aus der Praxis ist die Firma Sabre: Hier wird MySQL als Nachschlagewerk für Reservierungen eingesetzt; für komplexe Transaktionsverarbeitungen verwendet Sabre HP Nonstop. 4.2 1. Schritt – Dokumentation des SQL Server-Quellcodes Die Dokumentation der Datenbankstruktur eines bestehenden SQL Servers über manuelle Standardverfahren kann schwierig sein. Obwohl SQL Server über ein sehr gutes MetadatenDictionary verfügt, kann der manuelle Auszug aller Metadaten (Tabelle, Spalte, Index usw.) sehr zeitraubend sein. Copyright © 2007, MySQL AB Seite 10 von 49 Der beste Ansatz besteht hier in der Verwendung eines computerisierten Reverse EngineeringVerfahrens, bei dem alle für die Konvertierung maßgeblichen Metadaten automatisch katalogisiert werden. Dafür kann ein gutes Datenmodellierungs-Werkzeug eines Drittanbieters verwendet werden. Der Markt bietet hier eine Reihe guter Produkte, wie z.B. PowerDesigner von Sybase/Quest und ER/Studio von Embarcadero, welche die Rückentwicklung verschiedener Datenquellen wie z.B. SQL Server unterstützen. MySQL stellt außerdem ein freies Modellierungswerkzeug mit der Bezeichnung MySQL Workbench, das eine Rückentwicklung der SQL Server-Tabellen und Indexstrukturen durchführen kann. Die Verschiebung von Daten und Indexstrukturen nach MySQL ist normalerweise keine besonders schwierige Aufgabe, denn MySQL unterstützt alle wichtigen Datentypen, Tabellendesigns und Indexstrukturen. Eine vollständige Beschreibung zum Vergleich von Datentypen und anderen wichtigen Migrationsmerkmalen für SQL Server und MySQL finden Sie in den Anhängen A - C dieses Dokuments. In Anhang D finden Sie eine schrittweise Beispielmigration von einem SQL Serverschema nach MySQL. Außerhalb codebezogener Objekte wie gespeicherter Prozeduren können einige wenige SQL Server-Objekte nicht eins-zu-eins migriert werden: • • Synonyme Sicherheitsrollen Der schwierigere Teil der Migration ist die Arbeit mit Codeobjekten. Transact-SQL von SQL Server enthält viele Funktionen, von denen viele nicht dem ANSI-Standard entsprechen. Aus diesem Grund muß bei der Betrachtung von gespeicherten Prozeduren, Triggern, Views, benutzerdefinierten Funktionen usw. sehr vorsichtig vorgegangen werden. Neben den allgemeinen Unterschieden bei Syntaxfunktionen und Funktionalität erfordern folgende Elemente besondere Aufmerksamkeit, bevor sie vollständig von SQL Server nach MySQL migriert werden können: • • • • • Assemblies Typen DDL und Statement-basierte Trigger (MySQL hat zeilenbasierte Trigger) Proprietäre SQL Server-Funktionsaufrufe Bestimmte Fälle von dynamischem T-SQL Um die Migration von Datenobjekten von SQL Server nach MySQL zu vereinfachen, stellt MySQL ein frei verfügbares grafisches MigrationsWerkzeug bereit. Dieses Werkzeug enthält auch eine Komponente zur Rückentwicklung, wie sie auch in guten DatenmodellierungsWerkzeugen zu finden ist. Über eine einfach zu verwendende Schnittstelle gibt der Anwender zunächst die Verbindungsdetails für das Quelldatenbanksystem ein und stellt dann eine Verbindung mit der SQL Serverdatenbank her, die zu Migrationszwecken rückentwickelt wird. Mit dem MySQL Migration Toolkit ist es ganz einfach, die notwendigen Metadaten der Quelldatenbank zu erhalten, so daß die Migration rasch gestartet werden kann. Copyright © 2007, MySQL AB Seite 11 von 49 4.3 2. Schritt – Entwurf der MySQL-Zieldatenbanken Nachdem die Quellmetadaten des SQL Servers erhalten und verarbeitet wurden, besteht der nächste Schritt im Entwurf der MySQL-Zieldatenbank. Hierzu gehört vor allem die Übersetzung der Quellobjekte und ihrer Eigenschaften (wie Spaltendatentypen) in MySQL-Gegenstücke. Dieser Schritt kann extrem zeitraubend und fehlerträchtig ausfallen, wenn er manuell durchgeführt wird, denn die meisten Datenbanken beinhalten Tausende von Objekteigenschaften, die konvertiert werden müssen. Eine detaillierte Auflistung der umzuwandelnden Datentypen und Funktionen von SQL Server nach MySQL finden Sie auch hier in Anhang A dieses Dokuments. Bitte beachten Sie, daß die meisten Werkzeuge für die Datenmodellierung die Fähigkeit besitzen, mit nur wenigen Mausklicks ein SQL Server-Schema in ein MySQL-Schema zu konvertieren. MySQL Workbench erledigt automatisch diese Aufgabe, wenn eine Rückentwicklung der SQL Server-Datenbank mit diesem Tool durchgeführt wird. Diese Modelle können natürlich bei Bedarf angepaßt werden. Die automatische Konvertierung von SQL Server in MySQL-Datenobjekte durch die Modeling-Werkzeuge spart große Mengen an Zeit und kann für das Datenbankmigrationsteam zu großen Produktivitätsgewinnen führen. Bei der Konvertierung von Codeobjekten verhält es sich jedoch anders. Eine Reihe von MySQLPartnern arbeitet bereits an Werkzeugen für die automatische Codekonvertierung, mit dem ein Reverse Engineering der T-SQL-Codeobjekte von SQL Server durchgeführt werden kann und konstruieren dafür MySQL-Gegenstücke. Das MySQL Migration Toolkit konvertiert automatisch jede Quelldatenbank, an der mit diesem Tool ein Reverse Engineering durchgeführt wurde, in ein MySQLGegenstück, und zwar vollständig mit allen Datentypübersetzungen und anderen ähnlichen Konvertierungen. Der Anwender hat die vollständige Kontrolle über die exakten, zu migrierenden Objekte sowie darüber, wie MySQL-spezifische Angaben – zum Beispiel, welche Speicher-Engine verwendet werden soll – erfolgen sollen. Wie bereits erwähnt, kann dieser Schritt extrem kompliziert sein, und wird er nicht korrekt durchgeführt, so kann das dazu führen, daß der Datenbankadministrator plötzlich Objekte neu konzipieren oder Datentransferfehler bearbeiten muß, die aufgrund eines ungültigen Datentypmappings auftreten. Wie dem auch sei, wenn Sie das MySQL Migration Toolkit verwenden, gehören diese Probleme der Vergangenheit an, denn dieses Werkzeug erledigt die Arbeit auf Anhieb korrekt. 4.4 3. Schritt - Durchführung der Migration nach MySQL Nachdem die Quellmetadaten von SQL Server erfaßt und die MySQL-Ziel-Datenbank konzipiert wurde, ist der nächste Schritt die Durchführung der tatsächlichen Migration. Die Extrahierungs-, Umwandlungs- und Ladephasen (ETL) können abhängig von den Zielen recht kompliziert sein. Zusätzlich zum MySQL Migration Toolkit gibt es daher viele leistungsstarke ETL-Werkzuge von Drittanbietern auf dem Markt, die eine extreme Flexibilität bei Bewegung, Sammlung, Mapping und Transformation der Daten vom SQL Server zu den MySQL-Datenbanken bieten. Drittanbieter wie Informatica, Embarcadero DT/Studio, Goldengate und andere bieten Support für die Migration Copyright © 2007, MySQL AB Seite 12 von 49 komplexer SQL Server-Datenbanken nach MySQL an. Wenn Sie kontinuierlich Datenbankmigrationen durchführen müssen (zum Beispiel für die Datenübertragung von Quellsystemen in Data Warehouses) ist der Erwerb eines solchen Werkzeugs eine gute Investition. Für einmalige Migrationen ist der Preis für derartige ETL-Tools jedoch zu hoch. Das MySQL Migration Toolkit kann hier hilfreich sein, denn es bietet eine Reihe an Optionen für den Transfer einer Quelldatenbank von SQL Server nach MySQL. Das MySQL Migration Toolkit steht frei zur Verfügung und ist und unter der Open-Source-GPL-Lizenz veröffentlicht. Auch Microsoft bietet Data Transformation Services (DTS für SQL Server 2000) und Integration Services (SQL Server 2005) an, die bei einer Migration von SQL Server nach MySQL hilfreich sein können. Microsofts integrierte Migrationswerkzeuge unterstützen den Datenbankadministrator beim mühelosen Transfer von SQL Server-Daten nach MySQL. Wenn Sie SQL Server verwenden, mit den Integration Services jedoch nicht vertraut sind, können Sie die Daten mit Hilfe einer Kombination des SQL Server Bulk Copy-Programms (BCP) und dem MySQL LOAD DATA INFILE-Dienstprogramm von SQL Server nach MySQL transferieren. Wenn die Daten durch ein geeignetes Zeichen getrennt sind (wie z.B. durch ein Komma, Semikolon etc.), dann kann der DBA Datenfiles mit SQL Server BCP erstellen und dann mit LOAD DATA INFILE unter Angabe desselben Trennzeichens nach MySQL laden. Eine letzte Möglichkeit zum Laden einer SQL Server-Datenbank nach MySQL mit Hilfe von Microsoft besteht in der Verwendung der Exportmöglichkeiten von Microsoft Access. Der Datenbankadministrator kann durch Klicken auf eine Access-Tabelle und eine Kombination aus Exportfunktion und dem ODBC-Treiber von MySQL jeden Datensatz aus Access nach MySQL exportieren. Bitte achten Sie darauf, daß die Indizes normalerweise nicht mit der Tabellenstruktur und den Daten exportiert werden. Eine Strategie für die Datenmigration besteht in der Migration aller bestehenden SQL ServerObjekte und Daten aus der Quelldatenbank in eine MySQL Staging-Datenbank. Nachdem die Daten sicher im MySQL Datenbankserver angekommen sind, kann der DBA oder Entwickler gespeicherte Prozeduren oder anderen Migrationscode erzeugen, anhand dessen die Daten dann selektiv von der Staging-Datenbank in eine andere MySQL-Datenbank zur weiteren Entwicklung oder Produktion manipuliert oder transferiert werden. Eine weitere Option besteht in den Scripting-Fähigkeiten des MySQL Migration Toolkits für die Übermittlung der Daten beim Transfer von der SQL Server-Quelle zur MySQL-Zieldatenbank. Obwohl die meisten Anwender die grafische Benutzerschnittstelle zur Durchführung von Datenbankmigrationen mit der Maus verwenden werden, so können fortgeschrittene Anwender die zugrundeliegende Architektur einsetzen, um – falls erforderlich - komplexere ETL-Prozesse zu erstellen und zu planen. Bei umfangreichen Transformationen von SQL Server-Daten bewegt das Migration Toolkit die Daten als Bulk und stellt sicher, daß alle Datenbank- und Objekteigenschaften, die zu schnellen Ladezeiten führen, automatisch eingestellt werden. Die Anwender des Migration Toolkits werden über einfach abzulesende Anzeigen und andere Informationsmeldungen über den Fortschritt des Migrationsverfahrens auf dem Laufenden gehalten. Nach Beendigung der Migration erhält der Anwender einen zusammenfassenden Bericht aller durchgeführten Aufgaben. 4.5 Validierung der Migration von SQL Server nach MySQL Nachdem alle Informatioenn von der SQL Server-Quelldatenbank nach MySQL extrahiert wurden, empfehlen wir Ihnen, abschließende Tests durchzuführen, um sich zu vergewissern, daß im Hinblick auf die Übereinstimmung von Objekten und Datensatzanzahl sowie auf ergänzende Elemente wie Indizes und unterstützende Codeobjekte (Views etc.) alles in Ordnung ist. Auch die Durchführung einer Reihe von Benchmarktests, anhand derer Sie feststellen können, ob die Leistung akzeptabel ist, ist eine gute Idee. Dieser Schritt wird von allen Migrationsprozessen vielleicht am meisten vernachlässigt, da er naturgemäß nicht so einfach auszuführen ist. Copyright © 2007, MySQL AB Seite 13 von 49 Gute Leistungstests erfassen die Leistungsprobleme, die von ungeeigneten Anwender- und Qualitätssicherungstests übersehen werden. Leistungstests simulieren nur das, was beim tatsächlichen Einsatz erwartet wird. Sie belasten die MySQL-Datenbank auf eine Weise, die sonst nur durch gleichzeitige Zugriffe aller möglichen Nutzer erreicht werden könnte (Spitzenlast). Intelligente Leistungstests verwenden folgende Komponenten für eine realistische Simulation dessen, was in einer produktiven Datenbank geschieht: • Erwartete Anwenderpräsenz – Es ist entscheidend, daß der Test die Anzahl der Anwenderverbindungen simuliert, die zu Spitzenzeiten und zu normalen Arbeitszeiten erwartet werden. Dies ist der größte Bereich, in dem manuelle Methoden, bei denen nur ein Teil der Anwender zum Test von Datenbank und Anwendung verwendet werden, scheitern. Die Datenbank funktioniert eventuell mit 10 Anwendern vollkommen problemlos, scheitert jedoch, wenn 400 Verbindungen hergestellt werden. • Wiederholte Anwenderaktivität – Nachdem die erwartete Anzahl an Anwendern Verbindungen mit der Datenbank hergestellt hat, müssen die Anwender natürlich „etwas tun", damit das System belastet wird. Und diese „Etwas“ dürfen sie nicht nur einmal tun. Entweder alle oder ein Teil der Anwender müssen die Aufgaben wiederholt durchführen, ganz genau so, wie es an einem normalen Arbeitstag erfolgen würde. Bei einem OLTPSystem kann dies die Eingabe zahlreicher Aufträge bedeuten. Bei einem Date Warehouse hingegen kann das umfangreiche analytische Abfragen bedeuten. Wichtig ist, daß die Arbeit wiederholt durchgeführt wird, so daß die Datenbank immer neuen Belastungsspitzen ausgesetzt ist. • Erweiterte Dauer – Nachdem Sie eine Anzahl von Sessions eingestellt haben, in denen wiederholt Aufgaben durchgeführt werden, besteht Ihr nächster Schritt darin sicherzustellen, daß die Arbeit über eine bestimmte Dauer fortgesetzt werden kann, damit der Test überhaupt sinnvoll ist. Sie suchen hier nach Problemen, die sich erst im Laufe der Zeit entwickeln. Die Fragmentierung einer MySQL-Tabelle erfolgt vielleicht nicht nach 30 Minuten OLTP-Arbeit, jedoch ganz überraschend und auf dramatische Weise nach 2 oder mehr Stunden wiederholter Aktivität. • Erwartetes Produktivdatenvolumen – Um ein aussagekräftiges Testergebnis zu erhalten, müssen Sie Testdaten in Ihre Datenbank laden, die in etwa der Größe Ihrer tatsächlichen Datenbank entsprechen. Dies ist einfach zu erreichen, wenn eine bestehende produktive Datenbank nach MySQL migriert wurde. Die meisten Datenbankadministratoren sind ratlos, wie sie in der Praxis alle oben erwähnten Punkte umsetzen sollen. Es gibt Open-Source Benchmark-Werkzeuge; die meisten verfügen aber über Unzulänglichkeiten bei der Durchführung von korrekten Performanz-Tests, sodaß das eigentliche Ziel verfehlt wird. Hier kann Software von Drittanbietern Abhilfe schaffen, wobei nicht jede Software gleich gut geeignet ist. Ein sehr gutes Leistungstestwerkzeug, Benchmark Factory, wird von Quest Software vertrieben. Benchmark Factory ist extrem einfach zu verwenden und bietet flexible, per Maus bedienbare Assistenten, die den Anwender durch den vollständigen Einrichtungsprozess führen und viele der standardmäßigen TPC-Benchmarktests für MySQL als auch andere skalierbare Leistungstests durchführen. Nach Beendigung der Tests liefert Benchmark Factory Analysen mit einfachen Vergleichsläufen und kann die Testergebnisse nach Microsoft Excel exportieren. Mit MySQL 5.1 wurde ein neues Dienstprogramm eingeführt – mysqlslap. Mit diesem Programm kann über die Befehlszeile ein Leistungsvergleich für MySQL Server durchgeführt werden. Mit diesem Programm können auf schnelle Weise Testschemata generiert, Testdaten eingepflegt und eine beliebige Anzahl an virtuellen Nutzern erzeugt werden, die eine Folge von vordefinierten oder kurzfristig erstellten SQL-Befehlen auf der Testdatenbank ausführen. Im Anschluß werden die Testergebnisse zurückgemeldet. Copyright © 2007, MySQL AB Seite 14 von 49 4.6 Ratschläge zur gemeinsamen Handhabung von SQL Server und MySQL Wie sehen die optimalen Verfahren für einen Datenbankadministrator aus, wenn MySQL in einem Rechenzentrum parallel zu SQL Server betrieben werden soll? Obwohl die nachfolgenden Empfehlungen keinen Anspruch auf Vollständigkeit haben, sollen sie Datenbankadministratoren dabei helfen, so produktiv wie möglich zu arbeiten. • Datenbankwerkzeuge können bei korrekter Wahl zu großen Produktivitätsgewinnen führen. Viele Drittanbieter von Datenbankwerkzeugen unterstützen heute MySQL und gleichzeitig SQL Server. Der DBA sollte also herausfinden, ob die Verwendung dieser Werkzeuge für ihn sinnvoll ist. Quest TOAD wird zum Beispiel aufgrund der großen Zeiteinsparungen in vielen SQL Server Shops verwendet. Ein Datenbankverwalter, der die TOAD-Schnittstelle kennt, kann durch Verwendung von Toad for MySQL von Quest ganz einfach zu MySQL wechseln. Das Gleiche gilt auch für die Anwender von DBArtisan von Embarcadero, das SQL Server unterstützt. DBArtisan unterstützt jetzt MySQL, so daß der DBA nur ein einziges Tool zur Handhabung sowohl der SQL Server- als auch der MySQL-Plattform verwenden muß. Der DBA kann natürlich auch die Werkzeuge seines Datenbanklieferanten wie Management Studio für SQL Server (Enterprise Manager für SQL Server 2000 und darunter) und die Administrator- und Query Browser-Tools von MySQL (alle frei von MySQL) verwenden. • SQL Server-DBAs, die daran gewöhnt sind, daß sich der SQL Server automatisch selbst verwaltet, sollten die entsprechenden zusätzlichen MySQL-Funktionen verwenden, so daß zusätzlicher Verwaltungsaufwand vermieden wird. Dazu gehören unter anderem die Aktivierung der InnoDB Tablespace-Dateien für die automatische Größenanpassung (entspricht der Aktivierung der Autogrowth-Eigenschaft für SQL Server-Daten und Logfiles), die Einrichtung des MySQL Binary Loggings für die Point-in-TimeWiederherstellung (entspricht der Verwendung eines vollständigen Wiederherstellungsmodells unter SQL Server mit periodischen Transaktions-Logdumps) und andere ähnliche Funktionen. • Denken Sie daran, daß Sie anders als bei SQL Server in MySQL eine Reihe unterschiedlicher zugrundeliegender Speicher-Engines zur Verfügung haben, die für bestimmte Anwendungsszenarien gedacht sind. Vergewissern Sie sich, daß Sie die richtige Engine für den richtigen Zweck verwenden. • Großzügige Speicherzuweisungen führen bei MySQL genau wie bei SQL Server zu Leistungssteigerungen. Achten Sie also darauf, daß abhängig von der zugrundeliegenden Engine genügend RAM für den Speicherzugriff auf die Daten (im Gegensatz zum Lesen von der Festplatte) verfügbar ist, denn die Standardeinstellungen für MySQL sind für fast alle Geschäftsanwendungen zu niedrig. Seien Sie sich auch bewußt, daß das ständige Lesen der Daten in den RAM - wie bei SQL Server - nicht bedeutet, daß der aktuelle SQL-Code wirklich auch effizient ist. Unnötige logische Ein/Ausgabe-Operationen können die Leistung genau wie physische Ein- und Ausgaben beeinträchtigen. o Geclusterte Indizes weichen in MySQL leicht von denen in SQL Server ab: Geclusterte Indizes sind nur mit der InnoDB-Speicherenginge verfügbar. Geclusterte Indizes müssen auf dem Primärschlüssel der Tabelle angelegt werden. Wird ein geclusterter Index nicht explizit auf einer InnoDB-Tabelle definiert, erstellt MySQL automatisch einen Index auf einem Primärschlüssel, einem eindeutigen Schlüssel (wenn ein Primärschlüssel nicht verfügbar ist) oder auf einem internen Row-Identifier, wenn die Tabelle keine eindeutigen Schlüssel enthält. • Die Partitionierung in MySQL erfordert anders als bei SQL Server nicht das Erstellen von Partitionsfunktionen oder Partitionsschemata. Die Partitionen und die Partitionsmethoden (Range, Hash, Key, List, Composite) werden statt dessen in der DDL für die Tabellenerstellung definiert. Copyright © 2007, MySQL AB Seite 15 von 49 • Linked Server und partitionierte Views von SQL Server können mit Hilfe der FederatedSpeicher-Engine von MySQL imitiert werden. • Anders als SQL Server 2005 erfolgt die Aktivierung von „Snapshot Read“ (beim Lesezugriff wird der Schreibzugriff nicht verhindert und umgekehrt) in MySQL automatisch und erfordert keinerlei Einstellung von Datenbankoptionen oder einleitenden SQL-Statements mit speziellen Befehlen für Snapshot-Isolation-Lesevorgänge. SnapshotRead ist zurzeit jedoch nur für besondere Speicherengines verfügbar (wie InnoDB, Archive etc.). Schlagen Sie also im aktuellen MySQL-Handbuch nach, welche Sperrfunktionen für jede Engine unterstützt werden. • Wenn mehrere MySQL-Instanzen parallel betrieben werden (wie viele DBAs dies mit SQL Server tun), dann sollte der MySQL Instance Manager verwendet werden. Er wurde mit Version 5.0 eingeführt und erhöht die Produktivität der MySQL DBAs, indem er eine einfache Möglichkeit bietet, MySQL-Instanzen remote zu starten, anzuhalten, zu bearbeiten und zu steuern. Darüber hinaus ermöglicht dieses Werkzeug den einfachen Fernzugriff auf Fehlerprotokolle und andere Vorgänge, die MySQL protokolliert. • Da ein ineffizienter SQL-Code negative Auswirkungen auf eine sonst gut laufende MySQL-Datenbank haben kann, sollten Sie als MySQL-Datenbankadministrator das Slow Query Log aktivieren, um auf diese Weise schlecht abgestimmten SQL-Code ausfindig zu machen und die Ergebnisse regelmäßig im Protokoll zu überprüfen. Mit MySQL können das Slow Query Log oder das General Log so eingerichtet werden, daß die Ergebnisse, die in den dynamischen Management-Views oder in SQL Profiler von SQL Server zum Aufspüren von schlechtem Code zu finden sind, automatisch widergespiegelt werden. Version 5.1 liefert SQL-Leistungstabellen, die über SQL abgerufen werden können, um Metriken über ineffizienten Code zu erhalten. Für eine weitere Leistungsüberwachung können die Befehle MySQL SHOW GLOBAL STATUS und SHOW INNODB STATUS zur Untersuchung der rohen MySQL-Leistungsmetriken verwendet werden. MySQL Enterprise bietet mit dem MySL Enterprise Monitor erweiterte Überwachungs- und Beratungsfunktionen und sollte in den meisten produktiven Umgebungen verwendet werden, in denen MySQL eingesetzt wird. • MySQL DBAs sollten für die Überprüfung des MySQL-Fehlerprotokolls auf ungewöhnliches Verhalten dieselben Pläne wie zur Überprüfung der SQL Server Error/Notification Logs verwenden. • Wenn Sie es gewohnt sind, den SQL Server Agent zur Planung und Ausführung von SQL/T-SQL-Jobs zu verwenden, dann können Sie in MySQL 5.1 den Event Scheduler für denselben Zweck verwenden. • DBAs mit produktiven Anwendungen, die eine Überwachung rund um die Uhr benötigen, sollten MySQL Enterprise in Betracht ziehen, denn die zertifizierte Software liefert eine hohe Zuverlässigkeit, während die Softwareupgrades und Überwachungs/Advisorydienste proaktiv dabei helfen, eine möglichst hohe verfügbare Betriebszeit zu gewährleisten und bei der Diagnose und Lösung von Leistungsproblemen Unterstützung bieten. 5 Fazit Vom geschäftlichen und technischen Standpunkt aus betrachtet ist die Frage, ob eine Migration von SQL Server nach MySQL sinnvoll ist, schnell beantwortet. Zahreiche Unternehmen kommen durch den Einsatz von MySQL in den Genuß gewaltiger Kosteneinsparungen. Gleichzeitig betreiben sie ihre anspruchsvollsten datenbankgetriebenen Systeme mit Hilfe der benutzerfreundlichen Scale-Out-Architektur von MySQL. Obwohl die SQL Server-Datenbankmigration normalerweise nicht leicht ist, gewährleisten Sie durch die Verwendung der in diesem Dokument dargelegten Migrationsschritte einen problemlosen, erfolgreichen Wechsel zu MySQL. Zur Unterstützung der Migration von SQL Copyright © 2007, MySQL AB Seite 16 von 49 Server bietet MySQL das frei verfügbare Migration Toolkit, mit dem bei der Datenbankmigration erhebliche Zeit eingespart werden kann, während die Fehler, die normalerweise bei der manuellen Durchführung derart komplexer Operationen entstehen, erheblich gesenkt werden. Der Wechsel von SQL Server nach MySQL kann – unabhängig davon, ob er vollständig oder teilweise erfolgt und ob MySQL und SQL Server für entsprechende Anwendungssituationen verwendet werden – sehr sinnvoll sein, sowohl vom finanziellen als auch vom technologischen Standpunkt aus betrachtet. Wenn Sie die Vorschläge und Schritte in diesem Dokument folgen, können Sie sicher sein, daß Ihre Implementierung von MySQL erfolgreich sein wird. Unabhängig davon, ob Sie lediglich einen Testlauf mit Open Source durchführen möchten oder sich bereits auf MySQL festlegen und es damit zu Ihrer bevorzugten Datenbankplattform machen. 6 Weitere Informationsquellen 6.1 MySQL Migrationshilfen MySQL Migration Toolkit http://www.mysql.de/products/tools/migration-toolkit/ Die graphische Migration einer beliebigen Datenbank auf MySQL, auf die mit Hilfe von Oracle, SQL Server, Microsoft Access oder JDBC zugegriffen werden kann. Weitere Infos auf den MySQL-Webseiten http://www.mysql.de/why-mysql/migration/ Erfahren Sie, wie Sie schnell und leicht Ihre bestehende Datenbank auf MySQL migrieren können. Migrationsforen http://forums.mysql.com/ Arbeiten Sie mit anderen MySQL-Experten zusammen, die mit aktuellen Datenbankmigrationen beschäftigt sind. MySQL Migrationsstarthilfe http://www.mysql.de/consulting/packaged/migration.html Wenn Sie einen MySQL-Berater benötigen, der Ihnen bei Ihrem Datenbank-Migrationsprojekt Starthilfe gibt, dann ist das Beratungspaket MySQL Migrationsstarthilfe genau das richtige für Sie. Unsere Seniorberater nutzen bewährte Methodiken, um von Oracle, Sybase, Microsoft SQL Server, DB2, Informix und anderen Datenbanksystem auf MySQL zu migrieren. 6.2 Anwenderberichte The Phone House Telecom wählt MySQL Enterprise Gold als Datenbank-Standard http://www.mysql.de/why-mysql/case-studies/de/mysql-phonehouse.php.de Onlineshop, CMS und Online-Rechnung waren bei The Phone House Telecom GmbH unabhängige Systeme und verteilt auf Informix- und Oracle-Datenbanken. Vereinzelt wurde MySQL für eigenentwickelte neue Funktionen eingesetzt. Diese nur schwer zu wartende Systemlandschaft sollte mit einem grundlegenden Neuaufbau des Systems vereinheitlicht werden. Heute laufen alle Websysteme (Händler Online-Aktivierungs- und Informationssystem, CMS, Onlineshop, Kundenselbstadministration einschließlich Online-Rechnung) über einen einheitlichen Softwarekern auf Basis von PHP mit dem MySQL Enterprise Server als Datenbank. Cox Communications betreibt große Data Warehouse-Anwendungen mit MySQL, MySQL AB http://www.mysql.com/it-resources/case-studies/cox.php Cox Communications ist der viertgrößte Anbieter für Kabelfernsehen in den Vereinigten Staaten und bedient rund 6,3 Millionen Kunden. Um eine optimale Leistungsfähigkeit und ein hohes Niveau an Kundenservice sicherzustellen, hat Cox ein riesiges Data Warehouse-System Copyright © 2007, MySQL AB Seite 17 von 49 entwickelt. Das Herzstück dieses geschäftskritischen Systems bildet eine MySQL-Datenbank mit 2 Milliarden Datensätzen. Friendster skaliert horizontal mit MySQL Enterprise, MySQL AB http://www.mysql.com/it-resources/case-studies/cox.php Friendster, die größte Webseite zum Social Networking mit über 60 Millionen Seitenansichten täglich wählte MySQL Enterprise, um die richtige Kombination an erschwinglicher Zuverlässigkeit und Skalierbarkeit der Datenbank zu erreichen. Ihr horizontal skaliertes LAMP-System verarbeitet über eine Milliarde Datenbankabfragen am Tag. Zudem konnte das IT-Personal Millionen Dollar Hardware- und Softwarekosten einsparen. Citysearch spart über 1 Million Dollar mit MySQL, MySQL AB http://www.mysql.com/why-mysql/case-studies/mysql-citysearch-casestudy.php Citysearch ist ein führender regionaler Online-Suchservice, der die aktuellsten Informationen zu Unternehmen – von Restaurants und Handel bis hin zu Reisen und qualifizierten Dienstleistungen - zur Verfügung stellt. Diese Webseite verzeichnet monatlich über 10 Millionen einzelne Besucher. Die Anzahl der Nutzer stieg exponentiell an, sodaß das ursprüngliche Oracle-System dem Datenverkehr der Webseite nicht mehr gewachsen war. Zur Verarbeitung des Datenverkehrs und einem Terabyte an Daten wurden replizierte MySQL-Server eingesetzt – damit war Citysearch in der Lage, eine extrem hochleistungsfähige Lösung zur Verfügung zu stellen und zusätzlich über 1 Million Dollar an Datenbanklizenzen und Hardwarekosten einzusparen. 6.3 White Paper Leitfaden zur Senkung der Datenbankkosten (TCO), MySQL AB http://www.mysql.de/tco Ein Artikel in der Computerworld „MySQL Breaks Into the Data Center“ zeigte auf, wie MySQL zur populärsten Open-Source-Datenbank der Welt wurde und warum sie von Unternehmen, die darauf bedacht sind, ihre Betriebskosten zu senken eingesetzt wird, um ihre IT-Infrastruktur zu vereinheitlichen. In diesem White Paper zeigen wir Ihnen, wie Sie dabei vorgehen können. Sie erfahren außerdem, wie Organisationen wie Cox Communications, NASA, Sabre Holdings und Yahoo! Zuverlässigkeit, Leistungsfähigkeit und Datenbankbetriebskosten durch den Einsatz von MySQL verbessert haben. Kostengünstiges Datenbank Scale-Out durch den Einsatz von MySQL, MySQL AB http://www.mysql.de/why-mysql/white-papers/scale-out.php Zahlreiche moderne Unternehmen setzen MySQL in Verbindung mit handelsüblicher Hardware ein, um hohe Kosteneinsparungen und nahezu uneingeschränkte Anwendungsskalierbarkeit zu erreichen. In diesem White Paper werden wir die Techniken behandeln, welche MySQL-Kunden heute einsetzen, um ihre wichtigsten Unternehmensanwendungen zu betreiben und abzusichern. Copyright © 2007, MySQL AB Seite 18 von 49 7 Anhang A – MSSQL to MySQL - Datatypes 7.1 Overview This section provides a quick listing of the compatibility between SQL Server and MySQL with respect to datatypes. 7.2 Comparable Datatypes The following datatypes can be mapped in a one-to-one relationship from SQL Server to MySQL: • BIGINT • BINARY • BIT • CHAR • CHARACTER • DATETIME • DEC, DECIMAL • FLOAT • DOUBLE PRECESION • INT, INTEGER • NCHAR, NATIONAL CHARACTER • NVARCHAR, NCHAR VARYING • NATIONAL CHAR VARYING, NATIONAL CHARACTER VARYING • NUMERIC • REAL • SMALLINT • TEXT • TIMESTAMP • TINYINT • VARBINARY • VARCHAR, CHAR VARYING, CHARACTER VARYING Note that the DATETIME datatype in MySQL is a seven byte value that is currently down to the second precision (although a future release will allow greater granularity), while SQL Server is an eight byte value that has granularity down to the 3/100 second precision. In addition, TIMESTAMP is a special datatype that is typically used to store the time a row was last created or updated (which MySQL handles automatically). 7.3 Datatypes Requiring Conversion The following map can be used to convert SQL Server datatypes that do not map in 1-to-1 relationship to MySQL: SQL Server IDENTITY NTEXT, NATIONAL TEXT SMALLDATETIME MONEY SMALL MONEY UNIQUEIDENTIFIER SYSNAME Copyright © 2007, MySQL AB MySQL AUTO_INCREMENT TEXT CHARACTER SET UTF8 DATETIME DECIMAL(19,4) DECIMAL(10,4) BINARY(16) CHAR(256) Seite 19 von 49 8 Anhang B – SQL Server to MySQL – Predicates 8.1 Overview This section provides a list of the SQL predicates supported by SQL Server Database 10g and compares them to equivalent predicates supported by MySQL version 5.0. The predicates are split into nine categories: • • • • • • • Predicates for comparison conditions Predicates for exists conditions Predicates for floating-point conditions Predicates for in conditions Predicates for null conditions Predicates for pattern matching conditions Predicates for range conditions 8.2 Synopsis SQL Server and MySQL 5.0 both support the use of conditions in the WHERE clause of the SELECT, DELETE, and UPDATE statements, as well as in the HAVING clause of the SELECT statement. 8.3 Boolean conditions A Boolean condition combines two other conditions, to return a single result. SQL Server supports three Boolean conditions. Summary Each SQL Server Boolean condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server boolean conditions expression1 AND expression2 Returns TRUE if both expressions return TRUE, UNKNOWN if either expression is NULL, FALSE otherwise. MySQL equivalent: AND NOT expression Negates the result of expression; returns TRUE if expression is FALSE, UNKNOWN if expression is NULL, and FALSE if expression is TRUE. MySQL equivalent: NOT expression1 OR expression2 Returns TRUE if either expression returns TRUE, UNKNOWN if either expression is NULL, FALSE otherwise. MySQL equivalent: OR 8.4 Comparison conditions Comparison conditions compare two expressions. SQL Server supports eight comparison conditions. Summary Each SQL Server comparison condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. Copyright © 2007, MySQL AB Seite 20 von 49 SQL Server comparaison conditions expression1 = expression2 Returns TRUE if the expressions are equal, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: = expression1 <> expression2 Additional formats accepted (not all forms available on every platform): != ^= ¬= Returns TRUE if the expressions are not equal, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: <> != expression1 < expression2 Returns TRUE if expression1 is less than expression2, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: < expression1 <= expression2 Returns TRUE if expression1 is less than or equal to expression2, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: <= expression1 > expression2 Returns TRUE if expression1 is greater than expression2, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: > expression1 >= expression2 Returns TRUE if expression1 is greater than or equal to expression2, UNKNOWN if either expression is NULL, and FALSE otherwise. MySQL equivalent: >= expression1 comparison ANY expression2 expression1 comparison SOME expression2 Synonyms; return TRUE if the comparison condition returns TRUE for at least one value in expression2 and FALSE if the comparison condition returns either FALSE for every value in expression2 or returns an empty set (zero rows). comparison must be one of: = <> < <= > >=. expression2 is generally a subquery, but may resolve to any expression. MySQL equivalent: ANY, SOME, provided expression2 is a subquery. expression1 comparison ALL expression2 Returns FALSE if the comparison condition returns FALSE for at least one value in expression2 and TRUE if the comparison condition returns either TRUE for every value in expression2 or returns an empty set (zero rows). comparison must be one of: = <> < <= > >=. expression2 is generally a subquery, but may resolve to any expression. MySQL equivalent: ALL, provided expression2 is a subquery. Copyright © 2007, MySQL AB Seite 21 von 49 8.5 Exists conditions Exists conditions test for rows in a sub query. SQL Server supports two exists conditions. Summary Each SQL Server exists condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server exists conditions EXISTS (subquery) Returns TRUE if subquery returns at least one row, FALSE otherwise. MySQL equivalent: EXISTS NOT EXISTS (subquery) Returns TRUE if subquery returns zero rows, FALSE otherwise. MySQL equivalent: NOT EXISTS 8.6 In conditions In conditions test whether a value is found in a set. SQL Server supports two in conditions. Summary Each SQL Server in condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server in conditions expression IN {value_list | (subquery)} Returns TRUE if expression equals any value in value_list (or returned by subquery), UNKNOWN if either argument is NULL, FALSE otherwise. MySQL equivalent: IN expression NOT IN {value_list | (subquery)} Returns TRUE if expression does not equal any value in value_list (or returned by subquery), UNKNOWN if either argument is NULL, FALSE otherwise. MySQL equivalent: NOT IN 8.7 Null conditions Null conditions test for null values. SQL Server supports two null conditions. Summary Each SQL Server null condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server null conditions expression IS NULL Copyright © 2007, MySQL AB Seite 22 von 49 Returns TRUE if the result of expression is NULL, FALSE otherwise. MySQL equivalent: IS NULL expression IS NOT NULL Returns TRUE if the result of expression is not NULL, FALSE otherwise. MySQL equivalent: IS NOT NULL 8.8 Pattern matching conditions Pattern matching conditions test whether a value matches a specific pattern. SQL Server supports nine pattern matching conditions. SQL Server pattern matching conditions string_expression LIKE pattern [ESCAPE escape_string] Returns TRUE if string_expression matches pattern, UNKNOWN if any argument is NULL, FALSE otherwise. Uses the current (input) character set to interpret all arguments. MySQL equivalent: LIKE string_expression NOT LIKE pattern [ESCAPE escape_string] Returns TRUE if string_expression does not match pattern, UNKNOWN if any argument is NULL, FALSE otherwise. Uses the current (input) character set to interpret all arguments. MySQL equivalent: NOT LIKE 8.9 Range conditions Range conditions test for inclusion in a range of values. SQL Server supports two range conditions. Summary Each SQL Server range condition has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server range conditions expression1 BETWEEN expression2 AND expression3 Returns TRUE if expression1 falls into the range of values specified by the other expressions (i.e. if expression1 is greater than or equal to expression2 and less than or equal to expression3), UNKNOWN if any expression is NULL, FALSE otherwise. MySQL equivalent: BETWEEN expression1 NOT BETWEEN expression2 AND expression3 Returns TRUE if expression1 does not fall into the range of values specified by expression2 and expression3, UNKNOWN if any expression is NULL, FALSE otherwise. MySQL equivalent: NOT BETWEEN Copyright © 2007, MySQL AB Seite 23 von 49 9 Anhang C – SQL Server to MySQL – Operators and Date Functions 9.1 Overview This paper provides a list of the built-in SQL operators supported by SQL Server Database 10g and compares them to equivalent operators supported by MySQL version 5.0. The operators are split into five categories: • • • • Arithmetic operators Concatenation operators Hierarchical Query operators Set operators 9.2 Arithmetic operators Summary Each SQL Server arithmetic operator has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server arithmetic operators + When used as a unary operator, indicates a positive numeric or temporal expression. When used as a binary operator, adds two numeric or temporal values. MySQL equivalent: + When used as a unary operator, indicates a negative numeric or temporal expression. When used as a binary operator, subtracts one numeric or temporal value from another. MySQL equivalent: * Binary operator; multiplies numeric expressions. MySQL equivalent: * / Binary operator; divides numeric expressions. MySQL equivalent: / 9.3 Concatenation operators Summary When the MySQL server is started with the –ansi option, the SQL Server || (concatenation) operator has an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. When the MySQL server is started in the default mode, map SQL Server || to MySQL CONCAT('string1', 'string2'). No other concatenation operators are supported by SQL Server, although SQL Server's CONCAT string function serves the same purpose. Copyright © 2007, MySQL AB Seite 24 von 49 SQL Server concatenation operators + Concatenates character strings and CLOB values. MySQL equivalent (--ansi mode): || MySQL equivalent (default mode): CONCAT('string1', 'string2') 9.4 Hierarchical query operators Summary SQL Server LEVEL has no MySQL equivalent. 9.5 Set operators Summary SQL Server INTERSECT and EXCEPT have no MySQL equivalent. All other SQL Server set operators have an exact MySQL equivalent, and therefore no action is necessary when migrating from SQL Server to MySQL. SQL Server set operators UNION Combines two SELECT queries. Returns all distinct (non-duplicate) rows found by either SELECT. MySQL equivalent: UNION. UNION ALL Combines two SELECT queries. Returns all rows found by either SELECT, including duplicates. MySQL equivalent: UNION ALL. Copyright © 2007, MySQL AB Seite 25 von 49 9.6 Date Functions Summary The majority of date functions in SQL Server can be replicated in MySQL. Date Formats SQL Server YYYYMMDD YYYY MonthName DD MM/DD/YY[YY] MM-DD-YY[YY] MM.DD.YY[YY] MySQL YYYYMMDD YY[YY]-MM-DD YY[YY]/MM/DD YY[YY]-MM-DD YY[YY].MM.DD Date Functions SQL Server DATEADD(day, 1, GETDATE()) DATEDIFF(day, GETDATE(), GETDATE()-1) DATENAME(month, GETDATE()) DATENAME(weekday, GETDATE()) DATEPART(month, GETDATE()) DAY(GETDATE()) GETDATE() GETDATE() + 1 GETUTCDATE() MONTH(GETDATE()) YEAR(GETDATE()) Copyright © 2007, MySQL AB MySQL DATE_ADD(NOW(), INTERVAL 1 DAY) DATEDIFF(NOW(), NOW() – INTERVAL 1 DAY) DATE_FORMAT(NOW(), ‘%M’) MONTHNAME(NOW()) DATE_FORMAT(NOW(), ‘%W’) DAYNAME(NOW()) DATE_FORMAT(NOW(), ‘%m’) DATE_FORMAT(NOW(), ‘%d’) DAY(NOW()) (as of MySQL 4.1.1) DAYOFMONTH(NOW()) NOW() SYSDATE() CURRENT_TIMESTAMP CURRENT_TIMESTAMP() NOW() + INTERVAL 1 DAY CURRENT_TIMESTAMP + INTERVAL 1 DAY UTC_TIMESTAMP() MONTH(NOW()) YEAR(NOW()) Seite 26 von 49 10 Anhang D – T-SQL Conversion Suggestions 10.1 Overview As of March 2006 the MySQL migration tool does not migrate MS SQL Transact SQL code to MySQL. Because of this stored procedures and other code objects in SQL Server need to be migrated manually. This appendix provides suggestions in converting Microsoft T-SQL code to MySQL. 10.2 Getting T-SQL Code out of SQL Server The stored procedures are extracted from SQL Server using the SQL Server ‘create scripts’ option with all Stored Procedure selected and the generate a file for each stored procedure flag selected. 10.3 Procedure Formats While the general format for an MS stored procedure is: CREATE PROCEDURE name Param1 type, Param2 type AS Statement1 Statement2 MySQL requires that a format of: CREATE PROCEDURE name ( Param1 type, Param2 type ) BEGIN Statement1 ; StateMent2 ; … END ; With the major differences being that MySQL: 1. 2. 3. 4. 5. Requires that the parameter list be in ‘(‘ ‘)” pairs Cannot take an AS after the parameter list Requires a BEGIN END pair if there is more than one statement in the stored procedure Requires that every statement is terminated by a ‘;’. In MySQL stored procedures all variable declarations must come before the first non-declare statement. 10.4 Error Handling In SQL Server, errors below a certain level are returned in @@ERROR and the Stored Procedure continues while errors above that level terminate the Stored Procedure immediately and return and error to the caller. In MySQL most errors terminate the Stored Procedure and return an error code. To get a MySQL Stored Procedure to behave more like a SQL Server Stored Procedure you must define an error handler as follows: DECLARE "@ERROR" INT DEFAULT 0; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN Copyright © 2007, MySQL AB Seite 27 von 49 SET "@ERROR" = 1; END; And then modify your Stored Procedure code to use the @ERROR variable instead of @@ERROR, for example, replace: IF @@ERROR <>0 GOTO ERROUT UPDATE MessageBoardEntries SET ReplyCount = ReplyCount - 1 WHERE EntryID = @EntryID IF @@ERROR <>0 GOTO ERROUT UPDATE MessageBoardCategories SET PostCount = PostCount -1 WHERE CategoryID = @CategoryID IF @@ERROR <>0 GOTO ERROUT With: DECLARE "@ERROR" INT DEFAULT 0 ; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN SET "@ERROR" = 1 ; END ; INSERT groupmessageboardreplies ( parentid, authorid, body ) VALUES ( "@entryid", "@authorid", "@body" ) ; IF "@ERROR" = 0 THEN UPDATE groupmessageboardentries set replycount = replycount + 1, lastpostdate = NOW(), lastposter = "@authorid" WHERE entryid = "@entryid" ; END IF IF "@ERROR" = 0 THEN UPDATE groupmessageboards set lastpostdate = NOW(), postcount = postcount + 1, lastposterid = "@authorid", lastpostentryid = "@entryid" WHERE groupid = "@groupid" ; END IF; 10.5 Use LIMIT instead of TOP The MySQL, the LIMIT feature in a SELECT both replaces the SQL Server TOP function and adds new functionality not available in TOP. In its simplest form: Replace: SELECT TOP 100 * FROM TABLE With: SELECT * FROM TABLE LIMIT 100 ; Copyright © 2007, MySQL AB Seite 28 von 49 If you want to get 10 records starting at position 100, then use: SELECT * FROM TABLE LIMIT 100,10 ; Note that the values in the LIMIT clause must be constants, variables are not allowed. You cannot use: SELECT * FROM TABLE LIMIT @start,@rows ; To get around this issue you can use a PREPARE statement as follows. Assuming the query you want to run is: select c.classifiedid, c.subject, c.createddate, c.views, c.userid from schoolsclassifieds c where categoryid = "@categoryid" and schoolid = "@schoolid" order by classifiedid desc limit “@startrow","@maxrows" ; Use the following code to implement the SELECT: PREPARE STMT FROM 'select c.classifiedid, c.subject, c.createddate, c.views, c.userid from schoolsclassifieds c where categoryid = ? and schoolid = ? order by classifiedid desc limit ?,?' ; EXECUTE STMT USING "@categoryid","@schoolid","@startrow","@maxrows" ; 10.6 LIMIT and Optimization In some cases, MySQL handles a query differently when you are using LIMIT <row_count> and not using HAVING: • If you are selecting only a few rows with LIMIT, MySQL uses indexes in some cases when normally it would prefer to do a full table scan. • If you use LIMIT row_count with ORDER BY, MySQL ends the sorting as soon as it has found the first row_count rows of the sorted result, rather than sorting the entire result. If ordering is done by using an index, this is very fast. If a filesort must be done, all rows that match the query without the LIMIT clause must be selected, and most or all of them must be sorted, before it can be ascertained that the first row_count rows have been found. In either case, after the initial rows have been found, there is no need to sort any remainder of the result set, and MySQL does not do so. • When combining LIMIT row_count with DISTINCT, MySQL stops as soon as it finds row_count unique rows. Copyright © 2007, MySQL AB Seite 29 von 49 • In some cases, a GROUP BY can be resolved by reading the key in order (or doing a sort on the key) and then calculating summaries until the key value changes. In this case, LIMIT row_count does not calculate any unnecessary GROUP BY values. • As soon as MySQL has sent the required number of rows to the client, it aborts the query unless you are using SQL_CALC_FOUND_ROWS. • LIMIT 0 quickly returns an empty set. This can be useful for checking the validity of a query. When using one of the MySQL APIs, it can also be employed for obtaining the types of the result columns. (This trick does not work in the MySQL Monitor, which merely displays Empty set in such cases; you should instead use SHOW COLUMNS or DESCRIBE for this purpose.) • When the server uses temporary tables to resolve the query, it uses the LIMIT row_count clause to calculate how much space is required. 10.7 IF THEN … ELSE … END IF ; MySQL requires that an IF include a THEN and that a block with more than one statement must be terminated by an ‘END IF ;’. Note that the ‘;’ after the END IF is required. IF <expr> THEN Statement 1; ELSE Statement 2 ; END IF; 10.8 DATETIME with default values The MySQL migration tool cannot handle migrating DATETIME columns that have a default value of getdate(). For example: UPLOADED DATETIME NULL DEFAULT GETDATE(), Tables with DATETIME columns with the above default will not automatically be converted and must be manually modified as follows: UPLOADED TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMTP, Note that only the TIMESTAMP type can have a default value of CURRENT_TIMESTATMP so if you want to keep the default you must also change the type from DATETIME to TIMEDSTAMP. Another difference between MySQL and SQL Server is that MySQL only allows 1 column per table to have a default value of CURRENT_TIMESTATMP. For tables in SQL Server with two or more columns with default values set to GETDATE(), one or the other column must have its default value removed for the table to create successfully. In addition, MySQL implicitly assigns a default value of CURRENT_TIMESTAMP to the first TIMESTAMP column in a create table statement unless it is explicitly assigned a default value other than NULL or CURRENT_TIMESTATMP. This means that if you are converting a table that has two columns with a default values of getdate() and you choose the second column as the one to have the default value you will get a error creating the table if you do not explicitly assign a default value, such as 0 or ‘0000-00-00 00:00:00’ to the first column. 10.9 Index Name Length Differences MySQL does not support index names longer than 64 bytes. Indexes with names longer than 64 bytes must be renamed. Copyright © 2007, MySQL AB Seite 30 von 49 10.10 Support for SQL Server Declared Tables SQL Server supports a ‘table’ data type in an stored procedure. For example: DECLARE "@Results" TABLE (Pos int IDENTITY, ClassifiedID int) MySQL does not support this. Instead, use a temporary in memory table: CREATE TEMPORARY TABLE temp1 (ClassifiedID int) ENGINE = MEMORY; < other code > DROP TEMPORARY TABLE temp1 ; 10.11 Obtaining Row Counts In MySQL, the function ROW_COUNT() returns the number of rows effected by the last insert, update, or delete. Use this instead of the SQL Server @@ROWCOUNT variable. 10.12 Default Values for Parameters In SQL Server a parameter can have the form: @Param int default 0 MySQL does not support this. The application must be changed to pass in the appropriate default values. 10.13 Use of SELECT INTO In SQL Server, if you want to set a variable based on the results of a SELECT you use: SELECT INTO A=col1 … In MySQL, the INTO will cause an error, so you will need to use: SELECT A=col1 … 10.14 Uses of IFNULL Use the IFNULL() function to check if a value is NULL and then return either the value or another value based on the results of the test. The IFNULL() function returns A if A is not NULL, and returns B otherwise. 10.15 Replace DATEADD with ADDDATE() The MySQL function ADDDATE() replaces DATEADD(). For example: Replace: DATEADD(dd, -14, GETDATE()) With: ADDDATE(NOW(),INTERVAL -14 DAY) ; Copyright © 2007, MySQL AB Seite 31 von 49 10.16 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED This exact syntax works in MySQL and can be placed at the top of each Stored Procedure if desired. The better solution is to set the value of transaction-isolation in the my.cnf file: transaction-isolation=READ-UNCOMMITTED 10.17 Replace SET ROWCOUNT = @rows with SQL_SELECT_LIMIT Use SQL_SELECT_LIMIT instead of ROWCOUNT in MySQL to limit the rows returned in a select. This method allows the number of rows returned to be set by a variable without using a prepare statement. Replace: SET ROOWCOUNT = @rowcount With SET SQL_SELECT_LIMIT=@rowcount; 10.18 Perl Script to Help with Conversion of T-SQL to MySQL The Perl script below assists in the conversion of SQL Server T-SQL to MySQL. Note that it performs rudimentary changes only, so many complex SQL Server code objects will still have to be massaged by hand. Many thanks go to Brian Miezejewski of MySQL Professional Services for providing the utility. The method of using the Perl conversion utility is as follows: 1. Extract all desired SQL Server stored procedures into files and place them into a single directory. 2. Run the below perl script ‘MSProcstoMySql.pl’ as such: perl MSProcstoMySql.pl *.PRC 3. The procedure will create a subdirectory called ‘converted’ and place the converted stored procedures in that directory. The following example shows a stored procedure before and after the above perl script is run: SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO CREATE PROCEDURE DeleteMessageBoardReply @ReplyID int, @EntryID int, @CategoryID int AS SET NOCOUNT ON SET LOCK_TIMEOUT 4000 BEGIN TRAN DELETE FROM MessageBoardReplies WHERE ReplyID = @ReplyID IF @@ERROR <>0 GOTO ERROUT UPDATE MessageBoardEntries SET ReplyCount = ReplyCount - 1 WHERE EntryID = @EntryID IF @@ERROR <>0 GOTO ERROUT Copyright © 2007, MySQL AB Seite 32 von 49 UPDATE MessageBoardCategories SET PostCount = PostCount -1 WHERE CategoryID = @CategoryID IF @@ERROR <>0 GOTO ERROUT COMMIT TRAN RETURN ERROUT: ROLLBACK TRAN GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO DELIMITER $$; SET SQL_MODE = ANSI_QUOTES$$ DROP PROCEDURE IF EXISTS DeleteMessageBoardReply $$ CREATE PROCEDURE DeleteMessageBoardReply ( "@replyid" int, "@entryid" int, "@categoryid" int ) BEGIN /*BEGIN tran*/ delete from messageboardreplies WHERE replyid ="@replyid" IF @@error <>0 goto errout UPDATE messageboardentries set replycount = replycount - 1 WHERE entryid ="@entryid" IF @@error <>0 goto errout UPDATE messageboardcategories set postcount = postcount -1 WHERE categoryid ="@categoryid" IF @@error <>0 goto errout /*commit tran*/ return errout: rollback tran END; $$ DELIMITER ;$$ The Perl conversion routine performs the following functions: 1. Renames the file from dbo.spName.PRC to spName.sql 2. Wraps the code in: • DELIMITER $$; • SET SQL_MODE = ANSI_QUOTES$$ • <Stored procedure code> • $$ • DELIMITER ;$$ 3. Removes all ‘GO’ statements from the code Copyright © 2007, MySQL AB Seite 33 von 49 4. Remove all SET statements for QUOTED_IDENTIFIER, ANSI_NULL, NOCOUNT, and LOCK_TIMEOUT. 5. Comments out both BEGIN TRAN and COMMIT TRAN 6. Replaces all @@IDENTITY references with a call to LAST_INSERT_ID() 7. Wraps every reference to a variable of the format @<name> in double quotes, i.e. @vari becomes “@vari” 8. Makes all table names lower case 9. Changes NVARCHAR types to VARCHAR 10. Places the parameter list in parentheses 11. Removes the AS after the parameter list 12. Wraps all code after the parameter list in a BEGIN END block 13. Replaces all call to GETDATE() with calls to NOW() While the script makes many changes to the SQL Server stored procedures, it does not fully convert them. Each stored procedure will still need to be reviewed and modified before it can be used. The following list includes some of the more common issues that will still need to be fixed: • • • 10.18.1 Place a ‘;’ after every statement Add an error handler Remove any IF @@ERROR<>0 GOTO LABEL and replace them with IF … END IF blocks using the value set in the error handler. Perl Conversion Script #!/usr/bin/perl if (! -d "converted" ) { mkdir "converted" ; } foreach my $inFile (@ARGV) { open INFILE, "<$inFile" ; my $outFile = $inFile ; $outFile =~ s/\.[^\.]*$/.sql/ ; $outFile =~ s/^dbo\.// ; open OUTFILE, ">converted/$outFile" ; print OUTFILE "DELIMITER \$\$;\n" ; print OUTFILE "SET SQL_MODE = ANSI_QUOTES\$\$" ; while( <INFILE> ) { s/\@\@identity/LAST_INSERT_ID()/i ; s/\s(\@[^\s\,\)\@]+)/"$1"/g ; /SET QUOTED_IDENTIFIER ON/ && next ; /SET NOCOUNT ON/ && next ; /SET\s*LOCK_TIMEOUT.*/ && next ; /^\s*GO\s*$/ && next ; /SET QUOTED_IDENTIFIER OFF/i && next ; /SET QUOTED_IDENTIFIER ON/ && next ; /SET ANSI_NULLS ON/ && next ; /SET ANSI_NULLS OFF/ && next ; s/nvarchar/varcharg/ ; if (/(CREATE\s+PROCEDURE)\s+([^\n\r]*)/) { print OUTFILE "DROP PROCEDURE IF EXISTS $2 \$\$\n\n" ; print OUTFILE "$1 $2 (\n" next ; Copyright © 2007, MySQL AB ; Seite 34 von 49 }; if (/^\s*AS\s*$/) { print OUTFILE ")\n" ; print OUTFILE "BEGIN\n" ; next ; }; s/(BEGIN\s+TRAN[^\n\r]*)/\/*$1*\// ; s/(COMMIT\s+TRAN[^\n\r]*)/\/*$1*\// ; tr/[A-Z]/[a-z]/; s/getdate\(\)/NOW()/i ; s/select\s/SELECT / ; s/update\s/UPDATE / ; s/insert\s/INSERT / ; s/declare\s/DECLARE / ; s/where\s/WHERE / ; s/values/VALUES/ ; s/begin/BEGIN/ ; s/if/IF/ ; /([^\r\n]*)/ && print OUTFILE "$1\n" ; } print OUTFILE "END;\n" ; print OUTFILE "\$\$\n" ; print OUTFILE "DELIMITER ;\$\$\n" ; close OUTFILE ; close INFILE ; } Copyright © 2007, MySQL AB Seite 35 von 49 11 Anhang E – Sample Migration This section provides a simple example of moving an SQL Server 2005 database schema over to MySQL using the MySQL Migration Toolkit. 11.1 Sample SQL Server Schema The SQL Server 2005 schema is a small database used for tracking financial investments in a small brokerage company. The SQL Server schema DDL is as follows: --- CREATE Tables -CREATE TABLE BROKER ( BROKER_ID numeric(18,0) NOT NULL, OFFICE_LOCATION_ID numeric(18,0) NULL, BROKER_LAST_NAME varchar(40) NOT NULL, BROKER_FIRST_NAME varchar(20) NOT NULL, BROKER_MIDDLE_INITIAL char(1) NULL, MANAGER_ID numeric(18,0) NULL, YEARS_WITH_FIRM numeric(3,1) NOT NULL, CONSTRAINT BROKER_PK PRIMARY KEY CLUSTERED (BROKER_ID) ) go IF OBJECT_ID('BROKER') IS NOT NULL PRINT '<<< CREATED TABLE BROKER >>>' ELSE PRINT '<<< FAILED CREATING TABLE BROKER >>>' go CREATE TABLE CLIENT_TRANSACTION ( CLIENT_TRANSACTION_ID numeric(18,0) NOT NULL, CLIENT_ID numeric(18,0) NOT NULL, INVESTMENT_ID numeric(18,0) NOT NULL, [ACTION] varchar(10) NOT NULL, PRICE numeric(12,2) NOT NULL, NUMBER_OF_UNITS numeric(18,0) NOT NULL, TRANSACTION_STATUS varchar(10) NOT NULL, TRANSACTION_SUB_TIMESTAMP datetime NOT NULL, TRANSACTION_COMP_TIMESTAMP datetime NOT NULL, DESCRIPTION varchar(200) NULL, BROKER_ID numeric(18,0) NULL, BROKER_COMMISSION numeric(10,2) NULL, CONSTRAINT CLIENT_TRANSACTION_PK PRIMARY KEY CLUSTERED (CLIENT_TRANSACTION_ID) ) go IF OBJECT_ID('CLIENT_TRANSACTION') IS NOT NULL PRINT '<<< CREATED TABLE CLIENT_TRANSACTION >>>' ELSE PRINT '<<< FAILED CREATING TABLE CLIENT_TRANSACTION >>>' go CREATE TABLE CLIENT ( CLIENT_ID numeric(18,0) NOT NULL, CLIENT_FIRST_NAME varchar(20) NOT NULL, CLIENT_LAST_NAME varchar(40) NOT NULL, CLIENT_GENDER char(1) NOT NULL, CLIENT_YEAR_OF_BIRTH numeric(4,0) NOT NULL, CLIENT_MARITAL_STATUS varchar(20) NULL, CLIENT_STREET_ADDRESS varchar(40) NOT NULL, CLIENT_POSTAL_CODE varchar(10) NOT NULL, CLIENT_CITY varchar(30) NOT NULL, Copyright © 2007, MySQL AB Seite 36 von 49 CLIENT_STATE_PROVINCE varchar(40) CLIENT_PHONE_NUMBER varchar(25) CLIENT_HOUSEHOLD_INCOME numeric(30,0) CLIENT_COUNTRY varchar(40) BROKER_ID numeric(18,0) CONSTRAINT CLIENT_PK PRIMARY KEY CLUSTERED (CLIENT_ID) NOT NULL, NOT NULL, NULL, NULL, NOT NULL, ) go IF OBJECT_ID('CLIENT') IS NOT NULL PRINT '<<< CREATED TABLE CLIENT >>>' ELSE PRINT '<<< FAILED CREATING TABLE CLIENT >>>' go --- Foreign Keys -ALTER TABLE CLIENT_TRANSACTION ADD CONSTRAINT CLIENT_TRANSACTION_CLIENT FOREIGN KEY (CLIENT_ID) REFERENCES CLIENT (CLIENT_ID) ON DELETE CASCADE go --- CREATE Indexes -CREATE NONCLUSTERED INDEX CLIENT_BROKER ON CLIENT(BROKER_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('CLIENT') AND name='CLIENT_BROKER') PRINT '<<< CREATED INDEX CLIENT.CLIENT_BROKER >>>' ELSE PRINT '<<< FAILED CREATING INDEX CLIENT.CLIENT_BROKER >>>' go --- Foreign Keys -ALTER TABLE CLIENT_TRANSACTION ADD CONSTRAINT CLIENT_TRANSACTION_BROKER FOREIGN KEY (BROKER_ID) REFERENCES BROKER (BROKER_ID) ON DELETE CASCADE go ALTER TABLE CLIENT ADD CONSTRAINT FK__CLIENT__BROKER_I__0F975522 FOREIGN KEY (BROKER_ID) REFERENCES BROKER (BROKER_ID) go --- CREATE Indexes -CREATE NONCLUSTERED INDEX CLIENT_TRANSACTION_BROKER ON CLIENT_TRANSACTION(BROKER_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('CLIENT_TRANSACTION') AND name='CLIENT_TRANSACTION_BROKER') PRINT '<<< CREATED INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_BROKER >>>' ELSE PRINT '<<< FAILED CREATING INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_BROKER >>>' go CREATE NONCLUSTERED INDEX CLIENT_TRANSACTION_CLIENT ON CLIENT_TRANSACTION(CLIENT_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('CLIENT_TRANSACTION') AND Copyright © 2007, MySQL AB Seite 37 von 49 name='CLIENT_TRANSACTION_CLIENT') PRINT '<<< CREATED INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_CLIENT >>>' ELSE PRINT '<<< FAILED CREATING INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_CLIENT >>>' go CREATE NONCLUSTERED INDEX CLIENT_TRANSACTION_INVESTMENT ON CLIENT_TRANSACTION(INVESTMENT_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('CLIENT_TRANSACTION') AND name='CLIENT_TRANSACTION_INVESTMENT') PRINT '<<< CREATED INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_INVESTMENT >>>' ELSE PRINT '<<< FAILED CREATING INDEX CLIENT_TRANSACTION.CLIENT_TRANSACTION_INVESTMENT >>>' go --- CREATE Tables -CREATE TABLE INVESTMENT ( INVESTMENT_ID numeric(18,0) NOT NULL, INVESTMENT_TYPE_ID numeric(18,0) NULL, INVESTMENT_VENDOR varchar(30) NULL, INVESTMENT_NAME varchar(200) NULL, INVESTMENT_UNIT varchar(20) NULL, INVESTMENT_DURATION varchar(10) NULL, CONSTRAINT INVESTMENT_PK PRIMARY KEY CLUSTERED (INVESTMENT_ID) ) go IF OBJECT_ID('INVESTMENT') IS NOT NULL PRINT '<<< CREATED TABLE INVESTMENT >>>' ELSE PRINT '<<< FAILED CREATING TABLE INVESTMENT >>>' go --- CREATE Indexes -CREATE NONCLUSTERED INDEX INVESTMENT_INVESTMENT_TYPE ON INVESTMENT(INVESTMENT_TYPE_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('INVESTMENT') AND name='INVESTMENT_INVESTMENT_TYPE') PRINT '<<< CREATED INDEX INVESTMENT.INVESTMENT_INVESTMENT_TYPE >>>' ELSE PRINT '<<< FAILED CREATING INDEX INVESTMENT.INVESTMENT_INVESTMENT_TYPE >>>' go --- CREATE Tables -CREATE TABLE INVESTMENT_TYPE ( INVESTMENT_TYPE_ID numeric(18,0) NOT NULL, INVESTMENT_TYPE_NAME varchar(30) NOT NULL, CONSTRAINT INVESTMENT_TYPE_PK PRIMARY KEY CLUSTERED (INVESTMENT_TYPE_ID) ) go IF OBJECT_ID('INVESTMENT_TYPE') IS NOT NULL PRINT '<<< CREATED TABLE INVESTMENT_TYPE >>>' ELSE PRINT '<<< FAILED CREATING TABLE INVESTMENT_TYPE >>>' go --- Foreign Keys Copyright © 2007, MySQL AB Seite 38 von 49 -ALTER TABLE INVESTMENT ADD CONSTRAINT FK__INVESTMEN__INVES__108B795B FOREIGN KEY (INVESTMENT_TYPE_ID) REFERENCES INVESTMENT_TYPE (INVESTMENT_TYPE_ID) go ALTER TABLE CLIENT_TRANSACTION ADD CONSTRAINT CLIENT_TRANSACTION_INVESTMENT FOREIGN KEY (INVESTMENT_ID) REFERENCES INVESTMENT (INVESTMENT_ID) ON DELETE CASCADE go --- CREATE Tables -CREATE TABLE OFFICE_LOCATION ( OFFICE_LOCATION_ID numeric(18,0) NOT NULL, OFFICE_NAME varchar(20) NOT NULL, OFFICE_ADDRESS varchar(50) NOT NULL, OFFICE_CITY varchar(30) NOT NULL, OFFICE_STATE_PROVINCE varchar(40) NOT NULL, OFFICE_POSTAL_CODE varchar(10) NOT NULL, OFFICE_COUNTRY varchar(40) NULL, CONSTRAINT OFFICE_LOCATION_PK PRIMARY KEY CLUSTERED (OFFICE_LOCATION_ID) ) go IF OBJECT_ID('OFFICE_LOCATION') IS NOT NULL PRINT '<<< CREATED TABLE OFFICE_LOCATION >>>' ELSE PRINT '<<< FAILED CREATING TABLE OFFICE_LOCATION >>>' go --- Foreign Keys -ALTER TABLE BROKER ADD CONSTRAINT BROKER_OFFICE_LOCATION FOREIGN KEY (OFFICE_LOCATION_ID) REFERENCES OFFICE_LOCATION (OFFICE_LOCATION_ID) ON DELETE CASCADE go ---- CREATE Indexes -CREATE NONCLUSTERED INDEX BROKER_LOCATION ON BROKER(OFFICE_LOCATION_ID) go IF EXISTS (SELECT * FROM sysindexes WHERE id=OBJECT_ID('BROKER') AND name='BROKER_LOCATION') PRINT '<<< CREATED INDEX BROKER.BROKER_LOCATION >>>' ELSE PRINT '<<< FAILED CREATING INDEX BROKER.BROKER_LOCATION >>>' go Copyright © 2007, MySQL AB Seite 39 von 49 11.2 Moving the SQL Server Database to MySQL with the Migration Toolkit The following steps are used to move the SQL Server 2005 database schema (with data) over to a MySQL 5.x database. Step 1 – Connect to SQL Server Source Server and database: Supply a SQL Server connection string along with an ID, password, and database, and then connect to SQL Server. Step 2 – Connect to MySQL Target Server: Copyright © 2007, MySQL AB Seite 40 von 49 Enter MySQL connection information for the target server. The Migration Toolkit connects to both the source and target servers. Step 3 – Select Target Users/Schema(s) to Migrate: For this example, SQL Server ‘gim’ database is the source database, with the ‘dbo’ user/schema being migrated. Note that more than one schema can be selected. The Migration Toolkit will reverse engineer the source database schema along with all datatypes, etc. Step 4 (Optional) – Choose Objects to Migrate: You can optionally select what objects to migrate to MySQL. The default is all data objects in the schema. Copyright © 2007, MySQL AB Seite 41 von 49 Step 5 – Tweak MySQL Defaults: This step allows you to customize your MySQL settings like target engine, etc. Intelligent defaults are provided (such as InnoDB storage engine for SQL Server databases, using autoincrement columns, etc.) The Migration Toolkit will then proceed and inform you if any mapping problems are found and generate the SQL necessary to create the MySQL target database. Step 6 – Create MySQL Target Objects: This step allows you to create the new MySQL database and object schema (with no data) online or save the SQL statements to a file. If you choose to proceed with the default online option, the Migration Toolkit will create the MySQL database and schema objects: Copyright © 2007, MySQL AB Seite 42 von 49 Step 7 – Migrate Existing SQL Server Data to MySQL: This step allows you to migrate the existing SQL Server data to the new MySQL database schema. You can optionally choose to generate INSERT statements into a file for later execution. If you choose to proceed, the migration toolkit will move the data in bulk from SQL Server to MySQL: Copyright © 2007, MySQL AB Seite 43 von 49 Step 8 – Review Migration The final step is to review the migration process and ensure the desired results were obtained. Copyright © 2007, MySQL AB Seite 44 von 49 11.3 Sample MySQL Schema Generated from SQL Server The following MySQL database was generated from the sample SQL Server10g schema: DROP TABLE IF EXISTS gim_dbo.BROKER; CREATE TABLE gim_dbo.BROKER ( BROKER_ID decimal(18,0) NOT NULL, OFFICE_LOCATION_ID decimal(18,0) default NULL, BROKER_LAST_NAME varchar(40) NOT NULL, BROKER_FIRST_NAME varchar(20) NOT NULL, BROKER_MIDDLE_INITIAL char(1) default NULL, MANAGER_ID decimal(18,0) default NULL, YEARS_WITH_FIRM decimal(3,1) NOT NULL, PRIMARY KEY (BROKER_ID), KEY BROKER_LOCATION (OFFICE_LOCATION_ID), CONSTRAINT BROKER_OFFICE_LOCATION FOREIGN KEY (OFFICE_LOCATION_ID) REFERENCES OFFICE_LOCATION (OFFICE_LOCATION_ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS gim_dbo.CLIENT; CREATE TABLE gim_dbo.CLIENT ( CLIENT_ID decimal(18,0) NOT NULL, CLIENT_FIRST_NAME varchar(20) NOT NULL, CLIENT_LAST_NAME varchar(40) NOT NULL, CLIENT_GENDER char(1) NOT NULL, CLIENT_YEAR_OF_BIRTH decimal(4,0) NOT NULL, CLIENT_MARITAL_STATUS varchar(20) default NULL, CLIENT_STREET_ADDRESS varchar(40) NOT NULL, CLIENT_POSTAL_CODE varchar(10) NOT NULL, CLIENT_CITY varchar(30) NOT NULL, CLIENT_STATE_PROVINCE varchar(40) NOT NULL, CLIENT_PHONE_NUMBER varchar(25) NOT NULL, CLIENT_HOUSEHOLD_INCOME decimal(30,0) default NULL, CLIENT_COUNTRY varchar(40) default NULL, BROKER_ID decimal(18,0) NOT NULL, PRIMARY KEY (CLIENT_ID), KEY CLIENT_BROKER (BROKER_ID), CONSTRAINT FK__CLIENT__BROKER_I__0F975522 FOREIGN KEY (BROKER_ID) REFERENCES BROKER (BROKER_ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS gim_dbo.CLIENT_TRANSACTION; CREATE TABLE gim_dbo.CLIENT_TRANSACTION ( CLIENT_TRANSACTION_ID decimal(18,0) NOT NULL, CLIENT_ID decimal(18,0) NOT NULL, INVESTMENT_ID decimal(18,0) NOT NULL, ACTION varchar(10) NOT NULL, PRICE decimal(12,2) NOT NULL, NUMBER_OF_UNITS decimal(18,0) NOT NULL, TRANSACTION_STATUS varchar(10) NOT NULL, TRANSACTION_SUB_TIMESTAMP datetime NOT NULL, TRANSACTION_COMP_TIMESTAMP datetime NOT NULL, DESCRIPTION varchar(200) default NULL, BROKER_ID decimal(18,0) default NULL, BROKER_COMMISSION decimal(10,2) default NULL, PRIMARY KEY (CLIENT_TRANSACTION_ID), KEY CLIENT_TRANSACTION_BROKER (BROKER_ID), KEY CLIENT_TRANSACTION_CLIENT (CLIENT_ID), KEY CLIENT_TRANSACTION_INVESTMENT (INVESTMENT_ID), CONSTRAINT CLIENT_TRANSACTION_BROKER FOREIGN KEY (BROKER_ID) REFERENCES BROKER (BROKER_ID) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT CLIENT_TRANSACTION_INVESTMENT FOREIGN KEY (INVESTMENT_ID) REFERENCES INVESTMENT (INVESTMENT_ID) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT CLIENT_TRANSACTION_CLIENT FOREIGN KEY (CLIENT_ID) REFERENCES CLIENT (CLIENT_ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS gim_dbo.INVESTMENT; CREATE TABLE gim_dbo.INVESTMENT ( INVESTMENT_ID decimal(18,0) NOT NULL, INVESTMENT_TYPE_ID decimal(18,0) default NULL, INVESTMENT_VENDOR varchar(30) default NULL, INVESTMENT_NAME varchar(200) default NULL, INVESTMENT_UNIT varchar(20) default NULL, INVESTMENT_DURATION varchar(10) default NULL, PRIMARY KEY (INVESTMENT_ID), Copyright © 2007, MySQL AB Seite 45 von 49 KEY INVESTMENT_INVESTMENT_TYPE (INVESTMENT_TYPE_ID), CONSTRAINT FK__INVESTMEN__INVES__108B795B FOREIGN KEY (INVESTMENT_TYPE_ID) REFERENCES INVESTMENT_TYPE (INVESTMENT_TYPE_ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS gim_dbo.INVESTMENT_TYPE; CREATE TABLE gim_dbo.INVESTMENT_TYPE ( INVESTMENT_TYPE_ID decimal(18,0) NOT NULL, INVESTMENT_TYPE_NAME varchar(30) NOT NULL, PRIMARY KEY (INVESTMENT_TYPE_ID) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS gim_dbo.OFFICE_LOCATION; CREATE TABLE gim_dbo.OFFICE_LOCATION ( OFFICE_LOCATION_ID decimal(18,0) NOT NULL, OFFICE_NAME varchar(20) NOT NULL, OFFICE_ADDRESS varchar(50) NOT NULL, OFFICE_CITY varchar(30) NOT NULL, OFFICE_STATE_PROVINCE varchar(40) NOT NULL, OFFICE_POSTAL_CODE varchar(10) NOT NULL, OFFICE_COUNTRY varchar(40) default NULL, PRIMARY KEY (OFFICE_LOCATION_ID) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 11.4 Sample Code Migration As was mentioned, no automatic conversion exists in terms of migrating SQL Server T-SQL code objects to MySQL, although a prior Appendix in this paper does supply some guidance and a simple Perl conversion utility. MySQL is in discussions with several partners on providing this functionality, but until a mechanized solution is reached, there are several options open to performing code migration: 1. Contact MySQL Professional Services group to help with the code migration. Staff at MySQL have assisted in code conversions from a number of platforms to MySQL. 2. Perform code migrations internally. The difficulty level of migrating SQL Server T-SQL code to MySQL depends on the actual code itself. For example, the following SQL Server T-SQL procedure uses the sample schema presented above to create various business intelligence reports to the staff of the company using the database: SET QUOTED_IDENTIFIER OFF go SET ANSI_NULLS OFF go CREATE PROCEDURE CORPORATE_ANALYSIS @START_DATE DATETIME, @END_DATE DATETIME AS BEGIN --- display brokers ordered by highest commissions for time period -SELECT A.BROKER_ID, A.BROKER_FIRST_NAME, A.BROKER_LAST_NAME, SUM(BROKER_COMMISSION) TOTAL_COMMISSIONS FROM BROKER A, CLIENT_TRANSACTION B WHERE B.TRANSACTION_COMP_TIMESTAMP BETWEEN @START_DATE AND @END_DATE AND A.BROKER_ID = B.BROKER_ID GROUP BY A.BROKER_ID, A.BROKER_FIRST_NAME, A.BROKER_LAST_NAME ORDER BY 4 DESC --- display offices ordered by highest commissions for time period Copyright © 2007, MySQL AB Seite 46 von 49 -SELECT C.OFFICE_NAME, SUM(BROKER_COMMISSION) TOTAL_COMMISSIONS FROM BROKER A, CLIENT_TRANSACTION B, OFFICE_LOCATION C WHERE B.TRANSACTION_COMP_TIMESTAMP BETWEEN @START_DATE AND @END_DATE AND A.BROKER_ID = B.BROKER_ID AND A.OFFICE_LOCATION_ID = C.OFFICE_LOCATION_ID GROUP BY C.OFFICE_NAME ORDER BY 2 DESC --- display top 20 invests ordered by highest invested dollars for time period -SELECT TOP 20 B.INVESTMENT_VENDOR, B.INVESTMENT_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS FROM CLIENT_TRANSACTION A, INVESTMENT B WHERE A.TRANSACTION_COMP_TIMESTAMP BETWEEN @START_DATE AND @END_DATE AND B.INVESTMENT_ID = A.INVESTMENT_ID AND A.ACTION = 'BUY' GROUP BY B.INVESTMENT_VENDOR, B.INVESTMENT_NAME ORDER BY 3 DESC --- display top invest types ordered by highest invested $$ for time period -SELECT C.INVESTMENT_TYPE_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS FROM CLIENT_TRANSACTION A, INVESTMENT B, INVESTMENT_TYPE C WHERE A.TRANSACTION_COMP_TIMESTAMP BETWEEN @START_DATE AND @END_DATE AND B.INVESTMENT_ID = A.INVESTMENT_ID AND C.INVESTMENT_TYPE_ID = B.INVESTMENT_TYPE_ID AND A.ACTION = 'BUY' GROUP BY C.INVESTMENT_TYPE_NAME ORDER BY 2 DESC --- display top 20 clients ordered by highest invested dollars for time period -SELECT TOP 20 B.CLIENT_FIRST_NAME, B.CLIENT_LAST_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS FROM CLIENT_TRANSACTION A, CLIENT B WHERE A.TRANSACTION_COMP_TIMESTAMP BETWEEN @START_DATE AND @END_DATE AND B.CLIENT_ID = A.CLIENT_ID AND A.ACTION = 'BUY' GROUP BY B.CLIENT_FIRST_NAME, B.CLIENT_LAST_NAME ORDER BY 3 DESC END go IF OBJECT_ID('CORPORATE_ANALYSIS') IS NOT NULL PRINT '<<< CREATED PROCEDURE CORPORATE_ANALYSIS >>>' ELSE PRINT '<<< FAILED CREATING PROCEDURE CORPORATE_ANALYSIS >>>' go SET ANSI_NULLS OFF Copyright © 2007, MySQL AB Seite 47 von 49 go SET QUOTED_IDENTIFIER OFF go The SQL Server T-SQL procedure can be translated to MySQL as follows: CREATE PROCEDURE CORPORATE_ANALYSIS (IN START_DATE DATETIME, IN END_DATE DATETIME) BEGIN /* display brokers ordered by highest commissions for time period */ SELECT A.BROKER_ID, A.BROKER_FIRST_NAME, A.BROKER_LAST_NAME, SUM(BROKER_COMMISSION) TOTAL_COMMISSIONS FROM BROKER A, CLIENT_TRANSACTION B WHERE B.TRANSACTION_COMP_TIMESTAMP BETWEEN START_DATE AND END_DATE AND A.BROKER_ID = B.BROKER_ID GROUP BY A.BROKER_ID, A.BROKER_FIRST_NAME, A.BROKER_LAST_NAME ORDER BY 4; /* -- display offices ordered by highest commissions for time period */ SELECT C.OFFICE_NAME, SUM(BROKER_COMMISSION) TOTAL_COMMISSIONS FROM BROKER A, CLIENT_TRANSACTION B, OFFICE_LOCATION C WHERE B.TRANSACTION_COMP_TIMESTAMP BETWEEN START_DATE AND END_DATE AND A.BROKER_ID = B.BROKER_ID AND A.OFFICE_LOCATION_ID = C.OFFICE_LOCATION_ID GROUP BY C.OFFICE_NAME ORDER BY 2 DESC; /* -- display top 20 invests ordered by highest invested dollars for time period */ SELECT FROM WHERE GROUP ORDER LIMIT B.INVESTMENT_VENDOR, B.INVESTMENT_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS CLIENT_TRANSACTION A, INVESTMENT B A.TRANSACTION_COMP_TIMESTAMP BETWEEN START_DATE AND END_DATE AND B.INVESTMENT_ID = A.INVESTMENT_ID AND A.ACTION = 'BUY' BY B.INVESTMENT_VENDOR, B.INVESTMENT_NAME BY 3 DESC 20; /* -- display top types ordered by highest invested dollars for time period */ SELECT FROM WHERE Copyright © 2007, MySQL AB C.INVESTMENT_TYPE_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS CLIENT_TRANSACTION A, INVESTMENT B, INVESTMENT_TYPE C A.TRANSACTION_COMP_TIMESTAMP BETWEEN START_DATE AND END_DATE AND Seite 48 von 49 B.INVESTMENT_ID = A.INVESTMENT_ID AND C.INVESTMENT_TYPE_ID = B.INVESTMENT_TYPE_ID AND A.ACTION = 'BUY' GROUP BY C.INVESTMENT_TYPE_NAME ORDER BY 2 DESC; /* -- display top 20 clients ordered by highest invested dollars for time period */ SELECT FROM WHERE GROUP ORDER LIMIT B.CLIENT_FIRST_NAME, B.CLIENT_LAST_NAME, SUM(PRICE) * SUM(NUMBER_OF_UNITS) TOTAL_INVESTED_DOLLARS CLIENT_TRANSACTION A, CLIENT B A.TRANSACTION_COMP_TIMESTAMP BETWEEN START_DATE AND END_DATE AND B.CLIENT_ID = A.CLIENT_ID AND A.ACTION = 'BUY' BY B.CLIENT_FIRST_NAME, B.CLIENT_LAST_NAME BY 3 DESC 20; END; Copyright © 2007, MySQL AB Seite 49 von 49