Tabellen. Primärschlüssel und Generatoren
_NOTICE: Dieses Dokument ist ein Kapitel aus dem Buch “The InterBase World”, das von Alexey Kovyazin und Serg Vostrikov geschrieben wurde.
InterBase ist ein relationales DBMS. Darüber hinaus bedeutet dies, dass alle Daten in InterBase als Tabellen gespeichert werden. Die Tabelle, wie sie aus SQL-Sicht realisiert ist, ähnelt stark der gewöhnlichen Tabelle, die von Hand auf einem Blatt Papier gezeichnet oder in einem Programm wie Microsoft Excel erstellt werden kann. Tabellen in InterBase haben Spalten und Zeilen, in denen Daten platziert werden. Die Tabelle hat notwendigerweise einen Namen, der innerhalb einer Datenbank eindeutig ist. Tabellen sind der Hauptspeicher für Informationen in einer Datenbank, und daher sollten Sie beim Erstellen von Tabellen sehr vorsichtig sein.
Es gibt Regeln, die beschreiben, wie Tabellen in der relationalen Datenbank erstellt werden sollen, die die Daten der realen Welt widerspiegeln und gleichzeitig eine effektive Speicherung der Informationen in einer Datenbank ermöglichen. Der Prozess der Anwendung dieser Regeln zur Gestaltung einer “korrekten” Datenbank wird Normalisierung genannt. Wir haben das Wort “korrekt” bewusst in Anführungszeichen gesetzt, weil “normalisierte Datenbank” und “optimierte Datenbank” keine Synonyme sind. Sie müssen nicht eindeutig den Regeln der Normalisierung entsprechen - wenden Sie immer die Korrektur für die Spezifikation eines gegebenen Problems an.
Die Normalisierung von Tabellen in einer Datenbank wird im Buch [14. ausführlich behandelt, und daher werden wir nicht versuchen, das Unfassbare zu umfassen, und wir kehren zu unserem Diskussionsthema zurück - zu InterBase-Tabellen. Betrachten wir die Syntax eines DDL-Satzes (DDL - Data Definition Language, weitere Details siehe Glossar), der das Erstellen von Tabellen ermöglicht:
CREATE TABLE table [EXTERNAL [FILE] “”] ( [, | …]);
Hier ist table ein Name der erstellten Tabelle, - die Beschreibung der Spalten (manchmal sagen wir - Felder) der erstellten Tabelle. Die Option table [EXTERNAL [FILE] “”] bedeutet, dass die sogenannte externe Tabelle erstellt wird, die nicht in einer gemeinsamen Datenbankdatei, sondern in einer separaten Datei mit einem Namen gespeichert wird. Wie Sie sehen, ist alles einfach - wir definieren einen Tabellennamen und die Spalten, die sie enthält. Nun betrachten wir im Detail, wie Spalten definiert werden. Die Syntax zum Erstellen einer Spalte wird durch den folgenden DDL-Satz beschrieben:
= col { datatype | COMPUTED [BY] (< expr>)} | domain}
[DEFAULT { literal | NULL | USER}]
[NOT NULL] [ ]
[COLLATE collation]
Dies ist eine ziemlich große Definition, jedoch ist nur ein kleiner Teil der gegebenen Sätze bei der Definition einer Spalte obligatorisch. Jede Spalte in der Tabelle muss einen Namen haben, der innerhalb der Tabelle eindeutig ist, sowie einen Datentyp, der durch den Satz datatype definiert wird, oder einen Ausdruck zur Berechnung des Werts einer Spalte (für berechnete Spalten), oder die Domäne (siehe unten), definiert durch domain. Datentypen wurden im Kapitel “Datentypen” behandelt; daher können Sie leicht verstehen, wie der SQL-Ausdruck zum Erstellen einer Tabelle gebildet wird.
Lassen Sie uns mit unserer Datenbank FIRSTBASE.gdb verbinden, die zuvor im Kapitel “Eine Datenbank erstellen” erstellt wurde, und wir werden versuchen, praktisch mit Tabellen zu arbeiten. Wenn es um das Erstellen, Löschen und Aktualisieren von Tabellen geht, ist jedes der InterBase-Administrationswerkzeuge - von denen, die in der Anwendung “InterBase-Administrator- und Entwicklerwerkzeuge” aufgeführt sind, sowie das Standard-Dienstprogramm isql.exe aus einem Satz der Lieferung eines beliebigen InterBase-Klons - geeignet.
Hier ist ein Beispiel für eine einfache Tabelle namens TABLE_EXAMPLE, die 3 Felder verschiedener Typen enthält:
CREATE TABLE Table_example ( ID INTEGER, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION);
Diese Tabelle veranschaulicht den häufigsten Fall im Prozess der Datenbankentwicklung. Es gibt jedoch auch andere Methoden zur Definition von Feldern. Zum Beispiel können wir einen Feldtyp mithilfe von Domänen festlegen. Die Domäne ist ein Typ, der vom Benutzer zur Bequemlichkeit der Anwendung bestimmter Kombinationen von Typparametern definiert wird. Zum Beispiel ist es möglich, die Domäne D_ID zur Angabe von Feldern für Identifikatoren zu definieren. Nachdem wir die Domäne definiert haben, können wir sie zur Festlegung des Typs eines Feldes verwenden:
CREATE DOMAIN D_ID AS INTEGER; CREATE TABLE Тable_example ( ID D_ID, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION);
Das Feld ID wird den Typ haben, der durch die Domäne D_ID definiert ist. Somit können wir, nachdem wir den Typ des Feldes in der Domäne, erforderliche Prüfungen und Einschränkungen definiert haben, diese Domäne viele Male zur Erstellung von Feldern derselben Funktion anwenden. Zum Beispiel monetär, ohne mühsame und fehleranfällige Kopien von Definitionen variabler Typen. Der dritte Weg, eine Spalte in der Tabelle festzulegen, besteht darin, sie als berechnet (COMPUTED BY) zu definieren und eine Bedingung anzugeben, nach der ihr Wert berechnet wird. Zum Beispiel könnten wir wünschen, eine Spalte zu haben, die 10 % vom Wert des Feldes PRICE_1 in unserer Tabelle berechnet. In diesem Fall sollte der folgende Befehl geschrieben werden:
CREATE TABLE Тable_example ( ID INTEGER, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION, PRICE_10 COMPUTED BY (PRICE_1.0.1));
Aber denken Sie nicht, dass jetzt, sobald wir die Daten in das Feld PRICE_1 einfügen, im Feld PRICE_10 ein Zehntel des Werts dieses Feldes erscheint. Nein, der Prozess hier ist komplizierter. Tatsächlich erhalten wir das erforderliche Zehntel nur, wenn wir auf das Feld PRICE_10 verweisen, zum Beispiel bei der Ausführung einer SELECT-Abfrage auf diese Tabelle. Das heißt, in einem berechneten Feld werden keine Daten gespeichert, und das Abrufen der Berechnung des mit einem Feld verbundenen Ausdrucks wird durchgeführt, und das Ergebnis wird als Antwort auf die Abfrage erzeugt.
So haben wir 3 Hauptwege zur Angabe von Feldern in der Tabelle betrachtet. Nun betrachten wir im Detail Optionen, die beim Erstellen einer Spalte festgelegt werden können. Die Option [DEFAULT {literal | NULL | USER}] - ermöglicht es, einen Spaltenwert standardmäßig festzulegen. Dies ist sehr praktisch für die automatische Datenbefüllung. Es gibt 3 Möglichkeiten, einen Standard festzulegen. Die erste wird als literal bezeichnet und ermöglicht es, Standardwerte als Textkonstanten, Zahlen oder Daten festzulegen. Zum Beispiel können wir die folgenden Ausdrücke zum Erstellen einer Spalte mit Textstandards generieren: NAME VARCHAR(80) DEFAULT ‘Василий Станиславович’
Somit nehmen alle in die Tabelle eingefügten Felder Standardwerte an, d.h. wenn kein anderer Wert für das Feld NAME definiert wurde, erscheint die Zeichenfolge ‘Vasily Stanislavovich’. Der zweite Weg, einen Standard festzulegen, besteht darin, DEFAULT NULL in der Definition einer Spalte anzugeben. Und in neu erstellten Datensätzen wird der Wert dieser Spalte NULL sein, wenn der andere Wert natürlich nicht offensichtlich festgelegt wurde. Ein Beispiel:
PRICE_1 DOUBLE PRECISION DEFAULT NULL
Der dritte Weg, einen Standard festzulegen, besteht darin, DEFAULT USER in der Definition einer Spalte anzugeben. Somit enthält dieses Feld in neu erstellten Datensätzen den Namen des aktuellen Benutzers, d.h. des Benutzers, der eine Verbindung mit InterBase hergestellt und dieses Einfügen ausgeführt hat (weitere Details zu Benutzern siehe Kapitel “Sicherheit in InterBase: Benutzer, ihre Funktionen und Rechte” (Teil 4)). Für einige Felder ist es wesentlich, dass das Feld einen nicht leeren Wert hat. Zum Beispiel ein Feld, das gemäß Problemspezifikation nicht leer sein kann. Um eine Einschränkung auf Datenbankebene festzulegen, dass ein Feld einen definierten Wert haben sollte, ist es notwendig, die folgende Ergänzung zur Beschreibung einer Spalte zu machen:
NAME VARCHAR(80) NOT NULL
Somit wird es ein Feld geben, in dem keine Nullwerte gespeichert werden können. Normalerweise wird die Einschränkung NOT NULL mit der Option DEFAULT kombiniert, die diesem Feld definitiv einen korrekten Wert zuweist. Aber oft reicht die Einschränkung NOT NULL nicht aus. Zum Beispiel ist es bei der Speicherung von Preisen in einer Datenbank ziemlich klar, dass sie keine negativen Werte annehmen können (obwohl es großartig wäre, wenn wir beim Kauf von Waren zusätzlich bezahlt würden). Um den Server zu veranlassen, die in eine Datenbank eingefügten Preiswerte auf eine Bedingung der Positivität zu prüfen, ist es notwendig, eine Spalte wie folgt zu definieren:
PRICE_1 DOUBLE PRECISION CHECK (PRICE_1>0)
Werte, die in die Spalte PRICE_1 eingefügt werden, werden auf eine Bedingung der Positivität geprüft. Es sollte beachtet werden, dass verschiedene konsistente Optionen kombiniert werden können, und zum Beispiel können wir einen nicht leeren Wert und eine Prüfung auf Positivität festlegen:
PRICE_1 DOUBLE PRECISION NOT NULL CHECK (PRICE_1>0)
Beim Erstellen der Spalten können einige Optionen nicht kombiniert werden, zum Beispiel ist es unmöglich, NULL standardmäßig und gleichzeitig eine Einschränkung für nicht leere Werte festzulegen. Es sollte markiert werden, dass Prüfungen eine Reihe nützlicher Funktionen zur Datenverwaltung in einer Datenbank ausführen können. Wir werden ihre Verwendung im Detail im Kapitel “Datenbankeinschränkungen” betrachten.
So haben wir die Wege zum Erstellen von Tabellen und Feldern mit verschiedenen Optionen betrachtet. Es gibt jedoch Fälle, in denen wir die bereits vorhandene Tabelle ändern müssen. Sicherlich können wir die Tabelle vollständig neu erstellen. Zuerst sollten wir den Befehl zum Löschen der Tabelle ausführen und sie dann erneut erstellen. Zum Beispiel:
DROP TABLE Table_example; CREATE TABLE Table_example(ID NUMERIC(15,2);
Aber solche Art der Änderung von Tabellen hat erhebliche Nachteile. Beim Löschen einer Tabelle mit dem DROP-Befehl werden alle Daten, die die Tabelle enthält, gelöscht, und um sie nicht zu verlieren, ist es notwendig, sie in temporäre Tabellen zu kopieren. Das ist ziemlich mühsam. Daher gibt es den Befehl ALTER TABLE zur einfachen Änderung der Tabellenstruktur, der es ermöglicht, neue Felder hinzuzufügen, vorhandene zu löschen sowie Einschränkungen der referenziellen Integrität hinzuzufügen/zu löschen.
Zum Beispiel möchten wir eine weitere Spalte zur Tabelle hinzufügen, die zum Speichern der Daten über ein Patronym einer Person bestimmt ist:
ALTER TABLE Table_example ADD Patronimic VARCHAR(80);
Nach der Ausführung dieses Befehls hat unsere Tabelle Table_example eine neue Spalte mit dem Namen Patronimic und dem Typ VARCHAR (80). Wenn wir eine Spalte mit dem Namen NAME aus der Tabelle löschen möchten, sollten wir Folgendes ausführen:
ALTER TABLE Table_example DROP Name;
Sie können die vollständige Syntax der ALTER TABLE-Anweisung in [1.. sehen. Dies ist ein sehr nützlicher Befehl, und wir werden ihn oft verwenden.
Und was tun, werden Sie fragen, wenn es notwendig ist, eine Spalte zu ändern? Zum Beispiel haben wir entschieden, dass es für die Speicherung von Namen besser ist, das Feld HUMAN_NAME als NAME zu verwenden. In diesem Fall können wir ALTER TABLE anwenden:
ALTER TABLE Table_example ALTER COLUMN NAME TO HUMAN_NAME;
Wenn wir uns entschieden haben, den Typ eines Feldes zu ändern, zum Beispiel die Anzahl der Zeichen, die in einem Feld gespeichert werden, zu erhöhen, müssen wir die Domäne dieses Feldes mit der Anweisung ALTER DOMAIN ändern (siehe Kapitel “Datentypen” oben).
So haben wir die Erstellung und Änderung von Tabellen in InterBase betrachtet. Jetzt ist es Zeit, etwas tiefer in die Theorie der Datenbanken einzutauchen. InterBase ist, wie bereits gesagt, eine relationale Datenbank. Darüber hinaus bedeutet dies, dass jeder Datensatz in der Tabelle ein Merkmal haben sollte, nach dem ein Datensatz von einem anderen unterschieden werden kann. Der spezielle Mechanismus der eindeutigen Schlüssel dient diesem Zweck.
Primärschlüssel in Tabellen
Sicherlich können wir eine Tabelle erstellen, die keine Schlüssel enthält. Es ist uns nicht verboten, dies zu tun. Aber, wie bereits gesagt, ist die Erstellung einer effizienten Datenbank ohne die Einhaltung der Normalisierungsregeln unmöglich. Das Vorhandensein von Schlüsseln ist das wichtigste Element der Normalisierung. Daher, obwohl wir nicht darauf abzielen, die Theorie und Normalisierung von Datenbanken zu betrachten, sollten wir eine Definition von Schlüsseln einführen und ihre Funktion in InterBase überprüfen. Wir werden Schritt für Schritt vorgehen und mit dem häufigsten Schlüsseltyp beginnen - einem Primärschlüssel.
Also, was ist ein Primärschlüssel? Es ist ein oder mehrere Felder in der Tabelle, die Datensätze innerhalb dieser Tabelle eindeutig identifizieren. Das klingt schwierig, aber tatsächlich ist alles sehr einfach. Stellen Sie sich eine gewöhnliche Tabelle vor, zum Beispiel das Buchhaltungsblatt. Was ist die allererste Spalte? Das ist richtig, die Seriennummer - 1, 2, 3 … Diese Nummer bezeichnet eine eindeutige Zeile innerhalb der Tabelle, und es reicht aus, diese Nummer zu kennen, um eine Zeichenfolge in dieser Tabelle zu finden. In diesem Beispiel wäre es ein Primärschlüssel. Die überwiegende Mehrheit der Tabellen in einer relationalen Datenbank hat notwendigerweise einen Primärschlüssel (PK - Abkürzung von Primary key). Die allgemeine Richtlinie beim Erstellen der Tabellen ist es, einen Primärschlüssel zu erstellen. Ein Primärschlüssel kann beim Erstellen einer Tabelle oder später erstellt werden. Nehmen wir an, dass wir zum Zeitpunkt der Erstellung einer Tabelle entschieden haben, dass das Feld ID unser Primärschlüssel sein wird. Dann können wir einen Primärschlüssel wie folgt hinzufügen:
CREATE TABLE Table_example ( ID INTEGER NOT NULL, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION, CONSTRAINT pkTable PRIMARY KEY (ID));
Was muss getan werden, um einen Primärschlüssel für die Tabelle table_example zu erstellen? Lassen Sie uns untersuchen, was sich in der Definition der Tabelle geändert hat? Zuerst hat die Spalte ID die zusätzliche Definition NOT NULL erhalten. Das ist wichtig, denn der Primärschlüssel sollte eindeutig und von undefinierten Werten ausgeschlossen sein. Und NULL ist, wie Sie wissen, ein undefinierter Wert. Daher sollten alle Felder, die in einen Primärschlüssel einbezogen werden, die Einschränkung NOT NULL haben. Um die Erstellung eines Primärschlüssels abzuschließen, sollte am Ende der Tabelle Folgendes geschrieben werden: CONSTRAINT ()
Die vollständige Syntax der Einschränkungen finden Sie im Kapitel „Datenbank-Einschränkungen“ þ. 1, und für unser Beispiel eines Primärschlüssels sieht es so aus:
CONSTRAINT pkTable PRIMARY KEY (ID)
Hier ist pkTable der Name eines Primärschlüssels, und ID sind die Spalten, die er enthält. Diese Art der Definition von Primärschlüsseln für Tabellen ist praktisch bei der Massenerstellung von Tabellen (zum Beispiel beim Aufbau eines Datenbank-Prototyps auf der Grundlage von Skripten, die von verschiedenen CASE-Ressourcen erhalten wurden). Aber was tun, wenn wir einen Primärschlüssel zu einer Tabelle hinzufügen / löschen müssen, die bereits existiert und mit Daten gefüllt ist? Zu diesem Zweck sollte eine weitere Erweiterung des Befehls - ALTER TABLE - angewendet werden. Ein Beispiel für das Hinzufügen eines Primärschlüssels zu unserer Tabelle:
ALTER TABLE TABLE_EXAMPLE ADD CONSTRAINT FF PRIMARY KEY (ID);
Somit wird die Tabelle Table_example genau denselben Primärschlüssel haben wie im vorherigen Beispiel, als sie zusammen mit der Tabelle erstellt wurde. Um einen Primärschlüssel zu löschen, sollte der folgende Befehl eingegeben werden:
ALTER TABLE Table_example DROP CONSTRAINT pkTable;
Somit wird der Schlüssel mit dem Namen pkTable aus einer Datenbank entfernt.
Generatoren - beste Freunde von Primärschlüsseln
Wir müssen einige Worte über die Implementierung eines Primärschlüssels sagen. Da er dazu dient, Eindeutigkeit zu unterstützen, können keine zwei Datensätze in einer Tabelle dieselben Werte dieses Schlüssels haben. Das heißt, um die Bedingung zu erfüllen, muss InterBase beim Einfügen eines neuen Datensatzes in die Tabelle alle Datensätze in der Tabelle überprüfen und feststellen, ob die Tabelle solche Werte enthält oder nicht. Für die schnelle Suche hat InterBase einen Mechanismus von Indizes - spezielle InterBase-Objekte, die es ermöglichen, einen Datensatz in der Tabelle sehr schnell zu finden. Daher wird beim Erstellen und Löschen des Primärschlüssels ein Index für das Feld (oder die Felder) erstellt oder gelöscht, das in den Primärschlüssel einbezogen ist.
Wie bereits erwähnt, kann der Primärschlüssel einige Felder enthalten. Somit können wir eine Eindeutigkeit einer Kombination von Werten dieser Felder feststellen. Wenn wir zum Beispiel einen Schlüssel für die Felder ID und NAME definieren, wird der Server kontrollieren, dass es keine identischen Kombinationen dieser Felder in der Tabelle gibt. Das heißt, Kombinationen der Felder ID und 1 und „Ivanov“, 2 und „Ivanov“ werden korrekt sein, da sie sich in den Werten des Feldes ID unterscheiden.
Somit kann der Primärschlüssel einige Felder beliebiger Typen enthalten. In der Praxis ist jedoch der häufigste Typ des Schlüssels der Zähler - ein ganzzahliges Feld, das zunehmende Werte enthält. Warum ist das so? Es ist der Ausdruck eines alten Streits zwischen natürlichen und Ersatzschlüsseln. Das Konzept der natürlichen Schlüssel besagt, dass wir als Schlüssel versuchen sollten, die Werte zu verwenden, die tatsächlich in der Datendomäne existieren, die eine Datenbank widerspiegelt. Wenn wir zum Beispiel ein System zur Registrierung von Personen für ein Passamt entwickeln, sollte nach diesem Konzept eine Kombination aus Nummer und Serie des Passes als Primärschlüssel genommen werden. Tatsächlich muss jede Person eine eindeutige Kombination aus Nummer und Serie des Passes haben. Aber was tun mit der Tatsache, dass eine Person im Laufe seines Lebens den Pass wechseln kann (im Zusammenhang mit dem Erreichen eines bestimmten Alters, Heirat usw.)? In diesem Fall müssen wir die Nummer und die Serie des Passes ändern, die der konkreten Person zugeordnet sind, d.h. tatsächlich unseren Primärschlüssel ändern. Das ist aus Sicht der Entwicklung von Datenbankanwendungen unerwünscht: Unter Berücksichtigung eines verzweigten Systems der Kommunikation zwischen Tabellen (das nächste Kapitel ist diesem Thema gewidmet) wird der Entwickler große Mühen auf sich nehmen müssen, um diese Situation zu kontrollieren.
Daher wird in den meisten Fällen ein Ersatzschlüssel verwendet. Ersatz - bedeutet künstlich, d.h. nicht in der Datendomäne existierend, die unsere Datenbank beschreibt, und künstlich erstellt - für die Bequemlichkeit der Entwicklung von Datenbankanwendungen. Wie gesagt, ist normalerweise ein Zähler ein Primärschlüssel. Einige DBMS, wie Paradox und MS SQL, haben einen speziellen Typ - den Zähler (Auto-Inkrement). Beim Hinzufügen eines neuen Datensatzes zur Tabelle erhöht sich ein Feldwert automatisch mit diesem Typ um den Wert eines Inkrements - normalerweise um Einheiten. In InterBase gibt es kein Feld vom Typ Zähler, jedoch kann ein solches Verhalten realisiert werden. Für die Erstellung des Feldes, das beim Hinzufügen eines Datensatzes zur Tabelle automatisch gefüllt würde, wird eine Sammlung von Ressourcen verwendet: Die erste davon ist der Generator.
Was ist ein Generator? Einfach gesagt, ist ein Generator ein benannter Zähler. Innerhalb einer Datenbank können wir einen Zähler erstellen, ihm einen eindeutigen Namen innerhalb dieser Basis geben und die Werte dieses Zählers steuern. Das wird ein Generator sein. Hier ist ein Beispiel für DDL-Anweisungen, die es Ihnen erklären:
CREATE GENERATOR g1; SET GENERATOR g1 TO 2445;
In der ersten Zeile dieses Beispiels wird ein Generator mit dem Namen g1 erstellt, und in der zweiten Zeile wird diesem Generator der Wert 2445 zugewiesen. Nun stellt sich die Frage, wie man den erhaltenen Generator verwendet. Es gibt eine eingebaute Funktion GEN_ID in InterBase zum Abrufen und Ändern der Werte von Generatoren. Diese Funktion nimmt als Parameter den Namen des Generators und den Wert des Inkrements, das auf den gegebenen Generator angewendet werden soll, und gibt den ganzzahligen Wert zurück, der dem Wert des Generators entspricht, der als Ergebnis der Addition des Inkrements zu ihm erhalten wird. Hier ist ein Beispiel für einen GEN_ID-Funktionsaufruf in einem Trigger oder einer gespeicherten Prozedur:
Current_value = GEN_ID (g1, 1)
Wenn wir den Wert des Generators erhalten möchten, können wir die folgende Abfrage verwenden:
SELECT GEN_ID(g1, 1)FROM RDB$ DATABASE
Da die Tabelle RDB $ Database immer nur einen Datensatz enthält, erhalten wir als Ergebnis der gegebenen Abfrage einen Wert des Generators g1.
Hier ist current_value eine Variable (in den folgenden Kapiteln finden Sie Informationen, wie Sie Variablen in InterBase verwenden), g1 - ein Generator, 1 - Inkrement. In diesem Beispiel wird der Wert des Generators g1 in die Variable current_value gelangen, nachdem das Inkrement 1 zu ihm hinzugefügt wurde, d.h. der nächste Wert des Generators. Beachten Sie, dass das Inkrement nicht gleich 1 sein muss! Darüber hinaus kann es sogar negativ sein: Current_value = GEN_ID (g1, -23)
Als Ergebnis der Ausführung dieser Funktion wird der aktuelle Wert des Generators g1 minus 23 sein. Wie Sie sehen können, ist der Bereich möglicher Anwendungen von Generatoren ziemlich breit - er kann nicht nur zum Erhalten von Werten von Primärschlüsseln verwendet werden, sondern auch zum Überwachen globaler Änderungen in einer Datenbank.
Personen, die mit Datenbanken vertraut sind, könnten eine Frage stellen: „Was wird passieren, wenn gleichzeitig einige Clients versuchen, Daten in dieselbe Tabelle zu setzen und gleichzeitig die Generatoren ‚ziehen‘? Werden sie dieselben oder unterschiedliche Werte des Generators erhalten?“ Sie werden eindeutig UNTERSCHIEDLICHE Werte des Generators erhalten. Wie „gleichzeitig“ der Versuch war, den Wert des Generators zu erhalten, würde jeder, der sich beworben hat, den eindeutigen Wert erhalten. Es ist durch die „Konstruktion“ von Generatoren garantiert: Sie arbeiten auf der niedrigsten Ebene eines Servers und keine Prozesse des Aufzeichnens und Einfügens beeinflussen sie - es wird oft gesagt, dass Generatoren „außerhalb des Kontexts von Transaktionen“ arbeiten. Wenn Sie mehr über Transaktionen erfahren möchten, lesen Sie das Kapitel „Transaktionen. Parameter von Transaktionen“ (Teil 1); wie Generatoren aufgebaut sind - „InterBase-Datenbankstruktur“ (Teil 4). Nun, im Namen von Generatoren haben wir einen zuverlässigen Mechanismus zum Erstellen eindeutiger Primärschlüssel. Können wir diesen Mechanismus jedoch verwenden? Wie setzen wir den vom Generator erhaltenen Wert in ein Feld des Primärschlüssels?
Zu diesem Zweck gibt es zwei Wege - einen Primärschlüssel im Namen eines Clients und im Namen eines Servers einzufügen. Um den ersten Weg zu meistern, sollten wir auf das Kapitel „Verwendung der Hauptkomponenten von FIBPlus“ verweisen und den zweiten verstehen - auf das Kapitel „Trigger“ (Teil 1). Hier werden wir kurz den Hauptpunkt beider Wege überprüfen.
Im Fall der Erstellung eines Primärschlüssels im Namen eines Clients passiert Folgendes. Wenn der Datensatz, der in eine Datenbank eingefügt wird, generiert wird, wird der GEN_ID-Funktionsaufruf (, 1) ausgeführt und der erhaltene Wert wird für diesen Datensatz eingesetzt. Dann findet das Einfügen in die Tabelle statt, und wir erhalten garantiert einen eindeutigen Primärschlüssel.
Der zweite Weg - die Erstellung eines Primärschlüssels im Namen eines Servers - eliminiert im Allgemeinen jede Sorge von Seiten des Clients darüber, welcher Wert eines Primärschlüssels sein wird. In diesem Fall arbeitet beim Einfügen des Datensatzes der Trigger - ein spezielles Datenbankobjekt, das beliebige Operationen beim Einfügen / Löschen / Aktualisieren der Datensätze in Tabellen ausführen kann. Und in diesem Trigger werden die folgenden Operationen erfüllt: GEN_ID-Funktionsaufruf, Erhalten des erforderlichen Werts des Generators und sein Einfügen in die Tabelle. Der Vorteil des zweiten Weges ist, dass bei der Entwicklung einer Client-Anwendung keine Sorge um die Erstellung eines Primärschlüssels besteht, das Einzige, was Sie tun müssen, ist, einen notwendigen Trigger einmal zu schreiben. Aber der Nachteil ist, dass wir den Wert des generierten Schlüssels in der Anwendung nicht direkt nach dem Einfügen erhalten können! Wenn wir den ersten Weg verwenden, können wir den Wert des Primärschlüssels erhalten, obwohl wir uns bei jedem Einfügen um seine Erstellung kümmern müssen. Es ist schwer zu sagen, welcher Weg besser ist, alles hängt von einem spezifischen Problem ab. Weiter in diesem Buch werden wir mögliche Varianten zur Lösung der Fragen über die Arbeit mit einem Primärschlüssel betrachten.
Fazit
Also, in diesem Kapitel haben wir überprüft, wie man Tabellen in InterBase erstellt und aktualisiert, sowie die Primärschlüssel verwaltet. Somit haben wir die Hauptobjekte in InterBase betrachtet, die bedingt als statisch bezeichnet werden können, weil sie nur die Informationen speichern und keine Umwandlung durchführen. Weiter werden wir über die Wege der Informationssteuerung und Informationsumwandlung innerhalb einer Datenbank sprechen.