Jeder, der eine kleine datenbankgesteuerte Webanwendung mit MySQL entwickelt hat, weiß, dass das Erstellen, Abrufen, Aktualisieren und Löschen von Tabellen in einer relationalen Datenbank relativ einfache Prozesse sind. Theoretisch reicht es aus, die verschiedenen Vorgänge auszuführen, die für MySQL-Tabellen erforderlich sind, insbesondere wenn Sie das schnelle MyISAM verwenden, solange Sie die Verwendung der gängigsten SQL-Anweisungen beherrschen und mit der von Ihnen gewählten serverseitigen Skriptsprache vertraut sind Datenbank-Engine wann. Aber selbst in den einfachsten Fällen sind die Dinge komplizierter als wir denken. Nachfolgend verwenden wir zur Veranschaulichung ein typisches Beispiel. Angenommen, Sie betreiben eine Blog-Site, die Sie fast täglich aktualisieren, und auf der Website können Besucher Ihre Beiträge kommentieren.
In diesem Fall sollte unser Datenbankschema mindestens zwei MyISAM-Tabellen enthalten, eine zum Speichern Ihrer Blogbeiträge und eine andere zum Verarbeiten von Besucherkommentaren. Offensichtlich besteht zwischen diesen beiden Tabellen eine Eins-zu-Viele-Beziehung, daher müssen wir in der zweiten Tabelle einen Fremdschlüssel definieren, damit die Integrität der Datenbank aufrechterhalten werden kann, wenn Datenzeilen aktualisiert oder gelöscht werden.
Bei einer Anwendung wie der oben genannten stellt die Aufrechterhaltung der Integrität der beiden Tabellen nicht nur eine große Herausforderung dar, sondern die größte Schwierigkeit besteht auch darin, dass wir ihre Integrität auf Anwendungsebene aufrechterhalten müssen. Dies ist der Ansatz, der während der Entwicklung für die meisten Webprojekte gewählt wird, die keine Verwendung von Transaktionen erfordern, da MyISAM-Tabellen eine hervorragende Leistung bieten.
Dies ist natürlich auch mit Kosten verbunden. Wie ich bereits sagte, muss die Anwendung die Integrität und Konsistenz der Datenbank aufrechterhalten, was die Implementierung einer komplexeren Programmierlogik erfordert, um die Beziehungen zwischen verschiedenen Tabellen zu verwalten. Obwohl der Datenbankzugriff durch den Einsatz von Abstraktionsschichten und ORM-Modulen vereinfacht werden kann, wird mit zunehmender Anzahl der von einer Anwendung benötigten Datentabellen die für deren Verarbeitung erforderliche Logik zweifellos komplexer.
Gibt es also für MySQL eine Fremdschlüsselverarbeitungsmethode auf Datenbankebene, die dabei hilft, die Datenbankintegrität aufrechtzuerhalten? Glücklicherweise kann MySQL auch InnoDB-Tabellen unterstützen, sodass wir Fremdschlüsseleinschränkungen auf sehr einfache Weise handhaben können. Mit dieser Funktion können wir bestimmte Aktionen auslösen, z. B. das Aktualisieren und Löschen bestimmter Datenzeilen in der Tabelle, um vordefinierte Beziehungen aufrechtzuerhalten.
Alles hat Vor- und Nachteile, und der Hauptnachteil der Verwendung von InnoDB-Tabellen besteht darin, dass sie langsamer als MyISAM sind, insbesondere bei großen Anwendungen, bei denen viele Tabellen abgefragt werden müssen. Glücklicherweise unterstützt die MyISAM-Tabelle in der neueren Version von MySQL auch Fremdschlüsseleinschränkungen.
In diesem Artikel wird erläutert, wie Sie Fremdschlüsseleinschränkungen auf InnoDB-Tabellen anwenden. Darüber hinaus verwenden wir eine einfache PHP-basierte abstrakte MySQL-Klasse, um den entsprechenden Beispielcode zu erstellen. Natürlich können Sie auch Ihre bevorzugte andere serverseitige Sprache verwenden. Jetzt beginnen wir mit der Einführung, wie man Fremdschlüsseleinschränkungen auf MySQL anwendet.
Wann sollten Fremdschlüsseleinschränkungen verwendet werden?
Um ehrlich zu sein, müssen Sie bei der Verwendung von InnoDB-Tabellen in MySQL nicht unbedingt Fremdschlüsseleinschränkungen verwenden. Für den Zweck von Fremdschlüsseleinschränkungen werden wir jedoch den Code des zuvor erwähnten Beispiels verwenden, um dies im Detail zu erläutern. Es enthält zwei MyISAM-Tabellen, die zum Speichern von Blogbeiträgen und Kommentaren verwendet werden.
Bei der Definition des Datenbankschemas müssen wir eine Eins-zu-viele-Beziehung zwischen den beiden Tabellen herstellen, indem wir einen Fremdschlüssel in der Tabelle erstellen, in der Kommentare gespeichert werden, um die Datenzeilen (d. h. Kommentare) einem bestimmten Blog-Artikel zuzuordnen. Hier ist der grundlegende SQL-Code zum Erstellen einer Beispiel-MyISAM-Tabelle:
DROP TABLE IF EXISTS `test`.`blogs`;
TABELLE `test`.`blogs` ERSTELLEN (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`Titel` TEXT,
„Inhalt“-TEXT,
`Autor` VARCHAR(45) DEFAULT NULL,
PRIROSE-SCHLÜSSEL („id“)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `test`.`comments`;
TABELLE „test“ ERSTELLEN. „Kommentare“ (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
„Kommentar“ TEXT,
`Autor` VARCHAR(45) DEFAULT NULL,
PRIROSE-SCHLÜSSEL („id“)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Oben haben wir gerade zwei MyISAM-Tabellen definiert, die die Datenschicht der Blog-Anwendung bilden. Wie Sie sehen, heißt die erste Tabelle Blogs. Sie besteht aus einigen offensichtlichen Feldern, in denen die ID, der Titel und der Inhalt jedes Blog-Beitrags und schließlich der Autor gespeichert werden. Die zweite Tabelle mit dem Namen „Kommentare“ dient zum Speichern von Kommentaren zu jedem Blog-Beitrag. Sie verwendet die ID des Blog-Beitrags als Fremdschlüssel, um eine Eins-zu-Viele-Beziehung herzustellen.
Bisher war unsere Arbeit einfach, da wir nur zwei einfache MyISAM-Tabellen erstellt haben. Als Nächstes möchten wir diese Tabellen mit einigen Datensätzen füllen, um weiter zu veranschaulichen, was in der anderen Tabelle geschehen soll, wenn ein Eintrag in der ersten Tabelle gelöscht wird.
Aktualisieren und bewahren Sie die Datenbankintegrität
Im vorherigen Teil haben wir zwei MyISAM-Tabellen erstellt, die als Datenschicht der Blog-Anwendung dienen. Natürlich ist die obige Einführung immer noch sehr einfach und wir müssen sie weiter diskutieren. Dazu füllen wir diese Tabellen mit einigen Datensätzen, indem wir SQL-Befehle wie folgt verwenden:
INSERT INTO blogs (id, title, content, author) VALUES (NULL,'Titel des ersten Blogeintrags', 'Inhalt des ersten Blogeintrags', 'Ian')
INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, 1, „Kommentiert ersten Blogeintrag“, „Susan Norton“), (NULL, 1, „Kommentiert ersten Blogeintrag“, „Rose Wilson“)
Der obige Code simuliert tatsächlich die Situation, in der die Leser Susan und Rose einen Kommentar zu unserem ersten Blog abgegeben haben. Angenommen, wir möchten jetzt den ersten Blog mit einem weiteren Beitrag aktualisieren. Natürlich ist diese Situation möglich.
In diesem Fall muss zur Wahrung der Datenbankkonsistenz auch die Kommentartabelle entsprechend aktualisiert werden, entweder manuell oder durch eine Anwendung, die die Datenschicht verarbeitet. In diesem Beispiel verwenden wir einen SQL-Befehl, um die Aktualisierung wie folgt abzuschließen:
UPDATE blogs SET id = 2, title = 'Titel des ersten Blogeintrags', content = 'Inhalt des ersten Blogeintrags', Autor = 'John Doe' WHERE id = 1
UPDATE-Kommentare SET blog_id = 2 WHERE blod_id = 1
Wie bereits erwähnt, muss die Kommentartabelle diese Änderung ebenfalls widerspiegeln, da der Inhalt des Datenelements des ersten Blogs aktualisiert wurde. In Wirklichkeit sollte dieser Aktualisierungsvorgang natürlich auf der Anwendungsebene und nicht manuell durchgeführt werden, was bedeutet, dass diese Logik mithilfe einer serverseitigen Sprache implementiert werden muss.
Um diesen Vorgang abzuschließen, kann PHP einen einfachen Unterprozess verwenden. Wenn jedoch Fremdschlüsseleinschränkungen verwendet werden, kann der Aktualisierungsvorgang der Kommentartabelle tatsächlich an die Datenbank delegiert werden.
Wie bereits in diesem Artikel erwähnt, bieten InnoDB-MySQL-Tabellen nahtlose Unterstützung für diese Funktionalität. Daher werden wir im späteren Teil Fremdschlüsseleinschränkungen verwenden, um den vorherigen Beispielcode neu zu erstellen.
Kaskadierende Aktualisierungen der Datenbank
Im Folgenden werden wir den vorherigen Beispielcode mithilfe von Fremdschlüsseleinschränkungen und einer InnoDB-Tabelle (anstelle des Standardtyps MyISAM) umstrukturieren. Definieren Sie dazu zunächst die beiden Beispieltabellen neu, damit sie eine bestimmte Datenbank-Engine verwenden können. Dazu können Sie SQL-Code wie den folgenden verwenden:
DROP TABLE IF EXISTS `test`.`blogs`;
TABELLE `test`.`blogs` ERSTELLEN (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`Titel` TEXT,
„Inhalt“-TEXT,
`Autor` VARCHAR(45) DEFAULT NULL,
PRIROSE-SCHLÜSSEL („id“)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `test`.`comments`;
TABELLE „test“ ERSTELLEN. „Kommentare“ (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
„Kommentar“ TEXT,
`Autor` VARCHAR(45) DEFAULT NULL,
PRIROSE-SCHLÜSSEL („id“),
SCHLÜSSEL `blog_ind` (`blog_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Ein offensichtlicher Unterschied zwischen dem Code hier und dem vorherigen Code besteht darin, dass die beiden Tabellen jetzt die InnoDB-Speicher-Engine verwenden, sodass sie Fremdschlüsseleinschränkungen unterstützen können. Darüber hinaus müssen wir auch auf den Code achten, der die Kommentartabelle definiert:
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE
Tatsächlich teilt diese Anweisung MySQL mit, dass bei der Aktualisierung der Blogs-Tabelle auch der Wert des Fremdschlüssels blog_id in der Kommentartabelle aktualisiert werden sollte. Mit anderen Worten: MySQL soll die Datenbankintegrität kaskadenartig aufrechterhalten. Das bedeutet, dass bei der Aktualisierung eines Blogs auch die damit verbundenen Kommentare diese Änderung sofort widerspiegeln müssen . Dies geschieht nicht auf der Anwendungsebene.
Die beiden Beispiel-MySQL-Tabellen wurden nun definiert. Das Aktualisieren dieser beiden Tabellen ist so einfach wie das Ausführen einer UPDATE-Anweisung, wie unten gezeigt:
„UPDATE blogs SET id = 2, title = ‚Titel des ersten Blogeintrags‘, content = ‚Inhalt des ersten Blogeintrags‘, Autor = ‚John Doe‘ WHERE id = 1“
Wie bereits erwähnt, müssen wir die Kommentartabelle nicht aktualisieren, da MySQL dies automatisch erledigt. Darüber hinaus können Sie MySQL veranlassen, nichts zu unternehmen, wenn versucht wird, eine Zeile in der Tabelle „Blogs“ zu aktualisieren, indem Sie den „ON UPDATE“-Teil der Abfrage entfernen oder „NO ACTION“ und „RESTRICT“ angeben. Natürlich können Sie MySQL auch andere Dinge erledigen lassen, die in späteren Artikeln vorgestellt werden.
Ich denke, durch die obige Einführung hat jeder ein klares Verständnis dafür, wie man Fremdschlüsseleinschränkungen in Verbindung mit InnoDB-Tabellen in MySQL verwendet. Natürlich können Sie auch direkt Code schreiben, um Ihr Verständnis dieser praktischen Datenbankfunktion weiter zu vertiefen.