Kapitel 13. SQL-Anweisungssyntax

Inhaltsverzeichnis

13.1. Datendefinition: CREATE, DROP, ALTER
13.1.1. ALTER DATABASE
13.1.2. ALTER TABLE
13.1.3. CREATE DATABASE
13.1.4. CREATE INDEX
13.1.5. CREATE TABLE
13.1.6. DROP DATABASE
13.1.7. DROP INDEX
13.1.8. DROP TABLE
13.1.9. RENAME TABLE
13.2. Datenmanipulation: SELECT, INSERT, UPDATE, DELETE
13.2.1. DELETE
13.2.2. DO
13.2.3. HANDLER
13.2.4. INSERT
13.2.5. LOAD DATA INFILE
13.2.6. REPLACE
13.2.7. SELECT
13.2.8. Syntax von Unterabfragen
13.2.9. TRUNCATE
13.2.10. UPDATE
13.3. Grundlegende Befehle des MySQL-Dienstprogramms für Benutzer
13.3.1. DESCRIBE (Informationen über Spalten abrufen)
13.3.2. USE
13.4. Transaktionale und Sperrbefehle von MySQL
13.4.1. BEGIN/COMMIT/ROLLBACK
13.4.2. Statements können nicht zurückgerollt werden
13.4.3. Anweisungen, die implizite Commits verursachen
13.4.4. SAVEPOINT und ROLLBACK TO SAVEPOINT
13.4.5. LOCK TABLES und UNLOCK TABLES
13.4.6. SET TRANSACTION
13.4.7. XA-Transaktionen
13.5. Anweisungen zur Datenbankadministration
13.5.1. Anweisungen zur Benutzerkontenverwaltung
13.5.2. Anweisungen für die Tabellenwartung
13.5.3. SET
13.5.4. SHOW
13.5.5. Weitere Verwaltungsanweisungen
13.6. SQL-Befehle in Bezug auf Replikation
13.6.1. SQL-Anweisungen für die Steuerung von Master-Servern
13.6.2. SQL-Anweisungen für die Steuerung von Slave-Servern
13.7. SQL-Syntax für vorbereitete Anweisungen

Dieses Kapitel beschreibt die Syntax für die meisten von MySQL unterstützten SQL-Anweisungen. Weitere Beschreibungen zu Anweisungen finden Sie in den folgenden Kapiteln:

13.1. Datendefinition: CREATE, DROP, ALTER

13.1.1. ALTER DATABASE

ALTER {DATABASE | SCHEMA} [db_name]
    alter_specification [, alter_specification] ...

alter_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

Mit ALTER DATABASE können Sie die grundlegenden Eigenschaften einer Datenbank ändern. Diese Eigenschaften sind in der Datei db.opt im Datenbankverzeichnis gespeichert. Um ALTER DATABASE verwenden zu können, benötigen Sie die Berechtigung ALTER für die Datenbank. ALTER SCHEMA ist ein Synonym für ALTER DATABASE.

Die Klausel CHARACTER SET ändert den Standardzeichensatz der Datenbank. Die Klausel COLLATE ändert die Standardsortierfolge der Datenbank. Kapitel 10, Zeichensatz-Unterstützung, behandelt Namen von Zeichensätzen und Sortierfolgen.

Der Datenbankname kann weggelassen werden. In diesem Fall bezieht sich die Anweisung auf die Standarddatenbank.

13.1.2. ALTER TABLE

ALTER [IGNORE] TABLE tbl_name
    alter_specification [, alter_specification] ...

alter_specification:
    ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
  | ADD [COLUMN] (column_definition,...)
  | ADD INDEX [index_name] [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        PRIMARY KEY [index_type] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        UNIQUE [INDEX] [index_name] [index_type] (index_col_name,...)
  | ADD FULLTEXT [INDEX] [index_name] (index_col_name,...)
      [WITH PARSER parser_name]
  | ADD SPATIAL [INDEX] [index_name] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]]
        FOREIGN KEY [index_name] (index_col_name,...)
        [reference_definition]
  | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  | CHANGE [COLUMN] old_col_name column_definition
        [FIRST|AFTER col_name]
  | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
  | DROP [COLUMN] col_name
  | DROP PRIMARY KEY
  | DROP INDEX index_name
  | DROP FOREIGN KEY fk_symbol
  | DISABLE KEYS
  | ENABLE KEYS
  | RENAME [TO] new_tbl_name
  | ORDER BY col_name
  | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | DISCARD TABLESPACE
  | IMPORT TABLESPACE
  | table_options
  | partition_options
  | ADD PARTITION partition_definition
  | DROP PARTITION partition_names
  | COALESCE PARTITION number
  | REORGANIZE PARTITION partition_names INTO (partition_definitions)
  | ANALYZE PARTITION partition_names
  | CHECK PARTITION partition_names
  | OPTIMIZE PARTITION partition_names
  | REBUILD PARTITION partition_names
  | REPAIR PARTITION partition_names

ALTER TABLE ermöglicht Ihnen das Ändern der Struktur einer vorhandenen Tabelle. Sie können beispielsweise Spalten hinzufügen oder entfernen, Indizes erstellen oder löschen, den Typ einer vorhandenen Spalte ändern oder Spalten oder die Tabelle umbenennen. Ferner können Sie den Kommentar für die Tabelle und auch den Tabellentyp modifizieren.

Die Syntax für viele der zulässigen Änderungen ähnelt Klauseln der CREATE TABLE-Anweisung. Hierzu gehören table_options-Modifikationen für Optionen wie ENGINE, AUTO_INCREMENT und AVG_ROW_LENGTH. (Allerdings ignoriert ALTER TABLE die Tabellenoptionen DATA DIRECTORY und INDEX DIRECTORY.) Abschnitt 13.1.5, „CREATE TABLE, listet alle Tabellenoptionen auf.

Bei manchen Operationen kann eine Warnung erzeugt werden, wenn diese auf eine Tabelle angewendet werden sollen, deren Speicher-Engine die Operation nicht unterstützt. Diese Warnungen lassen sich mit SHOW WARNINGS anzeigen. Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS.

ALTER TABLE erstellt zunächst eine temporäre Kopie der Ursprungstabelle. Die Änderung wird dann an der Kopie vorgenommen, und schließlich wird die Originaltabelle gelöscht und die Kopie entsprechend umbenannt. Während der Ausführung von ALTER TABLE kann die Originaltabelle von anderen Clients gelesen werden. Änderungs- und Schreiboperationen in der Tabelle werden blockiert, bis die neue Tabelle bereit ist, und dann automatisch in die neue Tabelle umgeleitet. Aktualisierungen schlagen nicht fehl.

Beachten Sie, dass, wenn Sie eine andere ALTER TABLE-Option als RENAME verwenden, MySQL immer eine Temporärtabelle erstellt – und zwar auch dann, wenn die Daten strenggenommen nicht kopiert werden müssten (z. B. wenn Sie nur den Namen einer Spalte ändern). Bei MyISAM-Tabellen ist die Neuerstellung des Indexes der zeitaufwändigste Teil des Änderungsvorgangs. Sie können diesen beschleunigen, indem Sie die Systemvariable myisam_sort_buffer_size auf einen hohen Wert setzen.

  • Um ALTER TABLE zu verwenden, benötigen Sie die Berechtigungen ALTER, INSERT und CREATE für die Tabelle.

  • IGNORE ist eine MySQL-Erweiterung zum SQL-Standard. Sie steuert, wie ALTER TABLE funktioniert, wenn Dubletten eindeutiger Schlüssel in der neuen Tabelle vorhanden sind oder (bei aktiviertem striktem Modus) Warnungen auftreten. Wenn IGNORE nicht angegeben ist, wird der Vorgang bei Auftreten von Schlüsseldubletten abgebrochen, und ein Rollback wird durchgeführt. Ist IGNORE angegeben, dann wird nur der erste von mehreren Datensätzen mit Dubletten eindeutiger Schlüssel verwendet. Die übrigen betroffenen Datensätze werden gelöscht. Falsche Werte werden auf den nächstliegenden zulässigen Wert gesetzt.

  • Sie können mehrere ADD-, ALTER-, DROP- und CHANGE-Klauseln in einer ALTER TABLE-Anweisung angeben. Diese werden durch Kommata getrennt. Dies ist eine MySQL-Erweiterung zum SQL-Standard, der nur jeweils eine dieser Klauseln je ALTER TABLE-Anweisung zulässt. Um beispielsweise mehrere Spalten mit einer einzelnen Anweisung zu löschen, tun Sie Folgendes:

    ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
    
  • CHANGE col_name, DROP col_name und DROP INDEX sind MySQL-Erweiterungen zum SQL-Standard.

  • MODIFY ist eine Oracle-Erweiterung zu ALTER TABLE.

  • Das Wort COLUMN ist optional und darf weggelassen werden.

  • Wenn Sie ALTER TABLE tbl_name RENAME TO new_tbl_name ohne zusätzliche Optionen sehen, benennt MySQL alle Dateien, die der Tabelle tbl_name entsprechen, einfach um. Es ist nicht notwendig, eine Temporärtabelle zu erstellen. (Sie können zum Umbenennen von Tabellen auch die Anweisung RENAME TABLE verwenden. Siehe auch Abschnitt 13.1.9, „RENAME TABLE.)

  • column_definition-Klauseln verwenden dieselbe Syntax für ADD und CHANGE wie bei CREATE TABLE. Beachten Sie, dass diese Syntax den Spaltennamen (und nicht nur den Datentyp) enthält. Siehe auch Abschnitt 13.1.5, „CREATE TABLE.

  • Sie können eine Spalte mithilfe einer CHANGE old_col_name column_definition-Klausel umbenennen. Zu diesem Zweck geben Sie den alten und den neuen Spaltennamen sowie den Typ an, den die Spalte zurzeit hat. Um beispielsweise eine INTEGER-Spalte von a zu b umzubenennen, geben Sie Folgendes ein:

    ALTER TABLE t1 CHANGE a b INTEGER;
    

    Wenn Sie den Typ einer Spalte, nicht aber ihren Namen ändern wollen, erfordert die CHANGE-Syntax trotzdem einen alten und neuen Spaltennamen, auch wenn diese dann identisch sind. Zum Beispiel:

    ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
    

    Sie können den Spaltentyp auch mit MODIFY ändern, ohne die Spalte umzubenennen:

    ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
    
  • Wenn Sie CHANGE oder MODIFY zum Kürzen einer Spalte verwenden, für die ein Index vorhanden ist, und die Länge der Spalte nach der Operation geringer ist als die Indexlänge, dann kürzt MySQL den Index automatisch.

  • Ändern Sie einen Datentyp mit CHANGE oder MODIFY, dann versucht MySQL, vorhandene Spaltenwerte bestmöglich in den neuen Typ zu konvertieren.

  • Um eine Spalte an eine bestimmte Position in einer Tabellenzeile hinzuzufügen, verwenden Sie FIRST oder AFTER col_name. Standardmäßig werden neue Spalten am Ende eingefügt. Sie können FIRST und AFTER auch bei CHANGE- oder MODIFY-Operationen verwenden.

  • ALTER ... SET DEFAULT oder ALTER ... DROP DEFAULT geben einen neuen Vorgabewert für eine Spalte an bzw. entfernen den vorhandenen Vorgabewert. Wenn die alte Vorgabe entfernt wird und die Spalte NULL werden kann, dann wird NULL zum neuen Vorgabewert. Kann die Spalte nicht NULL werden, dann weist MySQL einen Standardwert zu (siehe auch Abschnitt 11.1.4, „Vorgabewerte von Datentypen“).

  • DROP INDEX entfernt einen Index. Dies ist eine MySQL-Erweiterung zum SQL-Standard. Siehe auch Abschnitt 13.1.7, „DROP INDEX.

  • Wenn Spalten aus einer Tabelle entfernt werden, werden die Spalten auch aus allen Indizes gelöscht, deren Bestandteil sie sind. Wenn alle Spalten, die einen Index bilden, gelöscht wurden, dann wird auch der Index gelöscht.

  • Enthält eine Tabelle nur eine Spalte, dann kann diese nicht gelöscht werden. Zur Entfernung der Tabelle verwenden Sie stattdessen DROP TABLE.

  • DROP PRIMARY KEY löscht den Primärschlüssel. Hinweis: Bei älteren MySQL-Versionen löscht DROP PRIMARY KEY, wenn kein Primärindex vorhanden ist, den ersten eindeutigen Index in der Tabelle. Dies trifft bei MySQL 5.1 nicht mehr zu: Wenn Sie hier DROP PRIMARY KEY auf eine Tabelle ohne Primärschlüssel anzuwenden versuchen, erhalten Sie einen Fehler.

    Wenn Sie einer Tabelle mit UNIQUE INDEX oder PRIMARY KEY einen eindeutigen Index bzw. einen Primärschlüssel hinzufügen, wird dieser vor jedem nichteindeutigen Index gespeichert, sodass MySQL Schlüsseldubletten schnellstmöglich erkennt.

  • ORDER BY erlaubt Ihnen die Erstellung einer neuen Tabelle mit allen Datensätzen in einer bestimmten Reihenfolge. Beachten Sie, dass diese Reihenfolge nach Einfüge- und Löschoperationen nicht aufrechterhalten wird. Diese Option ist in erster Linie nützlich, wenn Sie wissen, dass die Datensätze meistens in einer bestimmten Reihenfolge abgefragt werden. Wenn Sie diese Option nach umfangreicheren Änderungen in der Tabelle verwenden, können Sie die Leistung unter Umständen steigern. In bestimmten Fällen kann es MySQL das Sortieren erleichtern, wenn die Tabelle in der Reihenfolge der Spalte angeordnet ist, nach der Sie sie später auch sortieren wollen.

  • Wenn Sie ALTER TABLE auf eine MyISAM-Tabelle anwenden, werden alle nichteindeutigen Indizes in einer separaten Stapeloperation erstellt (wie bei REPAIR TABLE). Dies sollte ALTER TABLE erheblich beschleunigen, wenn Sie viele Indizes haben.

    Die Funktion lässt sich explizit aktivieren. ALTER TABLE ... DISABLE KEYS weist MySQL an, die Aktualisierung nichteindeutiger Indizes für eine MyISAM-Tabelle zu beenden. Danach sollte ALTER TABLE ... ENABLE KEYS verwendet werden, um die fehlenden Indizes neu zu erstellen. MySQL tut dies mit einem speziellen Algorithmus, der wesentlich schneller ist als das aufeinander folgende Einfügen von Schlüsseln. Insofern sollte die Deaktivierung von Schlüsseln vor umfangreichen Einfügeoperationen diese erheblich beschleunigen. Die Verwendung von ALTER TABLE ... DISABLE KEYS erfordert neben den bereits genannten Berechtigungen auch die Berechtigung INDEX.

  • Die Klauseln FOREIGN KEY und REFERENCES werden von der InnoDB-Speicher-Engine unterstützt, die ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...) implementiert. Siehe auch Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“. Von anderen Speicher-Engines werden die Klauseln zwar erkannt, aber ignoriert. Zudem wird die Klausel CHECK von allen Speicher-Engines erkannt, aber ignoriert. Siehe auch Abschnitt 13.1.5, „CREATE TABLE. Diese Verhaltensweise – das Erkennen und nachfolgende Ignorieren von Syntaxklauseln – ist aus Kompatibilitätsgründen vorhanden. Sie erleichtert die Portierung von Codes anderer SQL-Server und die Ausführung von Anwendungen, die Tabellen mit Referenzen erstellen. Siehe auch Abschnitt 1.9.5, „MySQL: Unterschiede im Vergleich zu ANSI SQL92“.

    In separaten Klauseln derselben ALTER TABLE-Anweisung können Sie keinen Fremdschlüssel hinzufügen und einen Fremdschlüssel löschen. Sie müssen hierzu separate Anweisungen verwenden.

  • InnoDB unterstützt die Verwendung von ALTER TABLE zum Löschen von Fremdschlüsseln:

    ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;
    

    In separaten Klauseln derselben ALTER TABLE-Anweisung können Sie keinen Fremdschlüssel hinzufügen und einen Fremdschlüssel löschen. Sie müssen hierzu separate Anweisungen verwenden.

    Weitere Informationen finden Sie unter Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.

  • Wenn Sie den Standardzeichensatz einer Tabelle und den Zeichensatz aller Zeichenspalten (CHAR, VARCHAR, TEXT) auf einen neuen Zeichensatz umstellen wollen, verwenden Sie eine Anweisung wie die folgende:

    ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
    

    Warnung: Die obige Operation wandelt Spaltenwerte zwischen Zeichensätzen um. Sie sollten dies keinesfalls tun, wenn Sie eine Spalte in einem Zeichensatz (z. B. latin1) haben, die gespeicherten Werte aber eigentlich einen anderen inkompatiblen Zeichensatz (wie utf8) verwenden. In diesem Fall müssen Sie bei solchen Spalten Folgendes tun:

    ALTER TABLE t1 CHANGE c1 c1 BLOB;
    ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
    

    Der Grund, warum dies funktioniert, ist, dass, wenn Sie von oder in BLOB-Spalten konvertieren, keine Konvertierung stattfindet.

    Wenn Sie CONVERT TO CHARACTER SET binary angeben, werden die CHAR-, VARCHAR- und TEXT-Spalten in ihre entsprechenden binären String-Typen umgewandelt (BINARY, VARBINARY, BLOB). Das bedeutet, dass die Spalten keinen Zeichensatz mehr haben; eine nachfolgende CONVERT TO-Operation hat also keine Auswirkungen mehr.

    Um nur den Standardzeichensatz einer Tabelle zu ändern, verwenden Sie folgende Anweisung:

    ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;
    

    Das Wort DEFAULT ist optional. Der Standardzeichensatz ist der Zeichensatz, der verwendet wird, wenn Sie den Zeichensatz für eine neue Spalte, die Sie (etwa mit ALTER TABLE ... ADD column) zu einer Tabelle hinzufügen, nicht explizit angegeben haben.

  • Bei einer InnoDB-Tabelle, die mit einem eigenen Tablespace in einer .ibd-Datei erstellt wurde, kann diese Datei verworfen und importiert werden. Mit folgender Anweisung können Sie die .ibd-Datei verwerfen:

    ALTER TABLE tbl_name DISCARD TABLESPACE;
    

    Hierbei wird die aktuelle .ibd-Datei gelöscht, d. h., Sie sollten zuerst ein Backup erstellt haben. Der Versuch des Zugriffs auf die Tabelle, während die Tablespace-Datei verworfen wird, führt zu einem Fehler.

    Um die .ibd-Sicherungsdatei in die Tabelle zurückzuimportieren, kopieren Sie sie ins Datenbankverzeichnis und setzen dann folgende Anweisung ab:

    ALTER TABLE tbl_name IMPORT TABLESPACE;
    

    Siehe auch Abschnitt 14.2.3.1, „Verwendung von Tabellen-Tablespaces (ein Tablespace pro Tabelle)“.

  • ALTER TABLE kann auch bei partitionierten Tabellen verwendet werden, um Partitionen hinzuzufügen, zu löschen, zu verbinden oder aufzutrennen. Auch die Partitionierungswartung ist hiermit möglich.

    Die einfache Angabe einer partition_options-Klausel zu ALTER TABLE für eine partitionierte Tabelle partitioniert diese entsprechend dem Partitionierungsschema neu, welches über die partition_options angegeben wurde. Diese Klausel beginnt immer mit PARTITION BY und verwendet ansonsten dieselbe Syntax und die Regeln, die auch auf die partition_options-Klausel für CREATE TABLE zutreffen. (Weitere Informationen finden Sie in Abschnitt 13.1.5, „CREATE TABLE). Hinweis: Diese Syntax wird derzeit vom MySQL 5.1 Server akzeptiert, tut aber eigentlich noch gar nichts. Wir erwarten die Implementierung im Zuge der Fortentwicklung von MySQL 5.1.

    Die partition_definition-Klausel für ALTER TABLE ADD PARTITION unterstützt dieselben Optionen wie die gleichnamige Klausel für die CREATE TABLE-Anweisung. (Informationen zu Syntax und eine Beschreibung finden Sie in Abschnitt 13.1.5, „CREATE TABLE.) Angenommen, Sie haben wie folgt eine partitionierte Tabelle erstellt:

    CREATE TABLE t1 (
        id INT,
        year_col INT
    )
    PARTITION BY RANGE (year_col) (
        PARTITION p0 VALUES LESS THAN (1991),
        PARTITION p1 VALUES LESS THAN (1995),
        PARTITION p2 VALUES LESS THAN (1999)
    );
    

    Sie können dieser Tabelle nun wie folgt eine neue Partition p3 hinzufügen, die Werte aufnehmen kann, die kleiner als 2002 sind.

    ALTER TABLE t1 ADD PARTITION p3 VALUES LESS THAN (2002);
    

    Hinweis: Sie können ALTER TABLE nicht zum Hinzufügen von Partitionen zu einer Tabelle verwenden, die (noch) nicht partitioniert ist.

    Mit DROP PARTITION können Sie eine oder mehrere RANGE- oder LIST-Partitionen löschen. Diese Anweisung kann nicht für HASH- oder KEY-Partitionen verwendet werden; dort benutzen Sie stattdessen COALESCE PARTITION (siehe unten). In gelöschten Partitionen vorhandene Daten, die in der Liste partition_names aufgeführt sind, werden verworfen. So können Sie beispielsweise in der zuvor definierten Tabelle t1 die Partitionen p0 und p1 wie folgt löschen:

    ALTER TABLE DROP PARTITION p0, p1;
    

    Beachten Sie, dass DROP PARTITION nicht bei Tabellen funktioniert, die die NDB Cluster-Speicher-Engine verwenden. Siehe auch Abschnitt 17.3.1, „Verwaltung von RANGE- und LIST-Partitionen“, und Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“.

    ADD PARTITION und DROP PARTITION unterstützen IF [NOT] EXISTS derzeit nicht. Ferner ist es nicht möglich, eine Partition oder eine partitionierte Tabelle umzubenennen. Stattdessen müssen Sie, wenn Sie eine Partition umbenennen wollen, diese löschen und neu erstellen. Wollen Sie eine partitionierte Tabelle umbenennen, dann müssen Sie zunächst alle Partitionen löschen, die Tabelle dann umbenennen und schließlich alle gelöschten Partitionen neu erstellen.

    COALESCE PARTITION kann bei Tabellen benutzt werden, die mit HASH oder KEY partitioniert wurden, um die Anzahl der Partitionen um den Wert number zu verringern. Angenommen, Sie haben die Tabelle t2 mit der folgenden Definition erstellt:

    CREATE TABLE t2 (
        name VARCHAR (30),
        started DATE
    )
    PARTITION BY HASH(YEAR(started))
    PARTITIONS (6);
    

    Sie können die Anzahl der von t2 verwendeten Partitionen nun mit der folgenden Anweisung von 6 auf 4 verringern:

    ALTER TABLE t2 COALESCE PARTITION 2;
    

    Die in den letzten number Partitionen enthaltenen Daten werden in die verbleibenden Partitionen eingefügt. In diesem Fall werden die Partitionen 4 und 5 in die ersten vier Partitionen (0 bis 3) eingefügt.

    Um einige, aber nicht alle Partitionen zu ändern, die von einer partitionierten Tabelle verwendet werden, können Sie REORGANIZE PARTITION verwenden. Diese Anweisung kann auf mehrere Arten verwendet werden:

    • Um mehrere Partitionen zu einer zusammenzufassen. Hierzu zählen Sie mehrere Partitionen in der partition_names-Liste auf und geben genau eine Definition für partition_definition an.

    • Um eine vorhandene Partition in mehrere Partitionen aufzuspalten. Hierzu benennen Sie genau eine Partition für partition_names und geben in partition_definitions mehrere Definitionen an.

    • Um die Bereiche für eine Teilmenge der Partitionen, die mit VALUES LESS THAN definiert wird, oder die Wertelisten für eine Teilmenge der Partitionen zu ändern, die mit VALUES IN definiert wird.

    Hinweis: Bei Partitionen, die nicht explizit aufgeführt wurden, verwendet MySQL automatisch die Standardnamen p0, p1, p2 usw.

    Weitere Informationen zu ALTER TABLE ... REORGANIZE PARTITION-Anweisungen und zugehörige Beispiele finden Sie in Abschnitt 17.3, „Partitionsverwaltung“.

  • Mehrere zusätzliche Klauseln ermöglichen die Wartung und Reparatur von Partitionen analog zu der Art und Weise, wie diese Funktionalitäten bei nicht partitionierten Tabellen durch Anweisungen wie CHECK TABLE und REPAIR TABLE (welche von partitionierten Tabellen nicht unterstützt werden) implementiert sind. Hierzu gehören ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITION und REPAIR PARTITION. Jede dieser Optionen nimmt eine partition_names-Klausel entgegen, die einen oder mehrere durch Kommata getrennte Partitionsnamen umfasst. Die Partitionen müssen in der zu ändernden Tabelle bereits vorhanden sein. Weitere Informationen hierzu und zugehörige Beispiele finden Sie in Abschnitt 17.3.3, „Wartung von Partitionen“.

Mit der C-API-Funktion mysql_info() können Sie ermitteln, wie viele Datensätze kopiert und (sofern IGNORE verwendet wird) aufgrund doppelt vorhandener eindeutiger Schlüsselwerte gelöscht wurden. Siehe auch Abschnitt 24.2.3.34, „mysql_info().

Es folgen ein paar Beispiele, die Anwendungsmöglichkeiten für ALTER TABLE zeigen. Beginnen wir mit einer Tabelle t1, die wie folgt erstellt wird:

CREATE TABLE t1 (a INTEGER,b CHAR(10));

So benennen Sie die Tabelle von t1 in t2 um:

ALTER TABLE t1 RENAME t2;

So ändern Sie den Typ der Spalte a von INTEGER auf TINYINT NOT NULL (wobei der Name erhalten bleibt) und den Typ der Spalte b von CHAR(10) zu CHAR(20) sowie deren Namen von b zu c:

ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

So fügen Sie eine neue TIMESTAMP-Spalte namens d hinzu:

ALTER TABLE t2 ADD d TIMESTAMP;

So fügen Sie Indizes zu den Spalten d und a hinzu:

ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);

So entfernen Sie die Spalte c:

ALTER TABLE t2 DROP COLUMN c;

So fügen Sie eine neue AUTO_INCREMENT-Spalte namens c hinzu:

ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
  ADD PRIMARY KEY (c);

Beachten Sie, dass wir c (als PRIMARY KEY) indiziert haben, weil AUTO_INCREMENT-Spalten indiziert werden müssen, und dass wir außerdem c als NOT NULL deklariert haben, weil Primärschlüsselspalten nicht NULL sein dürfen.

Wenn Sie eine AUTO_INCREMENT-Spalte hinzufügen, werden als Spaltenwerte automatisch Sequenznummern eingetragen. Bei MyISAM-Tabellen können Sie die erste Sequenznummer durch Ausführung von SET INSERT_ID=value vor ALTER TABLE oder durch Verwendung der Tabellenoption AUTO_INCREMENT=value einstellen. Siehe auch Abschnitt 13.5.3, „SET.

Sie können die Tabellenoption ALTER TABLE ... AUTO_INCREMENT=value bei InnoDB-Tabellen zur Einstellung der Sequenznummer für neue Datensätze benutzen, wenn der Wert größer ist als der höchste Wert in der AUTO_INCREMENT-Spalte. Ist der Wert kleiner als der aktuelle Maximalwert der Spalte, dann wird keine Fehlermeldung ausgegeben, und der aktuelle Sequenzwert wird nicht geändert.

Wenn Sie bei MyISAM-Tabellen die AUTO_INCREMENT-Spalte nicht ändern, ist die Sequenznummer nicht betroffen. Wenn Sie eine AUTO_INCREMENT-Spalte löschen und dann eine neue AUTO_INCREMENT-Spalte hinzufügen, beginnen die Sequenznummern wieder bei 1.

Siehe auch Abschnitt A.7.1, „Probleme mit ALTER TABLE.

13.1.3. CREATE DATABASE

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
    [create_specification [, create_specification] ...]

create_specification:
    [DEFAULT] CHARACTER SET charset_name
  | [DEFAULT] COLLATE collation_name

CREATE DATABASE erstellt eine Datenbank des angegebenen Namens. Um CREATE DATABASE verwenden zu können, benötigen Sie die Berechtigung CREATE für die Datenbank. CREATE SCHEMA ist ein Synonym für CREATE DATABASE.

Die Regeln für zulässige Datenbanknamen sind in Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben. Wenn die Datenbank vorhanden ist und Sie IF NOT EXISTS nicht angegeben haben, tritt ein Fehler auf.

create_specification-Optionen geben die Datenbankeigenschaften an. Diese Datenbankeigenschaften sind in der Datei db.opt im Datenbankverzeichnis gespeichert. Die Klausel CHARACTER SET gibt den Standardzeichensatz der Datenbank an. Die Klausel COLLATE gibt die Standardsortierfolge der Datenbank an. Kapitel 10, Zeichensatz-Unterstützung, behandelt Namen von Zeichensätzen und Sortierfolgen.

Datenbanken werden in MySQL als Verzeichnisse implementiert, die Dateien enthalten, welche den Tabellen der Datenbank entsprechen. Weil bei der Erstellung einer Datenbank noch keine Tabellen vorhanden sind, erzeugt die Anweisung CREATE DATABASE lediglich ein Verzeichnis im MySQL-Datenverzeichnis sowie die Datei db.opt.

Wenn Sie manuell (z. B. mit mkdir) ein Verzeichnis im Datenverzeichnis erstellen, betrachtet der Server dieses als Datenbankverzeichnis und zeigt es in der Ausgabe von SHOW DATABASES an.

Sie können zur Erstellung von Datenbanken auch das Programm mysqladmin verwenden. Siehe auch Abschnitt 8.7, „mysqladmin — Client für die Verwaltung eines MySQL Servers“.

13.1.4. CREATE INDEX

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [USING index_type]
    ON tbl_name (index_col_name,...)
    [WITH PARSER parser_name]

index_col_name:
    col_name [(length)] [ASC | DESC]

CREATE INDEX wird mit einer ALTER TABLE-Anweisung verknüpft, um Indizes zu erstellen. Siehe auch Abschnitt 13.1.2, „ALTER TABLE. Weitere Informationen dazu, wie MySQL Indizes verwendet, finden Sie in Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“.

Normalerweise erstellen Sie alle Indizes für eine Tabelle zu dem Zeitpunkt, an dem Sie auch die Tabelle selbst mit CREATE TABLE anlegen. Siehe auch Abschnitt 13.1.5, „CREATE TABLE. CREATE INDEX erlaubt Ihnen das Hinzufügen von Indizes zu vorhandenen Tabellen.

Eine Spaltenliste in der Form (col1,col2,...) erstellt einen mehrspaltigen Index. Indexwerte werden gebildet, indem die Werte der betreffenden Spalten verkettet werden.

Bei CHAR-, VARCHAR-, BINARY- und VARBINARY-Spalten können Indizes erstellt werden, die nur einen Teil einer Spalte verwenden. Hier verwenden Sie die Syntax col_name(length), um die Länge des Indexpräfixes anzugeben. Indexeinträge umfassen dann die ersten length Zeichen jedes Spaltenwerts bei CHAR- und VARCHAR-Spalten sowie die ersten length Bytes jedes Spaltenwerts bei BINARY- und VARBINARY-Spalten. BLOB- und TEXT-Spalten lassen sich auch indizieren, aber eine Präfixlänge muss angegeben werden.

Die folgende Anweisung erstellt einen Index unter Verwendung der ersten zehn Zeichen der Spalte name:

CREATE INDEX part_of_name ON customer (name(10));

Wenn die ersten zehn Zeichen aller Namen in der Spalte sich durchgehend unterscheiden, dann sollte dieser Index nicht viel langsamer sein als ein Index, der aus der gesamten Spalte name erstellt wurde. Auch die Verwendung von Teilspalten für Indizes kann die Indexdatei wesentlich kleiner machen, wodurch sich viel Festplattenspeicher sparen lässt und INSERT-Operationen unter Umständen auch beschleunigt werden können.

Präfixe können bis 1.000 Byte lang sein (767 Byte bei InnoDB-Tabellen). Beachten Sie, dass Präfixbeschränkungen in Byte angegeben werden, wohingegen die Präfixlänge in CREATE INDEX-Anweisungen bei nichtbinären Datentypen (CHAR, VARCHAR, TEXT) als Anzahl der Zeichen interpretiert wird. Dies muss bei der Angabe einer Präfixlänge für eine Spalte berücksichtigt werden, die einen Multibytezeichensatz verwendet.

In MySQL 5.1 können Sie

  • einen Index für eine Spalte, die NULL-Werte enthalten kann, nur dann hinzufügen, wenn Sie die Speicher-Engines MyISAM, InnoDB, BDB oder MEMORY verwenden,

  • einen Index für eine BLOB- oder TEXT-Spalte nur dann hinzufügen, wenn Sie die Speicher-Engines MyISAM, BDB oder InnoDB verwenden.

Eine index_col_name-Definition kann auf ASC oder DESC enden. Diese Schlüsselwörter sind für zukünftige Erweiterungen zulässig, um eine Speicherung der Indexwerte in auf- oder absteigender Reihenfolge festzulegen. Zurzeit werden sie zwar erkannt, aber ignoriert – Indexwerte werden immer in aufsteigender Reihenfolge gespeichert.

Einige Speicher-Engines gestatten bei der Erstellung eines Indexes die Angabe eines Indextyps. Die Syntax für die Konfigurationsangabe index_type lautet USING type_name. Zulässige Werte für type_name, die von den verschiedenen Speicher-Engines unterstützt werden, sind in der folgenden Tabelle aufgelistet. Sind mehrere Indextypen aufgeführt, so wird der erste standardmäßig verwendet, wenn keine Angabe für index_type vorhanden ist.

Speicher-EngineZulässige Indextypen
MyISAMBTREE
InnoDBBTREE
MEMORY/HEAPHASH, BTREE

Ein paar Beispiele:

CREATE TABLE lookup (id INT) ENGINE = MEMORY;
CREATE INDEX id_index USING BTREE ON lookup (id);

TYPE type_name kann als Synonym für USING type_name benutzt werden, um einen Indextyp anzugeben. Allerdings ist USING die bevorzugte Form. Ferner ist der Indexname, der in der Syntax zur Indexspezifikation vor dem Indextyp steht, bei TYPE nicht optional: Anders als USING ist TYPE kein reserviertes Wort und wird infolgedessen nicht als Indexname interpretiert.

Wenn Sie einen Indextyp angeben, der für eine gegebene Speicher-Engine nicht zulässig ist, aber ein anderer Indextyp vorhanden ist, den die Engine verwenden kann, ohne dass hiervon Abfrageergebnisse betroffen wären, dann verwendet die Engine diesen verfügbaren Typ.

FULLTEXT-Indizes werden nur für MyISAM-Tabellen unterstützt und dürfen nur CHAR-, VARCHAR- und TEXT-Spalten enthalten. Siehe auch Abschnitt 12.7, „MySQL-Volltextsuche“. Eine WITH PARSER-Klausel kann angegeben werden, um ein Parser-Plug-In mit dem Index zu verknüpfen, wenn Volltextindizierungs- und Suchoperationen besondere Maßnahmen erfordern. Diese Klausel ist nur für FULLTEXT-Indizes zulässig. Informationen zur Erstellung von Plug-Ins finden Sie in Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.

SPATIAL-Indizes werden nur für MyISAM-Tabellen unterstützt und dürfen nur raumbezogene Spalten enthalten, die als NOT NULL definiert sind. Kapitel 18, Raumbezogene Erweiterungen in MySQL, beschreibt raumbezogene Datentypen.

13.1.5. CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options] [select_statement]

Oder:

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(] LIKE old_tbl_name [)];

create_definition:
    column_definition
  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
  | KEY [index_name] [index_type] (index_col_name,...)
  | INDEX [index_name] [index_type] (index_col_name,...)
  | [CONSTRAINT [symbol]] UNIQUE [INDEX]
        [index_name] [index_type] (index_col_name,...)
  | FULLTEXT [INDEX] [index_name] (index_col_name,...)
      [WITH PARSER parser_name]
  | SPATIAL [INDEX] [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] FOREIGN KEY
        [index_name] (index_col_name,...) [reference_definition]
  | CHECK (expr)

column_definition:
    col_name type [NOT NULL | NULL] [DEFAULT default_value]
        [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
        [COMMENT 'string'] [reference_definition]

type:
    TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  | INT[(length)] [UNSIGNED] [ZEROFILL]
  | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  | DATE
  | TIME
  | TIMESTAMP
  | DATETIME
  | YEAR
  | CHAR(length) [BINARY | ASCII | UNICODE]
  | VARCHAR(length) [BINARY]
  | BINARY(length)
  | VARBINARY(length)
  | TINYBLOB
  | BLOB
  | MEDIUMBLOB
  | LONGBLOB
  | TINYTEXT [BINARY]
  | TEXT [BINARY]
  | MEDIUMTEXT [BINARY]
  | LONGTEXT [BINARY]
  | ENUM(value1,value2,value3,...)
  | SET(value1,value2,value3,...)
  | spatial_type

index_col_name:
    col_name [(length)] [ASC | DESC]

reference_definition:
    REFERENCES tbl_name [(index_col_name,...)]
               [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
               [ON DELETE reference_option]
               [ON UPDATE reference_option]

reference_option:
    RESTRICT | CASCADE | SET NULL | NO ACTION

table_options: table_option [table_option] ...

table_option:
    {ENGINE|TYPE} [=] engine_name
  | AUTO_INCREMENT [=] value
  | AVG_ROW_LENGTH [=] value
  | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
  | CHECKSUM [=] {0 | 1}
  | COMMENT [=] 'string'
  | CONNECTION [=] 'connect_string'
  | MAX_ROWS [=] value
  | MIN_ROWS [=] value
  | PACK_KEYS [=] {0 | 1 | DEFAULT}
  | PASSWORD [=] 'string'
  | DELAY_KEY_WRITE [=] {0 | 1}
  | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
  | UNION [=] (tbl_name[,tbl_name]...)
  | INSERT_METHOD [=] { NO | FIRST | LAST }
  | DATA DIRECTORY [=] 'absolute path to directory'
  | INDEX DIRECTORY [=] 'absolute path to directory'

partition_options:
    PARTITION BY
           [LINEAR] HASH(expr)
        |  [LINEAR] KEY(column_list)
        |  RANGE(expr)
        |  LIST(expr)
    [PARTITIONS num]
    [  SUBPARTITION BY
           [LINEAR] HASH(expr)
         | [LINEAR] KEY(column_list)
      [SUBPARTITIONS num]
    ]
    [(partition_definition) [, (partition_definition)] ...]

partition_definition:
    PARTITION partition_name
        [VALUES {LESS THAN (expr) | MAXVALUE | IN (value_list)}]
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]
        [(subpartition_definition) [, (subpartition_definition)] ...]

subpartition_definition:
    SUBPARTITION logical_name
        [[STORAGE] ENGINE [=] engine-name]
        [COMMENT [=] 'comment_text' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] (tablespace_name)]
        [NODEGROUP [=] node_group_id]

select_statement:
    [IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

CREATE TABLE erstellt eine Tabelle des angegebenen Namens. Für die Tabelle benötigen Sie die Berechtigung CREATE.

Die Regeln für zulässige Tabellennamen sind in Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben. Standardmäßig wird die Tabelle in der Standarddatenbank erstellt. Wenn die Tabelle bereits vorhanden ist oder weder die Standarddatenbank noch die angegebene Datenbank vorhanden sind, wird ein Fehler erstellt.

Der Tabellenname kann als db_name.tbl_name angegeben werden, um die Tabelle in einer bestimmten Datenbank zu erstellen. Das funktioniert unabhängig vom Vorhandensein einer Standarddatenbank, sofern die angegebene Datenbank vorhanden ist. Wenn Sie Bezeichner in Anführungszeichen verwenden, setzen Sie Datenbank- und Tabellennamen separat in Anführungszeichen. So ist etwa `mydb`.`mytbl` zulässig – anders als `mydb.mytbl`.

Sie können das Schlüsselwort TEMPORARY bei der Erstellung einer Tabelle verwenden. Eine TEMPORARY-Tabelle ist nur für die aktuelle Verbindung sichtbar und wird beim Beenden dieser Verbindung automatisch gelöscht. Das bedeutet, dass zwei verschiedene Verbindungen Temporärtabellen desselben Namens verwenden können, ohne dass es zu Konflikten mit der jeweils anderen Tabelle oder einer nichttemporären Tabelle gleichen Namens kommt. (Die vorhandene Tabelle wird verborgen, bis die Temporärtabelle gelöscht wird.) Zur Erstellung von Temporärtabellen benötigen Sie die Berechtigung CREATE TEMPORARY TABLES.

Die Schlüsselwörter IF NOT EXISTS verhindern, dass ein Fehler auftritt, wenn die Tabelle vorhanden ist. Allerdings wird nicht überprüft, ob die vorhandene Tabelle die gleiche Struktur wie die in der CREATE TABLE-Anweisung angegebene Tabelle hat. Hinweis: Wenn Sie IF NOT EXISTS in einer CREATE TABLE ... SELECT-Anweisung verwenden, werden alle durch den SELECT-Teil gewählten Datensätze ohne Berücksichtigung der Frage eingefügt, ob die Tabelle bereits vorhanden ist.

MySQL stellt jede Tabelle durch eine .frm-Tabellenformatdatei (Definitionsdatei) im Datenbankverzeichnis dar. Die Speicher-Engine der Tabelle erstellt unter Umständen auch andere Dateien. Im Falle von MyISAM-Tabellen erstellt die Speicher-Engine Daten- und Indexdateien. Es gibt also für jede MyISAM-Tabelle tbl_name drei Dateien auf der Festplatte:

DateiZweck
tbl_name.frmTabellenformatdatei (Definitionsdatei)
tbl_name.MYDDatendatei
tbl_name.MYIIndexdatei

Kapitel 14, Speicher-Engines und Tabellentypen, beschreibt, welche Dateien die einzelnen Speicher-Engines zur Darstellung von Tabellen erstellen.

type stellt den Datentyp einer Spaltendefinition dar. spatial_type ist ein raumbezogener Datentyp. Allgemeine Informationen zu den Eigenschaften von Datentypen (außer raumbezogenen Datentypen) finden Sie in Kapitel 11, Datentypen. Informationen zu raumbezogenen Datentypen finden Sie in Kapitel 18, Raumbezogene Erweiterungen in MySQL.

  • Wenn weder NULL noch NOT NULL angegeben sind, wird die Spalte so behandelt, als ob NULL angegeben worden wäre.

  • Eine Integer-Spalte kann das Zusatzattribut AUTO_INCREMENT erhalten. Wenn Sie den Wert NULL (empfohlen) oder 0 in eine indizierte AUTO_INCREMENT-Spalte einfügen, wird die Spalte auf den nächsten Sequenzwert gesetzt. Normalerweise ist dies value+1, wobei value der derzeit größte Wert der Spalte in der Tabelle ist. AUTO_INCREMENT-Sequenzen beginnen bei 1.

    Um einen AUTO_INCREMENT-Wert nach Einfügen eines Datensatzes abzurufen, verwenden Sie die SQL-Funktion LAST_INSERT_ID() oder die C-API-Funktion mysql_insert_id(). Siehe auch Abschnitt 12.10.3, „Informationsfunktionen“, und Abschnitt 24.2.3.36, „mysql_insert_id().

    Wenn der SQL-Modus NO_AUTO_VALUE_ON_ZERO aktiviert ist, können Sie 0 in AUTO_INCREMENT-Spalten als 0 speichern, ohne einen neuen Sequenzwert zu erzeugen. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.

    Hinweis: Es kann nur eine AUTO_INCREMENT-Spalte pro Tabelle geben. Diese muss indiziert sein und darf keinen Standardwert haben. Eine AUTO_INCREMENT-Spalte funktioniert nur dann einwandfrei, wenn sie ausschließlich positive Werte enthält. Das Einfügen eines negativen Werts wird als Einfügen einer sehr großen positiven Zahl aufgefasst. Dies wird gemacht, um genauigkeitsspezifische Probleme zu vermeiden, die beim „Umklappen“ von positiven auf negative Zahlen auftreten können, und um zu gewährleisten, dass Sie nicht versehentlich eine AUTO_INCREMENT-Spalte erhalten, die 0 enthält.

    Bei MyISAM- und BDB-Tabellen können Sie AUTO_INCREMENT in einer Sekundärspalte eines mehrspaltigen Schlüssels angeben. Siehe auch Abschnitt 3.6.9, „Verwendung von AUTO_INCREMENT.

    Um MySQL mit einigen ODBC-Anwendungen kompatibel zu machen, können Sie den AUTO_INCREMENT-Wert für den letzten eingefügten Datensatz mit der folgenden Abfrage ermitteln:

    SELECT * FROM tbl_name WHERE auto_col IS NULL
    
  • Das Attribut SERIAL kann als Alias für BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE verwendet werden.

  • Zeichendatentypen (CHAR, VARCHAR, TEXT) können CHARACTER SET- und COLLATE-Attribute zur Angabe von Zeichensatz und Sortierfolge der Spalte enthalten. Weitere Informationen finden Sie in Kapitel 10, Zeichensatz-Unterstützung. CHARSET ist ein Synonym für CHARACTER SET. Beispiel:

    CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);
    

    MySQL 5.1 interpretiert Längenangaben in Zeichenspaltendefinitionen als Anzahl von Zeichen. (Versionen vor MySQL 4.1 interpretierten sie als Anzahl von Bytes.)

  • Die DEFAULT-Klausel gibt einen Vorgabewert für eine Spalte an. Mit einer Ausnahme muss der Vorgabewert immer eine Konstante sein. Funktionen oder Ausdrücke sind als Vorgabe nicht zulässig. Das bedeutet, dass Sie beispielsweise als Vorgabewert einer Datumsspalte nicht den Wert einer Funktion wie NOW() oder CURRENT_DATE angeben dürfen. Die genannte Ausnahme besteht darin, dass Sie CURRENT_TIMESTAMP als Vorgabe für eine TIMESTAMP-Spalte festlegen können. Siehe auch Abschnitt 11.3.1.1, „TIMESTAMP-Eigenschaften ab MySQL 4.1“.

    Wenn eine Spaltendefinition keinen expliziten DEFAULT-Wert enthält, bestimmt MySQL diesen wie in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben.

    Für BLOB- und TEXT-Spalten können keine Vorgaben festgelegt werden.

  • Ein Kommentar für eine Spalte kann mit der Option COMMENT angegeben werden. Der Kommentar wird über die Anweisungen SHOW CREATE TABLE und SHOW FULL COLUMNS angezeigt.

  • KEY ist normalerweise ein Synonym für INDEX. Das Schlüsselattribut PRIMARY KEY kann auch einfach als KEY angegeben werden, sofern die Angabe in einer Spaltendefinition erfolgt. Dieses Verhalten wurde aus Gründen der Kompatibilität mit anderen Datenbanksystemen implementiert.

  • Ein eindeutiger Index ist dahingehend eingeschränkt, dass alle Werte im Index eindeutig sein müssen. Wenn Sie einen neuen Datensatz mit einem Schlüssel hinzufügen, der dem eines vorhandenen Datensatzes entspricht, tritt ein Fehler auf. Eine Ausnahme hierzu besteht darin, dass, wenn eine Spalte im Index NULL-Werte enthalten darf, diese mehrere NULL-Werte enthalten kann. Diese Ausnahme gilt jedoch nicht für BDB-Tabellen, bei denen eine Spalte mit einem eindeutigen Index NULL nur einmalig gestattet.

  • Ein Primärschlüssel ist ein eindeutiger Index, bei dem alle Schlüsselspalten als NOT NULL definiert sein müssen. Wenn sie nicht explizit als NOT NULL deklariert sind, holt MySQL dies implizit (und stillschweigend) nach. Eine Tabelle darf nur einen Primärschlüssel enthalten. Wenn Sie keinen Primärschlüssel haben und eine Anwendung nach dem Primärschlüssel in Ihren Tabellen fragt, gibt MySQL als Primärschlüssel den ersten eindeutigen Index zurück, der keine NULL-Spalten verwendet.

  • In der erstellten Tabelle wird der Primärschlüssel an die erste Position gesetzt, gefolgt von allen eindeutigen Indizes und nachfolgend den nichteindeutigen Indizes. Dies erleichtert dem MySQL-Optimierer die Priorisierung der zu verwendenden Indizes und die schnelle Erkennung von Dubletten bei den UNIQUE-Schlüsseln.

  • Ein Primärschlüssel kann ein mehrspaltiger Index sein. Sie können allerdings keinen mehrspaltigen Index mithilfe des Schlüsselattributs PRIMARY KEY in einer Spaltendefinition erstellen. Wenn Sie dies tun, wird nur diese eine Spalte als Primärschlüssel gekennzeichnet. Sie müssen hierzu eine separate PRIMARY KEY(index_col_name, ...)-Klausel verwenden.

  • Wenn ein Primärschlüssel oder ein eindeutiger Index aus nur einer Spalte eines Integer-Typs bestehen, können Sie die Spalte auch in SELECT-Anweisungen als _rowid referenzieren.

  • In MySQL lautet der Name eines Primärschlüssels PRIMARY. Bei anderen Indizes erhält, sofern Sie keinen Namen angeben, der Index jeweils denselben Namen wie die erste indizierte Spalte. Es kann optional ein Suffix (_2, _3, ...) angegeben werden, um den Index eindeutig zu machen. Sie können die Indexnamen für eine Tabelle mit SHOW INDEX FROM tbl_name anzeigen. Siehe auch Abschnitt 13.5.4.12, „SHOW INDEX.

  • Einige Speicher-Engines gestatten bei der Erstellung eines Indexes die Angabe eines Indextyps. Die Syntax für die Konfigurationsangabe index_type lautet USING type_name.

    Beispiel:

    CREATE TABLE lookup
      (id INT, INDEX USING BTREE (id))
      ENGINE = MEMORY;
    

    Detaillierte Informationen zu USING finden Sie in Abschnitt 13.1.4, „CREATE INDEX.

    Weitere Informationen dazu, wie MySQL Indizes verwendet, finden Sie in Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“.

  • In MySQL 5.1 unterstützen nur die Speicher-Engines MyISAM, InnoDB, BDB und MEMORY Indizes bei Spalten, die NULL-Werte enthalten. In anderen Fällen müssen Sie indizierte Spalten als NOT NULL deklarieren, andernfalls wird ein Fehler zurückgegeben.

  • Mit der Syntax col_name(length) in einer Indexdefinition können Sie einen Index erstellen, der die Spalte nur teilweise verwendet. Indexeinträge umfassen die ersten length Zeichen jedes Spaltenwerts bei CHAR- und VARCHAR-Spalten sowie die ersten length Bytes jedes Spaltenwerts bei BINARY- und VARBINARY-Spalten. Wenn Sie auf diese Weise nur ein Präfix der Spaltenwerte indizieren, kann dies die Indexdatei erheblich kleiner machen. Siehe auch Abschnitt 7.4.3, „Spaltenindizes“.

    Die Speicher-Engines MyISAM, BDB und InnoDB unterstützen die Indizierung von BLOB- und TEXT-Spalten. Bei der Indizierung einer BLOB- oder TEXT-Spalte müssen Sie eine Präfixlänge für den Index angeben. Zum Beispiel:

    CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
    

    Präfixe können bis 1.000 Byte lang sein (767 Byte bei InnoDB-Tabellen). Beachten Sie, dass Präfixbeschränkungen in Byte angegeben werden, wohingegen die Präfixlänge in CREATE TABLE-Anweisungen bei nichtbinären Datentypen (CHAR, VARCHAR, TEXT) als Anzahl der Zeichen interpretiert wird. Dies muss bei der Angabe einer Präfixlänge für eine Spalte berücksichtigt werden, die einen Multibytezeichensatz verwendet.

  • Eine index_col_name-Definition kann auf ASC oder DESC enden. Diese Schlüsselwörter sind für zukünftige Erweiterungen zulässig, um eine Speicherung der Indexwerte in auf- oder absteigender Reihenfolge festzulegen. Zurzeit werden sie zwar erkannt, aber ignoriert – Indexwerte werden immer in aufsteigender Reihenfolge gespeichert.

  • Wenn Sie ORDER BY oder GROUP BY für eine TEXT- oder BLOB-Spalte in einer SELECT-Anweisung verwenden, sortiert der Server Werte lediglich unter Verwendung der ersten Bytes. Wie viele Bytes dies sind, wird von der Systemvariablen max_sort_length angegeben. Siehe auch Abschnitt 11.4.3, „Die Spaltentypen BLOB und TEXT.

  • Sie können spezielle Volltextindizes erstellen, die für die Volltextsuche verwendet werden. Nur die MyISAM-Speicher-Engine unterstützt Volltextindizes. Diese können nur aus CHAR-, VARCHAR- und TEXT-Spalten erstellt werden. Die Indizierung erfolgt immer über die gesamte Spalte: Eine Teilindizierung wird nicht unterstützt, und ein eventuell angegebenes Präfix wird ignoriert. Weitere Informationen finden Sie in Abschnitt 12.7, „MySQL-Volltextsuche“. Eine WITH PARSER-Klausel kann angegeben werden, um ein Parser-Plug-In mit dem Index zu verknüpfen, wenn Volltextindizierungs- und Suchoperationen besondere Maßnahmen erfordern. Diese Klausel ist nur für FULLTEXT-Indizes zulässig. Informationen zur Erstellung von Plug-Ins finden Sie in Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.

  • SPATIAL-Indizes können Sie für raumbezogene Typen erstellen. Solche Typen werden nur für MyISAM-Tabellen unterstützt, und indizierte Spalten müssen als NOT NULL deklariert sein. Siehe auch Kapitel 18, Raumbezogene Erweiterungen in MySQL.

  • InnoDB-Tabellen unterstützen die Überprüfung von Fremdschlüssel-Constraints. Siehe auch Abschnitt 14.2, „InnoDB-Tabellen“. Beachten Sie, dass die Fremdschlüsselsyntax in InnoDB restriktiver ist als die zu Beginn dieses Abschnitts für die CREATE TABLE-Anweisung präsentierte Syntax: Die Spalten der referenzierten Tabellen müssen immer explizit genannt werden. InnoDB unterstützt sowohl ON DELETE- als auch ON UPDATE-Aktionen für Fremdschlüssel. Informationen zur exakten Syntax finden Sie in Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.

    Bei anderen Speicher-Engines erkennt MySQL Server die FOREIGN KEY- und REFERENCES-Syntax in CREATE TABLE-Anweisungen, ignoriert sie aber. Zudem wird die Klausel CHECK von allen Speicher-Engines erkannt, aber ignoriert. Siehe auch Abschnitt 1.9.5.5, „Fremdschlüssel“.

  • Bei MyISAM-Tabellen benötigt jede NULL-Spalte ein zusätzliches Bit, aufgerundet auf das nächste Byte. Die maximale Datensatzlänge in Byte kann wie folgt berechnet werden:

    row length = 1
                 + (sum of column lengths)
                 + (number of NULL columns + delete_flag + 7)/8
                 + (number of variable-length columns)
    

    delete_flag ist 1 bei Tabellen mit statischem Datensatzformat. Statische Tabellen verwenden ein Bit im Datensatz für ein Flag, das angibt, ob der Datensatz gelöscht wurde. delete_flag ist 0 bei dynamischen Tabellen, weil das Flag im dynamischen Datensatz-Header gespeichert wird.

    Diese Berechnungen gelten nicht für InnoDB-Tabellen, bei denen der Speicherbedarf von NULL-Spalten sich nicht von dem von NOT NULL-Spalten unterscheidet.

Die Tabellenoption ENGINE gibt die Speicher-Engine für die Tabelle an. TYPE ist ein Synonym hierzu, wobei ENGINE der bevorzugte Name ist.

Die Tabellenoption ENGINE akzeptiert die in der folgenden Tabelle aufgeführten Namen für Speicher-Engines.

Speicher-EngineBeschreibung
ARCHIVESpeicher-Engine zur Archivierung. Siehe auch Abschnitt 14.8, „Die ARCHIVE-Speicher-Engine“.
BDBTransaktionssichere Tabellen mit Seitensperrung. Heißt auch BerkeleyDB. Siehe auch Abschnitt 14.5, „Die BDB-Speicher-Engine“.
CSVTabellen, die Datensätze als kommagetrennte Werte speichern. Siehe auch Abschnitt 14.9, „Die CSV-Speicher-Engine“.
EXAMPLEEine Beispiel-Engine. Siehe auch Abschnitt 14.6, „Die EXAMPLE-Speicher-Engine“.
FEDERATEDSpeicher-Engine, die auf entfernte Tabellen zugreift. Siehe auch Abschnitt 14.7, „Die FEDERATED-Speicher-Engine“.
HEAPEin Synonym für MEMORY.
ISAM (VERALTET)In MySQL 5.1 nicht verfügbar. Wenn Sie von einer älteren Version auf MySQL 5.1 aktualisieren, sollten Sie alle vorhandenen ISAM-Tabellen in MyISAM-Tabellen konvertieren, bevor Sie das Upgrade durchführen.
InnoDBTransaktionssichere Tabellen mit Datensatzsperrung und Fremdschlüsseln. Siehe auch Abschnitt 14.2, „InnoDB-Tabellen“.
MEMORYDie Daten für diese Speicher-Engine werden nur im Speicher abgelegt. Siehe auch Abschnitt 14.4, „Die MEMORY-Speicher-Engine“.
MERGEEine Sammlung von MyISAM-Tabellen, die als eine Tabelle verwendet wird. Heißt auch MRG_MyISAM. Siehe auch Abschnitt 14.3, „Die MERGE-Speicher-Engine“.
MyISAMBinäre portable Speicher-Engine, die als Standard-Engine in MySQL verwendet wird. Siehe auch Abschnitt 14.1, „Die MyISAM-Speicher-Engine“.
NDBCLUSTERFehlertolerante, speicherbasierte Cluster-Tabellen. Heißt auch NDB. Siehe auch Kapitel 16, MySQL Cluster.

Wird eine Speicher-Engine angegeben, die nicht verfügbar ist, dann verwendet MySQL stattdessen die Standard-Engine. Im Normalfall ist dies MyISAM. Wenn beispielsweise eine Tabellendefinition die Option ENGINE=BDB enthält, aber der MySQL Server BDB-Tabellen nicht unterstützt, dann wird die Tabelle als MyISAM-Tabelle erstellt. Auf diese Weise ist eine Replikationskonfiguration realisierbar, bei der Sie transaktionssichere Tabellen auf dem Master haben, während die auf dem Slave erstellten Tabellen nicht transaktionssicher sind (was eine Erhöhung der Verarbeitungsgeschwindigkeit nach sich zieht). In MySQL 5.1 erscheint eine Warnung, wenn die Spezifikation der Speicher-Engine nicht berücksichtigt werden kann.

Die übrigen Tabellenoptionen werden zur Optimierung des Verhaltens der Tabelle verwendet. In den meisten Fällen müssen Sie sie überhaupt nicht angeben. Diese Optionen gelten für alle Speicher-Engines, soweit nichts anderes angegeben ist:

  • AUTO_INCREMENT

    Der AUTO_INCREMENT-Startwert für die Tabelle. In MySQL 5.1 funktioniert dies bei MyISAM-, MEMORY- und InnoDB-Tabellen. Um den ersten AUTO_INCREMENT-Wert für Engines zu setzen, die die Tabellenoption AUTO_INCREMENT nicht unterstützen, fügen Sie einen „Pseudodatensatz“ mit einem Wert ein, der um 1 niedriger ist als der gewünschte Startwert. Nach der Erstellung der Tabelle löschen Sie den Pseudodatensatz dann.

    Bei Engines, die die Tabellenoption AUTO_INCREMENT in CREATE TABLE-Anweisungen unterstützen, können Sie auch ALTER TABLE tbl_name AUTO_INCREMENT = N verwenden, um den AUTO_INCREMENT-Wert zurückzusetzen.

  • AVG_ROW_LENGTH

    Ein Näherungswert für die durchschnittliche Datensatzlänge in Ihrer Tabelle. Sie müssen die Einstellung nur bei großen Tabellen mit Datensätzen unterschiedlicher Größe vornehmen.

    Wenn Sie eine MyISAM-Tabelle erstellen, verwendet MySQL das Produkt der Optionen MAX_ROWS und AVG_ROW_LENGTH, um zu ermitteln, wie groß die resultierende Tabelle sein wird. Geben Sie keine der Optionen an, dann beträgt die maximale Tabellengröße 65.536 Tbyte Daten. (Wenn Ihr Betriebssystem derart große Dateien nicht unterstützt, wird die maximale Größe einer Tabelle durch die betriebssystemseitige Beschränkung der Dateigröße bestimmt.) Wenn Sie die Zeigergrößen gering halten wollen, damit der Index kleiner und schneller wird, und Sie eigentlich keine großen Dateien benötigen, können Sie die Standardzeigergröße durch Einstellen der Systemvariablen myisam_data_pointer_size verringern. (Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“.) Wenn Sie wollen, dass alle Ihre Tabellen über das standardmäßige Limit hinaus anwachsen können, und dafür in Kauf nehmen, dass die Tabellen etwas größer und langsamer sind als notwendig, dann können Sie die Standardzeigergröße durch Einstellen der Variablen auch erhöhen.

  • [DEFAULT] CHARACTER SET

    Gibt einen Standardzeichensatz für die Tabelle an. CHARSET ist ein Synonym für CHARACTER SET.

  • COLLATE

    Gibt eine Standardsortierfolge für die Tabelle an.

  • CHECKSUM

    Setzen Sie diese Option auf 1, wenn Sie wollen, dass MySQL eine Prüfsumme für alle Datensätze erstellt, die zudem bei Änderungen in der Tabelle automatisch aktualisiert wird. Dies macht die Aktualisierung der Tabelle zwar ein wenig langsamer, erleichtert aber das Auffinden beschädigter Tabellen. Die Anweisung CHECKSUM TABLE meldet die Prüfsumme. (Nur für MyISAM.)

  • COMMENT

    Ein Kommentar für die Tabelle, der bis zu 60 Zeichen lang sein kann.

  • CONNECTION

    Der Verbindungs-String für eine FEDERATED-Tabelle. (Hinweis: Ältere Versionen von MySQL verwendeten eine Option COMMENT für den Verbindungs-String.)

  • MAX_ROWS

    Maximale Anzahl der Datensätze, die Sie in der Tabelle zu speichern beabsichtigen. Dies ist keine feste Beschränkung, sondern ein Indikator für die Anzahl der Datensätze, die die Tabelle zumindest speichern können muss.

  • MIN_ROWS

    Minimale Anzahl der Datensätze, die Sie in der Tabelle zu speichern beabsichtigen.

  • PACK_KEYS

    Setzen Sie diese Option auf 1, wenn Sie kleinere Indizes wünschen. Hierdurch werden Updates in der Regel langsamer und Leseoperationen schneller. Wenn Sie die Option auf 0 setzen, wird das Packen für alle Schlüssel deaktiviert. Setzen Sie sie hingegen auf DEFAULT, dann wird die Speicher-Engine angewiesen, nur lange CHAR- und VARCHAR-Spalten zu packen. (Nur für MyISAM.)

    Wenn Sie PACK_KEYS nicht verwenden, werden standardmäßig Strings, aber nicht Zahlen gepackt. Bei PACK_KEYS=1 werden auch Zahlen gepackt.

    Beim Packen von binären Zahlenschlüsseln verwendet MySQL die Präfixkompression:

    • Jeder Schlüssel benötigt ein zusätzliches Byte, um anzugeben, wie viele Bytes des vorherigen Schlüssels beim nachfolgenden Schlüssel identisch sind.

    • Der Zeiger auf den Datensatz wird direkt auf den Schlüssel folgend und in absteigender Reihenfolge der Bytewertigkeit gespeichert, um die Komprimierung zu optimieren.

    Das bedeutet, dass, wenn Sie viele gleiche Schlüssel in zwei aufeinander folgenden Datensätzen haben, alle nachfolgenden „identischen“ Schlüssel einschließlich des Zeigers auf den Datensatz nur 2 Byte benötigen. Vergleichen Sie dies einmal mit dem normalen Fall, in dem die nachfolgenden Schlüssel storage_size_for_key + pointer_size Bytes benötigen (wobei die Zeigergröße normalerweise 4 beträgt). Umgekehrt können Sie nur dann umfassend von der Präfixkomprimierung profitieren, wenn Sie viele identische Zahlen haben. Wenn alle Schlüssel vollständig unterschiedlich sind, verwenden Sie pro Schlüssel ein Byte mehr, wenn der jeweilige Schlüssel keine NULL-Werte haben kann. (In diesem Fall wird die Länge des gepackten Schlüssels im selben Byte gespeichert, das zur Kennzeichnung verwendet wird, wenn ein Schlüssel NULL ist.)

  • PASSWORD

    Verschlüsselt die .frm-Datei mit einem Passwort. In der MySQL-Standardversion tut die Option nichts.

  • DELAY_KEY_WRITE

    Setzen Sie diese Option auf 1, wenn Sie Schlüssel-Updates für die Tabelle auf einen Zeitpunkt verschieben wollen, an dem die Tabelle geschlossen ist. Details finden Sie in der Beschreibung zur Systemvariablen delay_key_write in Abschnitt 5.2.2, „Server-Systemvariablen“. (Nur für MyISAM.)

  • ROW_FORMAT

    Definiert, wie die Datensätze gespeichert werden sollen. Bei MyISAM-Tabellen kann der Optionswert FIXED oder DYNAMIC für das statische wie auch das variabel lange Datensatzformat sein. myisampack setzt den Typ auf COMPRESSED. Siehe auch Abschnitt 14.1.3, „MyISAM-Tabellenformate“.

    Bei InnoDB-Tabellen werden die Datensätze standardmäßig im kompakten Format (ROW_FORMAT=COMPACT) gespeichert. Das nichtkompakte Format, welches in älteren MySQL-Versionen verwendet wurde, kann noch über die Angabe von ROW_FORMAT=REDUNDANT angefordert werden.

  • RAID_TYPE

    Die RAID-Unterstützung wurde ab MySQL 5.0 entfernt. Informationen zu RAID finden Sie online im MySQL-4.1-Handbuch unter http://dev.mysql.com/doc/refman/4.1/en/create-table.html.

  • UNION

    UNION wird verwendet, wenn Sie auf eine ganze Sammlung identischer MyISAM-Tabellen zugreifen wollen. Dies funktioniert nur bei MERGE-Tabellen. Siehe auch Abschnitt 14.3, „Die MERGE-Speicher-Engine“.

    Sie benötigen die Berechtigungen SELECT, UPDATE und DELETE für die Tabellen, um die Sammlung einer MERGE zuordnen zu können. (Hinweis: Ursprünglich mussten alle verwendeten Tabellen sich in der gleichen Datenbank wie die MERGE-Tabelle selbst befinden. Diese Einschränkung trifft nicht mehr zu.)

  • INSERT_METHOD

    Wenn Sie Daten in eine MERGE-Tabelle einfügen wollen, müssen Sie mit INSERT_METHOD die Tabelle festlegen, in die der Datensatz einzufügen ist. Die Option INSERT_METHOD ist nur für MERGE-Tabellen sinnvoll. Verwenden Sie die Werte FIRST oder LAST, um die Einfügung in die erste bzw. letzte Tabelle vorzunehmen, oder NO, um Einfügeoperationen ganz auszuschließen. Siehe auch Abschnitt 14.3, „Die MERGE-Speicher-Engine“.

  • DATA DIRECTORY, INDEX DIRECTORY

    Mithilfe von DATA DIRECTORY='directory' oder INDEX DIRECTORY='directory' können Sie angeben, wo die MyISAM-Speicher-Engine die Daten- und Indexdatei einer Tabelle ablegen soll. directory muss als vollständiger Pfadname zum Verzeichnis angegeben werden; relative Pfade sind nicht möglich.

    Diese Optionen funktionieren nur, wenn Sie die Option --skip-symbolic-links nicht verwenden. Außerdem muss Ihr Betriebssystem über einen funktionsfähigen und Thread-sicheren realpath()-Aufruf verfügen. Weitere Informationen finden Sie in Abschnitt 7.6.1.2, „Benutzung symbolischer Links für Tabellen“.

  • Partitionierungsoptionen (partition_options) können zur Steuerung der Partitionierung einer Tabelle benutzt werden, die mit CREATE TABLE erstellt wurde. Sofern angegeben, muss mindestens eine PARTITION BY-Klausel enthalten sein. Diese Klausel enthält die Funktion, die zur Bestimmung der Partition verwendet wird. Die Funktion gibt einen ganzzahligen Wert zwischen 1 und num zurück, wobei num die Gesamtzahl der Partitionen ist. Die nachfolgende Liste zeigt die Auswahlmöglichkeiten für diese Funktion in MySQL 5.1.

    Wichtig: Nicht alle zu Beginn dieses Abschnitts in der Syntax für partition_options aufgeführten Optionen stehen für alle Partitionierungstypen zur Verfügung. Entnehmen Sie den Listings für die jeweiligen Typen die passenden Informationen. Weitere Informationen zu Wirkungsweise und Anwendungsmöglichkeiten der Partitionierung in MySQL sowie zusätzliche Beispiele zur Tabellenerstellung und zu anderen partitionierungsbezogenen Anweisungen in MySQL finden Sie in Kapitel 17, Partitionierung.

    • HASH(expr): Führt ein Hashing einer oder mehrerer Spalten aus, um einen Schlüssel zum Platzieren und Wiederauffinden von Datensätzen zu erstellen. expr ist ein Ausdruck, der eine oder mehrere Tabellenspalten verwendet. Dabei kann es sich um einen zulässigen MySQL-Ausdruck (einschließlich MySQL-Funktionen) handeln, der genau einen Integer-Wert ausgibt. Die nachfolgenden CREATE TABLE-Anweisungen mit PARTITION BY HASH-Option etwa sind alle zulässig:

      CREATE TABLE t1 (col1 INT, col2 CHAR(5))
          PARTITION BY HASH(col1);
      
      CREATE TABLE t1 (col1 INT, col2 CHAR(5))
          PARTITION BY HASH( ORD(col2) );
      
      CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
          PARTITION BY HASH ( YEAR(col3) );
      

      VALUES LESS THAN- und VALUES IN-Klauseln dürfen nicht mit PARTITION BY HASH gemeinsam eingesetzt werden.

      PARTITION BY HASH verwendet den Rest des Ausdrucks expr geteilt durch die Anzahl der Partitionen (d. h. den Modulo). Beispiele und Informationen finden Sie in Abschnitt 17.2.3, „HASH-Partitionierung“.

      Das Schlüsselwort LINEAR bringt einen etwas anderen Algorithmus mit sich. In diesem Fall wird die Nummer der Partition, auf der ein Datensatz gespeichert ist, als Ergebnis einer oder mehrerer logischer AND-Operationen ermittelt. Eine Beschreibung und Beispiele für das lineare Hashing finden Sie in Abschnitt 17.2.3.1, „LINEAR HASH-Partitionierung“.

    • KEY(column_list): Dies ähnelt HASH, nur wird die Hashing-Funktion hier von MySQL selbst bereitgestellt, um eine gleichmäßige Datenverteilung zu gewährleisten. Das Argument column_list ist eine einfache Liste mit Tabellenspalten. Dieses Beispiel zeigt eine einfache, durch einen Schlüssel partitionierte Tabelle mit vier Partitionen:

      CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
          PARTITION BY KEY(col3)
          PARTITIONS 4;
      

      Bei Tabellen, die durch einen Schlüssel partitioniert sind, können Sie die lineare Partitionierung durch Angabe des Schlüsselworts LINEAR benutzen. Dies hat die gleichen Auswirkungen wie bei Tabellen, die mit HASH partitioniert wurden: Die Partitionsnummer wird mithilfe des Operators & statt über den Modulo ermittelt (siehe auch Abschnitt 17.2.3.1, „LINEAR HASH-Partitionierung“, und Abschnitt 17.2.4, „KEY-Partitionierung“). Dieses Beispiel verwendet die lineare Partitionierung über einen Schlüssel, um Daten auf fünf Partitionen zu verteilen:

      CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
          PARTITION BY LINEAR KEY(col3)
          PARTITIONS 5;
      

      VALUES LESS THAN- und VALUES IN-Klauseln dürfen nicht mit PARTITION BY KEY gemeinsam eingesetzt werden.

    • RANGE: In diesem Fall zeigt expr unter Verwendung einer Menge von VALUES LESS THAN-Operatoren einen Wertebereich an. Wenn Sie die Bereichspartitionierung verwenden, müssen Sie mindestens eine Partition mit VALUES LESS THAN angeben. VALUES IN können Sie bei der Bereichspartitionierung nicht einsetzen.

      VALUES LESS THAN kann entweder mit einem literalen Wert oder einem Ausdruck benutzt werden, der genau einen Wert zurückgibt.

      Angenommen, Sie haben eine Tabelle, die Sie nach einer Spalte partitionieren wollen, die Jahreswerte enthält. Hierbei wollen Sie das folgende Schema verwenden:

      Partitionsnummer:Jahre
      01990 und früher
      11991–1994
      21995–1998
      31999–2002
      42003–2005
      52006 und später

      Eine Tabelle, die dieses Partitionierungsschema implementiert, kann mit der folgenden CREATE TABLE-Anweisung erstellt werden:

      CREATE TABLE t1 (
          year_col  INT,
          some_data INT
      )
      PARTITION BY RANGE (year_col) (
          PARTITION p0 VALUES LESS THAN (1991),
          PARTITION p1 VALUES LESS THAN (1995),
          PARTITION p2 VALUES LESS THAN (1999),
          PARTITION p3 VALUES LESS THAN (2002),
          PARTITION p4 VALUES LESS THAN (2006),
          PARTITION p5 VALUES LESS THAN MAXVALUE
      );
      

      PARTITION ... VALUES LESS THAN ...-Anweisungen arbeiten konsekutiv, d. h., VALUES LESS THAN MAXVALUE verarbeitet die „übrig gebliebenen“ Werte, die größer sind als der anderweitig angegebene Maximalwert.

      Beachten Sie, dass VALUES LESS THAN-Klauseln sequenziell auf eine Weise verarbeitet werden, die der von case-Abschnitten eines switch ... case-Blocks ähnelt, wie man sie aus vielen Programmiersprachen wie C, Java oder PHP her kennt: Die Klauseln müssen so angeordnet sein, dass der obere Grenzwert einer nachfolgenden VALUES LESS THAN-Klausel größer ist als der der vorherigen Klausel; dabei muss MAXVALUE als Letztes in der Liste erscheinen.

    • LIST(expr): Dies ist praktisch, wenn man Partitionen basierend auf einer Tabellenspalte mit einer beschränkten Menge möglicher Werte (z. B. Land, PLZ usw.) konfiguriert. In einem solchen Fall lassen sich alle Datensätze, die einem bestimmten Land oder einer PLZ zuzuordnen sind, derselben Partition zuweisen, oder eine Partition kann für bestimmte Länder oder Postleitzahlen reserviert werden. Dies ähnelt RANGE mit der Einschränkung, dass nur VALUES IN zur Angabe zulässiger Werte für jede Partition verwendet werden kann.

      VALUES IN wird mit einer Liste passender Werte benutzt. Beispielsweise könnten Sie ein Partitionierungsschema wie das folgende erstellen:

      CREATE TABLE client_firms (
          id   INT,
          name VARCHAR(35)
      )
      PARTITION BY LIST (id) (
          PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
          PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
          PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
          PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
      );
      

      Wenn Sie die Listenpartitionierung verwenden, müssen Sie mindestens eine Partition mit VALUES IN angeben. VALUES LESS THAN können Sie bei der Listenpartitionierung nicht einsetzen.

      Hinweis: Derzeit darf die für VALUES IN verwendete Werteliste nur aus Integers bestehen.

    • Die Anzahl der Partitionen kann optional mit einer PARTITIONS num-Klausel angegeben werden, wobei num die Anzahl der Partitionen ist. Werden diese Klausel und beliebige PARTITION-Klauseln verwendet, muss num gleich der Anzahl aller Partitionen sein, die mit PARTITION-Klauseln deklariert wurden.

      Hinweis: Unabhängig davon, ob Sie eine PARTITIONS-Klausel bei der Erstellung einer Tabelle verwenden, die mit RANGE oder LIST partitioniert wurde, müssen Sie in jedem Fall mindestens eine PARTITION VALUES-Klausel in der Tabellendefinition angeben (siehe unten).

    • Eine Partition kann optional in eine Anzahl Unterpartitionen aufgeteilt werden. Dies kann durch Verwendung der optionalen Klausel SUBPARTITION BY angegeben werden. Die Unterpartitionierung kann mit HASH oder KEY erfolgen. Beide können LINEAR sein. Sie funktionieren auf die gleiche Weise wie oben für die entsprechenden Partitionierungstypen beschrieben. (Es ist nicht möglich, Unterpartitionen nach LIST oder RANGE zu erstellen.)

      Die Anzahl der Unterpartitionen kann mit dem Schlüsselwort SUBPARTITIONS, gefolgt von einem Integer-Wert, angegeben werden.

    Jede Partition kann individuell mit einer partition_definition-Klausel definiert werden. Die einzelnen Teile, aus denen die Klausel besteht, sind die folgenden:

    • PARTITION partition_name: Gibt einen logischen Namen für die Partition an.

    • VALUES-Klausel: Bei der Bereichspartitionierung muss jede Partition eine VALUES LESS THAN-Klausel enthalten, und bei der Listenpartitionierung müssen Sie eine VALUES IN-Klausel je Partition angeben. Hiermit wird bestimmt, welche Datensätze in dieser Partition gespeichert werden sollen. Weitere Informationen und Syntaxinformationen entnehmen Sie der Beschreibung der Partitionierungstypen in Kapitel 17, Partitionierung.

    • Eine optionale COMMENT-Klausel kann zur Beschreibung der Partition angegeben werden. Der Kommentar muss in einzelne Anführungszeichen gesetzt werden. Beispiel:

      COMMENT = 'Data for the years previous to 1999'
      
    • DATA DIRECTORY und INDEX DIRECTORY können zur Angabe des Verzeichnisses verwendet werden, in dem die Daten bzw. die Indizes dieser Partition gespeichert werden sollen. Sowohl data_dir als auch index_dir müssen absolute Pfadnamen sein. Beispiel:

      CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)
      PARTITION BY LIST(YEAR(adate))
      (
        PARTITION p1999 VALUES IN (1995, 1999, 2003)
          DATA DIRECTORY = '/var/appdata/95/data'
          INDEX DIRECTORY = '/var/appdata/95/idx',
        PARTITION p2000 VALUES IN (1996, 2000, 2004)
          DATA DIRECTORY = '/var/appdata/96/data'
          INDEX DIRECTORY = '/var/appdata/96/idx',
        PARTITION p2001 VALUES IN (1997, 2001, 2005)
          DATA DIRECTORY = '/var/appdata/97/data'
          INDEX DIRECTORY = '/var/appdata/97/idx',
        PARTITION p2000 VALUES IN (1998, 2002, 2006)
          DATA DIRECTORY = '/var/appdata/98/data'
          INDEX DIRECTORY = '/var/appdata/98/idx'
      );
      

      DATA DIRECTORY und INDEX DIRECTORY verhalten sich genauso wie in der table_option-Klausel einer CREATE TABLE-Anweisung bei MyISAM-Tabellen.

      Je Partition können ein Daten- und ein Indexverzeichnis angegeben werden. Wenn keine Angaben gemacht werden, werden Daten und Indizes standardmäßig im MySQL-Datenverzeichnis abgelegt.

    • MAX_ROWS und MIN_ROWS können zur Angabe der größten bzw. kleinsten Zahl von Datensätzen verwendet werden, die in der Partition gespeichert werden. Die Werte für max_number_of_rows und min_number_of_rows müssen positive ganze Zahlen sein. Wie bei den gleichnamigen Optionen auf Tabellenebene sind auch dies keine festen Grenzwerte, sondern nur „Vorschläge“ für den Server.

    • Die optionale TABLESPACE-Klausel kann zur Angabe eines Tablespaces für die Partition verwendet werden. (Nur für MySQL Cluster.)

    • Die optionale [STORAGE] ENGINE-Klausel bewirkt, dass die Tabelle in dieser Partition die angegebene Speicher-Engine verwendet. Dies kann jede der vom betreffenden MySQL Server unterstützten Engines sein. Sowohl das Schlüsselwort STORAGE als auch das Gleichheitszeichen (=) sind optional. Wird keine partitionsspezifische Speicher-Engine mit dieser Option angegeben, dann wird die für die gesamte Tabelle gültige Engine auch für diese Partition verwendet.

      Hinweis: Der Partitionierungs-Handler akzeptiert eine Option [STORAGE] ENGINE sowohl für PARTITION als auch für SUBPARTITION. Die derzeit einzige Möglichkeit, diese Klausel zu nutzen, besteht darin, alle Partitionen oder alle Unterpartitionen auf dieselbe Speicher-Engine zu setzen. Der Versuch, verschiedene Engines für Partitionen oder Unterpartitionen einer Tabelle einzustellen, führt zum Fehler ERROR 1469 (HY000): The mix of handlers in the partitions is not allowed in this version of MySQL. Wir beabsichtigen, diese partitionierungsbezogene Einschränkung in einem zukünftigen Release von MySQL 5.1 zu beseitigen.

    • Die Option NODEGROUP kann verwendet werden, um diese Partition zu einem Teil der Knotengruppe zu machen, die als node_group_id angegeben ist. (Nur für MySQL Cluster.)

    • Die Partitionsdefinition kann optional eine oder mehrere subpartition_definition-Klauseln enthalten. Jede dieser Klauseln umfasst zumindest SUBPARTITION name, wobei name ein Bezeichner für die Unterpartition ist. Die Syntax für eine Unterpartitionsdefinition ist mit der einer Partition bis auf die Tatsache identisch, dass das Schlüsselwort PARTITION durch SUBPARTITION zu ersetzen ist.

      Die Unterpartitionierung muss über HASH oder KEY erfolgen und kann nur bei RANGE- oder LIST-Partitionen durchgeführt werden. Siehe auch Abschnitt 17.2.5, „Unterpartitionen“.

    Partitionen können geändert, verbunden und zu Tabellen hinzugefügt sowie aus diesen gelöscht werden. Grundlegende Informationen zu den MySQL-Anweisungen, mit denen diese Aufgaben erledigt werden, finden Sie in Abschnitt 13.1.2, „ALTER TABLE. Detaillierte Beschreibungen und Beispiele finden Sie in Abschnitt 17.3, „Partitionsverwaltung“.

Sie können eine Tabelle aus einer anderen Tabelle erstellen, indem Sie am Ende der CREATE TABLE-Anweisung eine SELECT-Anweisung hinzufügen:

CREATE TABLE new_tbl SELECT * FROM orig_tbl;

MySQL erstellt neue Spalten für alle Elemente in der SELECT-Anweisung. Zum Beispiel:

mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
    ->        PRIMARY KEY (a), KEY(b))
    ->        ENGINE=MyISAM SELECT b,c FROM test2;

Hierbei wird eine MyISAM-Tabelle mit drei Spalten a, b und c erstellt. Beachten Sie, dass die Spalten aus der SELECT-Anweisung rechts an die Tabelle angehängt und nicht in diese eingesetzt werden. Betrachten Sie einmal das folgende Beispiel:

mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+

mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)

Für jeden Datensatz in der Tabelle foo wird ein Datensatz in bar mit den Werten aus foo und den Standardwerten bei neuen Spalten eingefügt.

In einer Tabelle, die mit CREATE TABLE ... SELECT erstellt wurde, erscheinen die Spalten, die im CREATE TABLE-Teil genannt werden, zuerst. Die in beiden Teilen oder nur im SELECT-Teil genannten Spalten folgen nach. Der Datentyp der SELECT-Spalten kann außer Kraft gesetzt werden, indem die Spalte zusätzlich im CREATE TABLE-Teil genannt wird.

Wenn während des Kopierens der Daten in die Tabelle Fehler auftreten, wird diese automatisch gelöscht und nicht erstellt.

CREATE TABLE ... SELECT erstellt keine automatischen Indizes. Dies wurde bewusst so eingerichtet, um die Anweisung so flexibel wie möglich zu halten. Wenn Sie wollen, dass Indizes in der Tabelle erstellt werden, müssen Sie diese vor der SELECT-Anweisung spezifizieren:

mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

Es kann dadurch zu Fällen von Datentypkonvertierung kommen. So wird z. B. das AUTO_INCREMENT-Attribut nicht beibehalten, und VARCHAR-Spalten können in CHAR-Spalten umgewandelt werden.

Wenn Sie eine Tabelle mit CREATE ... SELECT erstellen, müssen Sie in jedem Fall Aliase für Funktionsaufrufe oder Ausdrücke in der Abfrage verwenden. Andernfalls kann die CREATE-Anweisung fehlschlagen, oder es können unerwünschte Spaltennamen entstehen.

CREATE TABLE artists_and_works
  SELECT artist.name, COUNT(work.artist_id) AS number_of_works
  FROM artist LEFT JOIN work ON artist.id = work.artist_id
  GROUP BY artist.id;

Sie können den Typ einer erzeugten Spalte auch explizit angeben:

CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

Mit LIKE können Sie eine leere Tabelle basierend auf der Definition einer anderen Tabelle einschließlich aller Spaltenattribute und Indizes erstellen, die auch in der Ursprungstabelle vorhanden sind:

CREATE TABLE new_tbl LIKE orig_tbl;

CREATE TABLE ... LIKE behält weder für die Ursprungstabelle angegebene DATA DIRECTORY- und INDEX DIRECTORY-Optionen noch Fremdschlüsseldefinitionen bei.

Sie können dem SELECT ein IGNORE oder REPLACE voranstellen, um anzugeben, wie mit Datensätzen zu verfahren ist, in denen Dubletten für eindeutige Schlüssel auftreten. Bei IGNORE werden neue Datensätze, die eine Dublette eines eindeutigen Schlüssels für einen bereits vorhandenen Datensatz enthalten, einfach verworfen. Wenn Sie REPLACE angeben, ersetzen die neuen die vorhandenen Datensätze, die denselben eindeutigen Schlüsselwert aufweisen. Werden weder IGNORE noch REPLACE angegeben, dann führt das Auftreten von Dubletten eindeutiger Schlüssel zu einem Fehler.

Um sicherzustellen, dass das Binärlog zur Wiederherstellung der Originaltabellen verwendet werden kann, gestattet MySQL keine gleichzeitigen Einfügeoperationen während der Ausführung einer CREATE TABLE ... SELECT-Anweisung.

13.1.6. DROP DATABASE

DROP {DATABASE | SCHEMA} [IF EXISTS] db_name

DROP DATABASE löscht alle Tabellen in der Datenbank und nachfolgend auch die Datenbank. Seien Sie im Umgang mit dieser Anweisung extrem sorgfältig! Um DROP DATABASE verwenden zu können, benötigen Sie die Berechtigung DROP für die Datenbank. DROP SCHEMA ist ein Synonym für DROP DATABASE.

IF EXISTS wird verwendet, um einen Fehler abzufangen, wenn die Datenbank nicht vorhanden ist.

Wenn Sie DROP DATABASE für eine symbolisch verknüpfte Datenbank verwenden, werden sowohl die Verknüpfung als auch die Originaldatenbank gelöscht.

DROP DATABASE gibt die Anzahl der entfernten Tabellen zurück. Diese entspricht der Anzahl der gelöschten .frm-Dateien.

Die DROP DATABASE-Anweisung entfernt jene Dateien und Verzeichnisse, die MySQL im normalen Betrieb selbst erstellt hat, aus dem angegebenen Datenbankverzeichnis:

  • Alle Dateien mit den folgenden Erweiterungen:

    .BAK.DAT.HSH
    .MRG.MYD.ISD
    .MYI.db.frm
  • Alle Unterverzeichnisse mit Namen, die aus zwei Hexadezimalstellen (00-ff) bestehen. Dies sind Unterverzeichnisse, die für RAID-Tabellen verwendet werden. (Diese Verzeichnisse werden ab MySQL 5.0 nicht entfernt, weil die Unterstützung für RAID-Tabellen aufgehoben wurde. Sie sollten alle vorhandenen RAID-Tabellen konvertieren und diese Verzeichnisse manuell entfernen, bevor Sie auf MySQL 5.0 oder höher aktualisieren. Weitere Informationen finden Sie im Abschnitt zur Aktualisierung von früheren Releases auf MySQL 5.0 im MySQL 5.0 Reference Manual, welches auf der MySQL-Website erhältlich ist.)

  • Datei db.opt (sofern vorhanden).

Wenn andere Dateien oder Verzeichnisse im Datenbankverzeichnis zurückbleiben, nachdem MySQL die genannten Elemente entfernt hat, kann das Datenbankverzeichnis nicht gelöscht werden. In diesem Fall müssen Sie alle verbleibenden Dateien oder Verzeichnisse manuell entfernen und die DROP DATABASE-Anweisung nachfolgend erneut absetzen.

Sie können Datenbanken auch mit mysqladmin löschen. Siehe auch Abschnitt 8.7, „mysqladmin — Client für die Verwaltung eines MySQL Servers“.

13.1.7. DROP INDEX

DROP INDEX index_name ON tbl_name

DROP INDEX löscht den Index namens index_name aus der Tabelle tbl_name. Diese Anweisung wird einer ALTER TABLE-Anweisung zugewiesen, die den Index löscht. Siehe auch Abschnitt 13.1.2, „ALTER TABLE.

13.1.8. DROP TABLE

DROP [TEMPORARY] TABLE [IF EXISTS]
    tbl_name [, tbl_name] ...
    [RESTRICT | CASCADE]

DROP TABLE löscht eine oder mehrere Tabellen. Für jede Tabelle benötigen Sie die Berechtigung DROP. Alle Tabellendaten und die Tabellendefinition werden entfernt! Seien Sie also auch im Umgang mit dieser Anweisung sehr vorsichtig!

Beachten Sie, dass DROP TABLE bei einer partitionierten Tabelle die Tabellendefinition, alle Partitionen und alle in diesen Partitionen gespeicherten Daten permanent entfernt. Ebenso gelöscht wird die Partitionierungsdefinitiondatei (.par) der gelöschten Tabelle.

Verwenden Sie IF EXISTS, um einen Fehler bei Tabellen abzufangen, die nicht vorhanden sind. Für jede nicht vorhandene Tabelle wird ein Hinweis erzeugt, wenn Sie IF EXISTS benutzen. Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS.

RESTRICT und CASCADE erlauben eine leichtere Portierung. Derzeit haben sie aber keine Funktion.

Hinweis: DROP TABLE übergibt die derzeit aktive Transaktion sofort, sofern Sie nicht das Schlüsselwort TEMPORARY benutzen.

Das Schlüsselwort TEMPORARY hat die folgenden Auswirkungen:

  • Die Anweisung löscht nur Temporärtabellen.

  • Die Anweisung beendet keine laufende Transaktion.

  • Zugriffsrechte werden nicht geprüft. (Eine Temporärtabelle ist nur für den Client sichtbar, der sie erstellt hat; insofern ist eine Überprüfung unnötig.)

Die Verwendung von TEMPORARY ist eine gute Möglichkeit, sicherzustellen, dass Sie nicht versehentlich eine nichttemporäre Tabelle löschen.

13.1.9. RENAME TABLE

RENAME TABLE tbl_name TO new_tbl_name
    [, tbl_name2 TO new_tbl_name2] ...

Mit dieser Anweisung werden eine oder mehrere Tabellen umbenannt.

Der Umbenennungsvorgang erfolgt automatisch, d. h., kein anderer Thread kann währenddessen auf die umzubenennende(n) Tabelle(n) zugreifen. Wenn Sie beispielsweise eine Tabelle old_table haben, können Sie eine andere Tabelle new_table erstellen, die dieselbe Struktur hat, aber leer ist, und die vorhandene Tabelle dann wie folgt durch die leere Tabelle ersetzen (sofern backup_table nicht bereits vorhanden ist):

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

Wenn die Anweisung mehrere Tabellen umbenennt, erfolgen die Umbenennungen von links nach rechts. Wollen Sie zwei Tabellennamen gegeneinander austauschen, dann können Sie dies wie folgt tun (sofern tmp_table nicht bereits vorhanden ist):

RENAME TABLE old_table TO tmp_table,
             new_table TO old_table,
             tmp_table TO new_table;

Solange zwei Datenbanken sich im selben Dateisystem befinden, können Sie mit RENAME TABLE auch eine Tabelle von einer Datenbank in eine andere verschieben:

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

RENAME TABLE funktioniert auch bei Views, solange Sie nicht versuchen, einen View in einer anderen Datenbank umzubenennen.

Wenn Sie RENAME ausführen, dürfen keine Tabellen gesperrt und keine Transaktionen aktiv sein. Sie benötigen für die Ursprungstabelle ferner die Berechtigungen ALTER und DROP sowie die Berechtigungen CREATE und INSERT für die neue Tabelle.

Wenn MySQL in einer tabellenübergreifenden Umbenennungsaktion auf Fehler trifft, wird für alle umbenannten Tabellen eine umgekehrte Umbenennung durchgeführt, um den ursprünglichen Zustand wiederherzustellen.

13.2. Datenmanipulation: SELECT, INSERT, UPDATE, DELETE

13.2.1. DELETE

Syntax für eine Tabelle:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

Syntax für mehrere Tabellen:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

Oder:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*]] ...
    USING table_references
    [WHERE where_condition]

Bei der Ein-Tabellen-Syntax löscht die DELETE-Anweisung Datensätze aus tbl_name und gibt die Anzahl gelöschter Datensätze zurück. Sofern angegeben, bestimmt die WHERE-Klausel die Bedingungen dafür, welche Datensätze gelöscht werden. Ohne WHERE-Klausel werden alle Datensätze gelöscht. Wenn die ORDER BY-Klausel vorhanden ist, werden die Datensätze in der angegebenen Reihenfolge gelöscht. Die LIMIT-Klausel kann die Anzahl der zu löschenden Datensätze beschränken.

Bei der Mehrtabellensyntax löscht DELETE aus jeder Tabelle tbl_name die Datensätze, die die Bedingungen erfüllen. In diesem Fall können ORDER BY und LIMIT nicht verwendet werden.

where_condition ist ein Ausdruck, der für jeden zu löschenden Datensatz wahr ist. Er wird wie in Abschnitt 13.2.7, „SELECT, beschrieben angegeben.

Wie bereits gesagt, löscht eine DELETE-Anweisung ohne WHERE-Klausel alle Datensätze. Wenn Sie die Anzahl der gelöschten Datensätze nicht kennen müssen, können Sie dies schneller mit TRUNCATE TABLE erledigen. Siehe auch Abschnitt 13.2.9, „TRUNCATE.

Wenn Sie den Datensatz entfernen, der den höchsten Wert für eine AUTO_INCREMENT-Spalte hat, dann wird der Wert bei BDB-Tabellen später wiederverwendet, nicht jedoch bei MyISAM- oder InnoDB-Tabellen. Wenn Sie im AUTOCOMMIT-Modus alle Datensätze in der Tabelle mit DELETE FROM tbl_name (ohne WHERE-Klausel) löschen, beginnt die Sequenz für alle Speicher-Engines mit Ausnahme von InnoDB und MyISAM neu. Bei InnoDB-Tabellen gibt es bezüglich dieses Verhaltens ein paar Ausnahmen, die in Abschnitt 14.2.6.3, „Wie eine Auto-Increment-Spalte in InnoDB funktioniert“, beschrieben sind.

Bei MyISAM- und BDB-Tabellen können Sie AUTO_INCREMENT in einer Sekundärspalte eines mehrspaltigen Schlüssels angeben. In diesem Fall werden Werte, die am Anfang der Sequenz gelöscht wurden, auch bei MyISAM-Tabellen wiederverwendet. Siehe auch Abschnitt 3.6.9, „Verwendung von AUTO_INCREMENT.

Die DELETE-Anweisung unterstützt die folgenden Modifizierer:

  • Wenn Sie LOW_PRIORITY angeben, verzögert der Server die Ausführung von DELETE, bis kein Client mehr aus der Tabelle liest.

  • Wenn Sie bei MyISAM-Tabellen das Schlüsselwort QUICK angeben, fasst die Speicher-Engine beim Löschen Indexzweige nicht zusammen. Dies kann bestimmte Arten von Löschvorgängen beschleunigen.

  • Das Schlüsselwort IGNORE bewirkt, dass MySQL alle Fehler während des Vorgangs der Datensatzlöschung ignoriert. (Fehler, die bei der Analyse auftreten, werden allerdings wie gewöhnlich verarbeitet.) Fehler, die aufgrund der Verwendung von OPTION ignoriert werden, werden als Warnungen zurückgegeben.

Die Geschwindigkeit von Löschoperationen kann auch von den Faktoren beeinflusst werden, die in Abschnitt 7.2.18, „Geschwindigkeit von DELETE-Anfragen“, beschrieben werden.

Bei MyISAM-Tabellen werden gelöschte Datensätze zu einer verknüpften Liste hinzugefügt. Nachfolgende INSERT-Operationen verwenden die alten Datensatzpositionen neu. Um ungenutzten Speicher wieder freizugeben und die Dateigrößen zu verringern, verwenden Sie die OPTIMIZE TABLE-Anweisung oder das Hilfsprogramm myisamchk zur Reorganisierung der Tabellen. OPTIMIZE TABLE ist einfacher, myisamchk hingegen schneller. Siehe auch Abschnitt 13.5.2.5, „OPTIMIZE TABLE, und Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.

Der Modifizierer QUICK bestimmt, ob Indexzweige bei Löschoperationen zusammengefasst werden. DELETE QUICK ist am nützlichsten bei Anwendungen, bei denen Indexwerte für gelöschte Datensätze durch ähnliche Indexwerte von später eingefügten Datensätzen ersetzt werden. In diesem Fall werden die von den gelöschten Werten zurückgelassenen Löcher wiederverwendet.

DELETE QUICK ist hingegen nicht nützlich, wenn gelöschte Werte nicht aufgefüllte Indexblöcke zur Folge haben, die einen Bereich von Indexwerten umfassen, bei denen neue Einfügeoperationen auftreten. In diesem Fall kann die Verwendung von QUICK zur Verschwendung von Speicher im Index führen, da dieser Speicher nicht mehr freigegeben wird. Hier ein Beispiel für ein solches Szenario:

  1. Erstellen Sie eine Tabelle, die eine indizierte AUTO_INCREMENT-Spalte enthält.

  2. Fügen Sie viele Datensätze in diese Tabelle ein. Jede Einfügeoperation führt dazu, dass ein Indexwert am Ende des Indexes eingefügt wird.

  3. Löschen Sie mit DELETE QUICK einen Block mit Datensätzen vorne im Spaltenbereich.

In diesem Szenario werden die Indexblöcke, die mit den gelöschten Indexwerten verknüpft sind, nicht aufgefüllt, aber aufgrund der Verwendung von QUICK auch nicht mit anderen Indexblöcken zusammengefasst. Sie bleiben also unaufgefüllt, wenn weitere Einfügeoperationen auftreten, weil die neuen Datensätze keine Indexwerte im gelöschten Bereich haben. Außerdem bleiben sie auch dann unaufgefüllt, wenn Sie später DELETE ohne QUICK verwenden, sofern nicht zufällig einige der gelöschten Indexwerte in Indexblöcken innerhalb oder neben den nicht aufgefüllten Blöcken liegen. Um ungenutzten Indexspeicher unter diesen Umständen wieder freizugeben, verwenden Sie OPTIMIZE TABLE.

Wenn Sie viele Datensätze aus einer Tabelle zu löschen beabsichtigen, kann DELETE QUICK gefolgt von OPTIMIZE TABLE die schnellere Lösung sein. Hierbei wird der Index neu erstellt, statt zahlreiche Zusammenfassungsoperationen für Indexblöcke auszuführen.

Die MySQL-spezifische Option LIMIT row_count für DELETE nennt dem Server die maximale Anzahl Datensätze, die gelöscht werden, bevor die Kontrolle an den Client zurückgegeben wird. Hiermit können Sie gewährleisten, dass eine gegebene DELETE-Anweisung nicht zu viel Zeit in Anspruch nimmt. Sie können die DELETE-Anweisung dann einfach wiederholen, bis die Gesamtzahl betroffener Datensätze kleiner ist als der LIMIT-Wert.

Wenn die DELETE-Anweisung eine ORDER BY-Klausel enthält, werden die Datensätze in der in der Klausel angegebenen Reihenfolge gelöscht. Dies ist nur in Verbindung mit LIMIT wirklich nützlich. Die folgende Anweisung beispielsweise findet Datensätze, die der WHERE-Klausel entsprechen, sortiert sie nach timestamp_column und löscht den ersten (d. h. ältesten) Datensatz:

DELETE FROM somelog WHERE user = 'jcole'
ORDER BY timestamp_column LIMIT 1;

Sie können in einer DELETE-Anweisung mehrere Tabellen angeben, aus denen je nach Bedingung der WHERE-Klausel Datensätze gelöscht werden. Allerdings können Sie ORDER BY oder LIMIT nicht in einer DELETE-Anweisung für mehrere Tabellen verwenden. Die Klausel table_references listet die Tabellen auf, die im Join berücksichtigt werden. Die Syntax ist in Abschnitt 13.2.7.1, „JOIN, beschrieben.

Bei der ersten Mehrtabellensyntax werden nur passende Datensätze aus den Tabellen gelöscht, die vor der FROM-Klausel aufgelistet sind. Bei der zweiten Mehrtabellensyntax werden nur passende Datensätze aus den Tabellen gelöscht, die in der FROM-Klausel (vor der USING-Klausel) aufgelistet sind. Die Folge ist, dass Sie Datensätze aus vielen Tabellen gleichzeitig löschen und gleichzeitig in weiteren Tabellen nur suchen lassen können:

DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

Oder:

DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

Diese Anweisungen verwenden auf der Suche nach zu löschenden Datensätzen alle drei Tabellen, aber gelöscht werden passende Datensätze tatsächlich nur aus den Tabellen t1 und t2.

Die obigen Beispiele zeigen innere Joins, die den Kommaoperator verwenden. DELETE-Anweisungen für mehrere Tabellen können jedoch einen beliebigen Join-Typ verwenden, der für SELECT-Anweisungen zulässig ist, also etwa LEFT JOIN.

Die Syntax erlaubt .* nach den Tabellennamen, um die Kompatibilität mit Access zu gewährleisten.

Wenn Sie eine DELETE-Anweisung für mehrere Tabellen verwenden, die auch InnoDB-Tabellen einbezieht, für die Fremdschlüssel-Constraints vorhanden sind, dann verarbeitet der MySQL-Optimierer die Tabellen unter Umständen in einer Reihenfolge, die sich von der ihrer Parent/Child-Beziehung unterscheidet. In diesem Fall schlägt die Anweisung fehl, und es wird ein Rollback durchgeführt. Stattdessen sollten Sie die Löschoperation dann aus nur einer Tabelle durchführen und sich auf die ON DELETE-Funktionalität verlassen, die InnoDB bietet, um andere Tabellen entsprechend zu ändern.

Hinweis: Wenn Sie einen Alias für eine Tabelle angegeben haben, müssen Sie diesen bei der Referenzierung der Tabelle verwenden:

DELETE t1 FROM test AS t1, test2 WHERE ...

Datenbankübergreifende Löschvorgänge werden von Löschvorgängen für mehrere Tabellen unterstützt. In diesem Fall müssen Sie die Tabellen aber ohne Verwendung von Aliasen referenzieren. Zum Beispiel:

DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...

Zurzeit können Sie in einer Unterabfrage keine Löschoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.

13.2.2. DO

DO expr [, expr] ...

DO führt Ausdrücke aus, gibt aber keine Ergebnisse zurück. In den meisten Fällen ist DO eine Kurzform von SELECT expr, ..., hat aber den Vorteil, dass es etwas schneller ist, sofern das Ergebnis für Sie keine Rolle spielt. Allerdings meldet DO keine Fehler. Stattdessen werden Fehler als Warnungen ausgegeben.

DO ist in erster Linie bei Funktionen praktisch, die Begleiterscheinungen haben (z. B. RELEASE_LOCK()).

13.2.3. HANDLER

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE

Die Anweisung HANDLER bietet direkten Zugriff auf die Schnittstellen der Speicher-Engine einer Tabelle. Sie steht für MyISAM- und InnoDB-Tabellen zur Verfügung.

Die Anweisung HANDLER ... OPEN öffnet eine Tabelle und gestattet den Zugriff über nachfolgende HANDLER ... READ-Anweisungen. Dieses Tabellenobjekt wird nicht mit anderen Threads gemeinsam genutzt und wird erst geschlossen, wenn der Thread HANDLER ... CLOSE aufruft oder beendet wird. Wenn Sie die Tabelle unter Verwendung eines Alias öffnen, müssen nachfolgende Referenzierungen durch andere HANDLER-Anweisungen den Alias statt des Tabellennamens verwenden.

Die erste HANDLER ... READ-Syntax holt einen Datensatz, bei dem der angegebene Index den übergebenen Werten entspricht und die WHERE-Bedingung erfüllt ist. Wenn Sie einen mehrspaltigen Index haben, geben Sie die Indexspaltenwerte als kommagetrennte Liste an. Entweder geben Sie Werte für alle Spalten im Index oder aber Werte für das links stehende Präfix der Indexspalten an. Angenommen, ein Index my_idx enthält drei Spalten namens col_a, col_b und col_c in genau dieser Reihenfolge. Die Anweisung HANDLER kann Werte für alle drei Spalten im Index oder für die Spalten in einem links stehenden Präfix angeben. Zum Beispiel:

HANDLER ... READ my_idx = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... READ my_idx = (col_a_val,col_b_val) ...
HANDLER ... READ my_idx = (col_a_val) ...

Um die HANDLER-Schnittstelle für die Referenzierung des Primärschlüssels einer Tabelle zu verwenden, setzen Sie den Bezeichner in Anführungszeichen (`PRIMARY`).

HANDLER tbl_name READ `PRIMARY` ...

Die zweite HANDLER ... READ-Syntax holt aus der Tabelle einen Datensatz in der Indexreihenfolge, die der WHERE-Bedingung entspricht.

Die dritte HANDLER ... READ-Syntax holt aus der Tabelle einen Datensatz in der natürlichen Datensatzreihenfolge, die der WHERE-Bedingung entspricht. Sie ist schneller als HANDLER tbl_name READ index_name, wenn ein vollständiger Tabellenscan gewünscht wird. Die natürliche Datensatzreihenfolge ist die Reihenfolge, in der die Datensätze in der Datendatei einer MyISAM-Tabelle gespeichert sind. Diese Anweisung funktioniert auch bei InnoDB-Tabellen, aber das Konzept greift hier in Ermangelung einer separaten Datendatei nicht.

Ohne eine LIMIT-Klausel holen alle Formen von HANDLER ... READ einen einzelnen Datensatz (sofern vorhanden). Um eine bestimmte Anzahl Datensätze zurückzugeben, fügen Sie eine LIMIT-Klausel ein. Sie hat dieselbe Syntax wie bei der SELECT-Anweisung. Siehe auch Abschnitt 13.2.7, „SELECT.

HANDLER ... CLOSE schließt eine Tabelle, die mit HANDLER ... OPEN geöffnet worden war.

HANDLER ist eine etwas maschinennahe Anweisung. Sie bietet z. B. keine Konsistenz: HANDLER ... OPEN fertigt keine Momentaufnahme der Tabelle an und sperrt sie nicht. Das bedeutet, dass, nachdem eine HANDLER ... OPEN-Anweisung abgesetzt wurde, die Tabellendaten (vom aktuellen, aber auch von anderen Threads) modifiziert werden können und diese Änderungen dann für HANDLER ... NEXT- oder HANDLER ... PREV-Scans unter Umständen nur teilweise sichtbar sind.

Es gibt eine Reihe von Gründen zur Verwendung der HANDLER-Schnittstelle anstelle einer normalen SELECT-Anweisung:

  • HANDLER ist schneller als SELECT:

    • Für HANDLER ... OPEN wird ein dediziertes Speicher-Engine-spezifisches Handler-Objekt reserviert. Das Objekt wird bei nachfolgenden HANDLER-Anweisungen für diese Tabelle wiederverwendet; es muss nicht jeweils neu initialisiert werden.

    • Der Analyseaufwand ist geringer.

    • Es ist kein zusätzlicher Aufwand für den Optimierer oder die Abfrageüberprüfung erforderlich.

    • Die Tabelle muss nicht zwischen zwei Handler-Anforderungen gesperrt werden.

    • Die Handler-Schnittstelle muss keine konsistente Sicht der Daten bieten (Dirty Reads beispielsweise sind zulässig) – die Speicher-Engine kann also Optimierungen verwenden, die SELECT normalerweise nicht zulassen würde.

  • Bei Anwendungen, die eine maschinennahe ISAM-artige Schnittstelle verwenden, erleichtert HANDLER deren Portierung auf MySQL.

  • HANDLER erlaubt Ihnen das Durchlaufen einer Datenbank auf eine Weise, die mit SELECT – wenn überhaupt – nur sehr schwierig zu realisieren ist. Die HANDLER-Schnittstelle ist eine natürlicher anmutende Art der Datensicht, wenn Sie mit Anwendungen arbeiten, die eine interaktive Benutzeroberfläche für die Datenbank bereitstellen.

13.2.4. INSERT

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

Oder:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

Oder:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

INSERT fügt neue Datensätze in eine vorhandene Tabelle ein. Die Formen INSERT ... VALUES und INSERT ... SET der Anweisung fügen Datensätze basierend auf explizit angegebenen Werten ein. Die Form INSERT ... SELECT fügt Datensätze ein, die in einer oder mehreren anderen Tabellen ausgewählt wurden. INSERT ... SELECT wird in Abschnitt 13.2.4.1, „INSERT ... SELECT, näher erläutert.

Sie können REPLACE anstelle von INSERT verwenden, um alte Datensätze zu überschreiben. REPLACE ist das Gegenstück zu INSERT IGNORE bei der Behandlung neuer Datensätze, deren eindeutige Schlüsselwerte Dubletten bereits vorhandener Datensätze sind: Die neuen Datensätze ersetzen die alten, statt verworfen zu werden. Siehe auch Abschnitt 13.2.6, „REPLACE.

tbl_name ist die Tabelle, in die die Datensätze eingefügt werden sollen. Die Spalten, für die die Anweisung Werte angibt, lassen sich wie folgt angeben:

  • Sie können eine kommagetrennte Liste von Spaltennamen gefolgt vom Tabellennamen angeben. In diesem Fall muss für jede genannte Spalte in der VALUES-Liste oder der SELECT-Anweisung ein Wert vorhanden sein.

  • Wenn Sie keine Liste mit Spaltennamen für INSERT ... VALUES oder INSERT ... SELECT angeben, dann müssen die Werte für alle Spalten in der Tabelle in der VALUES-Liste oder der SELECT-Anweisung vorhanden sein. Wenn Sie die Reihenfolge der Spalten in der Tabelle nicht kennen, ermitteln Sie sie mit DESCRIBE tbl_name.

  • Die SET-Klausel gibt die Spaltennamen ausdrücklich an.

Spaltenwerte lassen sich auf mehrerlei Weise übergeben:

  • Wenn Sie MySQL nicht im strikten SQL-Modus ausführen, dann wird jede Spalte, für die kein Wert angegeben wird, auf den (expliziten oder impliziten) Standardwert gesetzt. Wenn Sie also etwa eine Spaltenliste angeben, die nicht alle Spalten in der Tabelle aufführt, werden nicht genannte Spalten auf ihre jeweiligen Standardwerte gesetzt. Die Zuweisung von Standardwerten ist in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben. Siehe auch Abschnitt 1.9.6.2, „Constraints auf ungültigen Daten“.

    Wenn Sie wollen, dass eine INSERT-Anweisung einen Fehler erzeugt, wenn Sie nicht alle Werte für alle Spalten ausdrücklich angeben, für die kein Standardwert vorhanden ist, dann sollten Sie den strikten Modus verwenden. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.

  • Mit dem Schlüsselwort DEFAULT können Sie eine Spalte explizit auf ihren Standardwert setzen. Dies erleichtert das Formulieren von INSERT-Anweisungen, die allen Spalten (bis auf einigen wenigen) Werte zuweisen, denn so brauchen Sie keine unvollständige VALUES-Liste zu erstellen, die nicht für jede Spalte in der Tabelle einen Wert enthält. Andernfalls müssten Sie die Liste der Spaltennamen ausschreiben, die den einzelnen Werten in der VALUES-Liste entspricht.

    Sie können auch DEFAULT(col_name) als eine allgemeinere Form benutzen, mit der in Ausdrücken der Standardwert einer gegebenen Spalte erzeugt werden kann.

  • Wenn sowohl die Spaltenliste als auch die VALUES-Liste leer sind, erstellt INSERT einen Datensatz, bei dem jede Spalte auf den jeweiligen Standardwert gesetzt ist:

    INSERT INTO tbl_name () VALUES();
    

    Im strikten Modus tritt ein Fehler auf, wenn nicht für jede Spalte ein Standardwert angegeben ist. Andernfalls verwendet MySQL den impliziten Standardwert für jede Spalte, der kein expliziter Wert zugewiesen ist.

  • Sie können den Spaltenwert auch durch einen Ausdruck expr angeben. Dies kann eine Typenkonvertierung bedingen, wenn der Ausdruckstyp nicht dem Typ der Spalte entspricht. Die Konvertierung eines gegebenen Werts kann je nach Datentyp zu unterschiedlichen Einfügewerten führen. So hat z. B. das Einfügen des Strings '1999.0e-2' in eine INT-. FLOAT-, DECIMAL(10,6)- oder YEAR-Spalte die Einfügewerte 1999, 19.9921, 19.992100 bzw. 1999 zur Folge. Der Grund dafür, dass der in den INT- und YEAR-Spalten gespeicherte Wert 1999 ist, besteht darin, dass bei der Konvertierung des Strings in den Integer nur der Teil des Strings berücksichtigt wird, der als gültiger Integer bzw. als sinnvolle Jahresangabe betrachtet wird. Bei Fließkomma- und Festkommaspalten wird bei der Umwandlung des Strings in einen Fließkommawert der gesamte String als zulässiger Fließkommawert betrachtet.

    Ein Ausdruck expr kann jede Spalte referenzieren, die zuvor in einer Werteliste eingestellt wurde. Sie könnten dies beispielsweise tun, weil der Wert von col2 die zuvor zugewiesene Spalte col1 referenziert:

    INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
    

    Die folgende Variante ist jedoch nicht zulässig, weil der Wert für col1 die Spalte col2 referenziert, die jedoch erst nach col1 zugewiesen wurde:

    INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
    

    Eine Ausnahme betrifft Spalten, die AUTO_INCREMENT-Werte enthalten. Weil der AUTO_INCREMENT-Wert nach anderen Wertezuweisungen erzeugt wird, gibt eine Referenzierung einer AUTO_INCREMENT-Spalte 0 zurück.

INSERT-Anweisungen, die die VALUES-Syntax verwenden, können mehrere Datensätze einfügen. Zu diesem Zweck fügen Sie mehrere Listen mit Spaltenwerten ein, die jeweils in Klammern gesetzt und durch Kommata getrennt sind. Beispiel:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

Die Werteliste für jeden Datensatz muss in Klammern gesetzt werden. Die folgende Anweisung ist unzulässig, weil die Anzahl der Werte in der Liste nicht der Anzahl der Spaltennamen entspricht:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);

Der Wert der von einer INSERT-Anweisung betroffenen Datensätze kann mit der C-API-Funktion mysql_affected_rows() ermittelt werden. Siehe auch Abschnitt 24.2.3.1, „mysql_affected_rows().

Wenn Sie eine INSERT ... VALUES-Anweisung mit mehreren Wertelisten oder INSERT ... SELECT verwenden, gibt die Anweisung einen Informations-String im folgenden Format zurück:

Records: 100 Duplicates: 0 Warnings: 0

Records gibt die Anzahl der von der Anweisung verarbeiteten Datensätze zurück. (Dies entspricht nicht unbedingt der Anzahl der tatsächlich eingefügten Datensätze, weil Duplicates auch ungleich null sein kann.) Duplicates gibt die Anzahl der Datensätze an, die nicht eingefügt wurden, weil eindeutige Schlüsselwerte andernfalls dupliziert worden wären. Warnings gibt die Anzahl der Spalteneinfügeversuche an, die aus irgendeinem Grund problematisch waren. Warnungen können unter den folgenden Umständen auftreten:

  • Einfügen von NULL in eine Spalte, die als NOT NULL deklariert wurde. Bei INSERT-Anweisung für mehrere Datensätze oder INSERT INTO ... SELECT-Anweisungen wird die Spalte auf den impliziten Standardwert für den betreffenden Spaltendatentyp gesetzt. Bei numerischen Typen ist dies 0, bei String-Typen der Leer-String ('') und der „Nullwert“ bei Datums- und Uhrzeittypen. INSERT INTO ... SELECT-Anweisungen werden auf die gleiche Weise behandelt wie Einfügeoperationen für mehrere Datensätze, weil der Server die Ergebnismenge von SELECT nicht darauf überprüft, ob genau ein Datensatz zurückgegeben wird. (Bei INSERT-Anweisungen für nur einen Datensatz erscheint keine Warnung, wenn NULL in eine NOT NULL-Spalte eingefügt wird. Stattdessen schlägt die Anweisung mit einem Fehler fehl.)

  • Setzen einer numerischen Spalte auf einen Wert außerhalb des zulässigen Wertebereichs. Der Wert wird auf den nächstgelegenen Endpunkt des Bereichs gesetzt.

  • Zuweisen eines Werts wie '10.34 a' zu einer numerischen Spalte. Der nichtnumerische Text am Ende wird entfernt, und der verbleibende numerische Teil wird eingefügt. Hat der String-Wert am Anfang keinen numerischen Teil, dann wird die Spalte auf 0 gesetzt.

  • Einfügen eines Strings in eine String-Spalte (CHAR, VARCHAR, TEXT oder BLOB), die die maximale Länge der Spalte überschreitet. Der Wert wird auf die zulässige Maximallänge der Spalte gekürzt.

  • Einfügen eines Werts in eine Spalte für Datum oder Uhrzeit, der für diesen Datentyp nicht zulässig ist. Die Spalte wird auf den passenden Nullwert des Typs gesetzt.

Wenn Sie die C-API verwenden, kann der Informations-String durch Aufruf der Funktion mysql_info() ermittelt werden. Siehe auch Abschnitt 24.2.3.34, „mysql_info().

Wenn INSERT einen Datensatz in eine Tabelle einfügt, die eine AUTO_INCREMENT-Spalte enthält, dann können Sie den Wert dieser Spalte mithilfe der SQL-Funktion LAST_INSERT_ID() abfragen. Aus der C-API heraus verwenden Sie die Funktion mysql_insert_id(). Sie sollten allerdings beachten, dass die beiden Funktionen sich nicht immer identisch verhalten. Das Verhalten von INSERT-Anweisungen in Bezug auf AUTO_INCREMENT-Spalten wird in Abschnitt 12.10.3, „Informationsfunktionen“, und Abschnitt 24.2.3.36, „mysql_insert_id(), ausführlicher beschrieben.

Die INSERT-Anweisung unterstützt die folgenden Modifizierer:

  • Wenn Sie das Schlüsselwort DELAYED verwenden, legt der Server den oder die einzufügenden Datensätze in einem Puffer ab, und der Client, der die INSERT DELAYED-Anweisung abgesetzt hat, kann sofort weiterarbeiten. Wird die Tabelle gerade verwendet, dann hält der Server die Datensätze zurück. Sobald die Tabelle frei ist, startet der Server mit dem Einfügen der Datensätze und prüft dabei periodisch, ob neue Leseanforderungen für die Tabelle anstehen. In diesem Fall wird die Warteschlange mit den verzögerten Datensätzen angehalten, bis die Tabelle wieder frei wird. Siehe auch Abschnitt 13.2.4.2, „INSERT DELAYED.

    DELAYED wird bei INSERT ... SELECT oder INSERT ... ON DUPLICATE KEY UPDATE ignoriert.

  • Wenn Sie das Schlüsselwort LOW_PRIORITY angeben, wird die Ausführung von INSERT verzögert, bis kein Client mehr aus der Tabelle liest. Dies schließt andere Clients mit ein, die Leseoperationen starten, während bereits vorhandene Clients aus der Tabelle lesen und die INSERT LOW_PRIORITY-Anweisung wartet. Aus diesem Grund ist es möglich, dass ein Client, der eine INSERT LOW_PRIORITY-Anweisung absetzt, sehr lange warten muss – in Umgebungen mit extrem hohen Aufkommen von Leseoperationen sogar für immer. (Dies steht im Gegensatz zu INSERT DELAYED, wo der Client direkt fortfahren kann.) Beachten Sie, dass LOW_PRIORITY normalerweise nicht bei MyISAM-Tabellen benutzt werden sollte, da auf diese Weise gleichzeitige Einfügeoperationen unmöglich gemacht werden. Siehe auch Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“.

  • Wenn Sie HIGH_PRIORITY angeben, setzt es die Auswirkungen der Option --low-priority-updates außer Kraft, sofern der Server mit dieser Option gestartet worden war. Außerdem sind auch hier gleichzeitige Einfügeoperationen nicht möglich.

  • Wenn Sie das Schlüsselwort IGNORE angeben, werden Fehler, die während der Ausführung der INSERT-Anweisung auftreten, als Warnungen behandelt. So würde beispielsweise ohne IGNORE ein Datensatz, der einen vorhandenen eindeutigen Index oder einen Primärschlüsselwert in der Tabelle dupliziert, einen Dublettenfehler verursachen, woraufhin die Anweisung abgebrochen würde. Bei IGNORE wird der Datensatz zwar auch nicht eingefügt, aber es wird kein Fehler ausgegeben. Bei Fehler auslösenden Datenkonvertierungen wird die Anweisung abgebrochen, wenn IGNORE nicht angegeben ist. Bei IGNORE hingegen werden ungültige Werte auf den jeweils nächstgelegenen gültigen Wert gesetzt und dann einfügt; außerdem werden Warnungen erzeugt, aber die Anweisung wird nicht abgebrochen. Mit der C-API-Funktion mysql_info() können Sie ermitteln, wie viele Datensätze tatsächlich in die Tabelle eingefügt wurden.

  • Wenn Sie ON DUPLICATE KEY UPDATE angeben und ein Datensatz eingefügt wird, der einen doppelten Wert in einem eindeutigen Index oder einem Primärschlüssel erzeugen würde, dann wird für den alten Datensatz UPDATE ausgeführt. Siehe auch Abschnitt 13.2.4.3, „INSERT ... ON DUPLICATE KEY UPDATE.

13.2.4.1. INSERT ... SELECT

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

Mit INSERT ... SELECT können Sie schnell mehrere Datensätze aus einer oder mehreren Tabellen in eine Tabelle einfügen. Zum Beispiel:

INSERT INTO tbl_temp2 (fld_id)
  SELECT tbl_temp1.fld_order_id
  FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;

Die folgenden Bedingungen gelten für eine INSERT ... SELECT-Anweisung:

  • Geben Sie IGNORE an, um Datensätze zu ignorieren, die unzulässige Schlüsseldubletten erzeugen würden.

  • DELAYED wird bei INSERT ... SELECT ignoriert.

  • Die Zieltabelle der INSERT-Anweisung kann in der FROM-Klausel des SELECT-Teils der Abfrage erscheinen. (Dies war bei einigen älteren MySQL-Versionen nicht möglich.)

  • AUTO_INCREMENT-Spalten arbeiten wie gewöhnlich.

  • Um sicherzustellen, dass das Binärlog zur Wiederherstellung der Originaltabellen verwendet werden kann, gestattet MySQL keine nebenläufigen Einfügeoperationen während der Ausführung einer INSERT ... SELECT-Anweisung.

  • Zurzeit können Sie in einer Unterabfrage keine Einfügeoperation in eine Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.

Im Werteteil von ON DUPLICATE KEY UPDATE können Sie Spalten in anderen Tabellen referenzieren, solange Sie im SELECT-Teil nicht GROUP BY verwenden. Eine Begleiterscheinung besteht darin, dass Sie nichteindeutige Spaltennamen im Werteteil qualifizieren müssen.

13.2.4.2. INSERT DELAYED

INSERT DELAYED ...

Die Option DELAYED für die INSERT-Anweisung ist eine MySQL-Erweiterung zum SQL-Standard, die sehr praktisch ist, wenn Sie Clients haben, die nicht auf den Abschluss der INSERT-Anweisung warten können oder müssen. Eine solche Situation liegt häufig vor, wenn Sie MySQL zum Loggen verwenden und zudem regelmäßig SELECT- und UPDATE-Anweisungen ausführen, deren Fertigstellung sehr lange dauert.

Wenn ein Client INSERT DELAYED verwendet, wird diese Anweisung vom Server sofort angenommen und der Datensatz in einer Warteschlange abgelegt. Sobald die Tabelle von keinem anderen Thread mehr verwendet wird, wird der Datensatz dann aus der Warteschlange eingefügt.

Ein weiterer wesentlicher Vorteil von INSERT DELAYED besteht darin, dass Einfügeoperationen mehrerer Clients gebündelt und dann in einem Block geschrieben werden. Dies ist bedeutend schneller als die Durchführung vieler separater Einfügeoperationen.

Beachten Sie, dass INSERT DELAYED, sofern die Tabelle gerade nicht anderweitig verwendet wird, langsamer als eine normale INSERT-Anweisung ist. Auch liegt die Serverbelastung etwas höher, weil der Server für jede Tabelle, für die verzögerte Datensätze vorhanden sind, einen separaten Thread verwalten muss. Insofern sollten Sie INSERT DELAYED nur verwenden, wenn Sie wirklich sicher sind, dass Sie die Funktionalität benötigen.

Die Datensätze in der Warteschlange verbleiben nur solange im Speicher, bis sie in die Tabelle eingefügt wurden. Aufgrund dessen gehen, wenn Sie mysqld – etwa mit kill -9 – terminieren oder mysqld unerwartet abstürzt, alle Datensätze in der Warteschlange, die noch nicht auf Festplatte geschrieben wurden, verloren!

Für die Verwendung von DELAYED gelten einige Einschränkungen:

  • INSERT DELAYED funktioniert nur bei MyISAM-, MEMORY- und ARCHIVE-Tabellen. Siehe auch Abschnitt 14.1, „Die MyISAM-Speicher-Engine“, Abschnitt 14.4, „Die MEMORY-Speicher-Engine“ und Abschnitt 14.8, „Die ARCHIVE-Speicher-Engine“.

    Bei MyISAM-Tabellen werden, wenn keine freien Blöcke in der Mitte der Datendatei vorhanden sind, gleichzeitige SELECT- und INSERT-Anweisung unterstützt. Unter diesen Umständen müssen Sie INSERT DELAYED bei MyISAM nur in sehr seltenen Fällen verwenden.

  • INSERT DELAYED sollte nur für INSERT-Anweisungen eingesetzt werden, die Wertelisten angeben. Bei INSERT DELAYED ... SELECT-Anweisungen ignoriert der Server das DELAYED.

  • Ebenso ignoriert der Server das DELAYED bei INSERT ... SELECT- oder INSERT ... ON DUPLICATE KEY UPDATE-Anweisungen.

  • Weil die INSERT DELAYED-Anweisung aus Clientsicht abgeschlossen wird, bevor die Datensätze tatsächlich eingefügt werden, können Sie den von der Anweisung erstellten AUTO_INCREMENT-Wert nicht mit LAST_INSERT_ID() abrufen.

  • Verzögerte Datensätze werden für SELECT-Anweisungen erst sichtbar, wenn sie tatsächlich eingefügt wurden.

  • DELAYED wird auf Slave-Replikationsservern ignoriert, weil andernfalls auf dem Slave andere Daten vorhanden sein könnten als auf dem Master.

Nachfolgend wird ausführlich beschrieben, was geschieht, wenn Sie die Option DELAYED für INSERT oder REPLACE einsetzen. In dieser Beschreibung ist „Thread“ der Thread, der eine INSERT DELAYED-Anweisung empfangen hat, und „Handler“ der Thread, der alle INSERT DELAYED-Anweisungen der betreffenden Tabelle verwaltet.

  • Wenn ein Thread eine DELAYED-Anweisung für eine Tabelle ausführt, wird – sofern nicht bereits vorhanden – ein Handler-Thread erzeugt, um alle DELAYED-Anweisungen für die Tabelle zu verarbeiten.

  • Der Thread überprüft, ob der Handler zuvor bereits eine DELAYED-Sperre erwirkt hat, und weist den Handler andernfalls dazu an. Die DELAYED-Sperre kann auch dann erwirkt werden, wenn andere Threads eine READ- oder WRITE-Sperre für die Tabelle halten. Allerdings wartet der Handler, bis alle ALTER TABLE-Sperren aufgehoben und FLUSH TABLES-Anweisungen abgeschlossen sind, um zu gewährleisten, dass die Tabellenstruktur aktuell ist.

  • Der Thread führt die INSERT-Anweisung aus, schreibt den Datensatz aber nicht in die Tabelle, sondern setzt eine Kopie des endgültigen Datensatzes in eine Warteschlange, die vom Handler verwaltet wird. Syntaxfehler werden vom Thread bemerkt und an das Clientprogramm zurückgemeldet.

  • Der Client kann die Anzahl doppelter Datensätze oder den AUTO_INCREMENT-Wert des resultierenden Datensatzes nicht beim Server erfragen, weil die INSERT-Anweisung vor Durchführung der eigentlichen Einfügeoperation bereits abgeschlossen wird. (Wenn Sie die C-API verwenden, dann gibt die Funktion mysql_info() aus demselben Grund nur irrelevante Angaben zurück.)

  • Das Binärlog wird vom Handler-Thread aktualisiert, sobald der Datensatz in die Tabelle eingefügt wurde. Im Falle des Einfügens mehrerer Datensätze wird das Binärlog aktualisiert, wenn der erste Datensatz eingefügt wird.

  • Jedes Mal, wenn delayed_insert_limit Datensätze geschrieben wurden, überprüft der Handler, ob noch weitere SELECT-Anweisungen anhängig sind. Ist dies der Fall, so gestattet er deren Ausführung, bevor er fortfährt.

  • Wenn der Handler keine Datensätze mehr in der Warteschlange hat, wird die Tabelle entsperrt. Werden innerhalb des durch delayed_insert_timeout (in Sekunden) angegebenen Zeitraums keine neuen INSERT DELAYED-Anweisungen empfangen, dann wird der Handler beendet.

  • Sind mehr als delayed_queue_size Datensätze in einer bestimmten Handler-Warteschlange anhängig, dann fordert der Thread INSERT DELAYED auf, zu warten, bis wieder Platz in der Warteschlange ist. Hierdurch soll gewährleistet werden, dass mysqld nicht den gesamten Speicher für die Warteschlange mit den verzögerten Datensätzen verwendet.

  • Der Handler-Thread erscheint in der MySQL-Prozessliste als delayed_insert in der Spalte Command. Er wird terminiert, wenn Sie eine FLUSH TABLES-Anweisung absetzen oder KILL thread_id ausführen. Allerdings speichert er vor der Terminierung alle in der Warteschlange vorhandenen Datensätze in die Tabelle, bevor er beendet wird. In diesem Zeitraum werden keine neuen INSERT-Anweisungen anderer Threads angenommen. Wenn Sie nachfolgend eine INSERT DELAYED-Anweisung ausführen, wird ein neuer Handler-Thread erstellt.

    Beachten Sie, dass dies bedeutet, dass INSERT DELAYED-Anweisungen Vorrang vor normalen INSERT-Anweisungen haben, wenn ein INSERT DELAYED-Handler ausgeführt wird. Andere Änderungsanweisungen müssen warten, bis die INSERT DELAYED-Warteschlange leer ist oder jemand den Handler-Thread (mit KILL thread_id) terminiert oder eine FLUSH TABLES-Anweisung ausführt.

  • Die folgenden Statusvariablen machen Angaben zu INSERT DELAYED-Anweisungen:

    StatusvariableBedeutung
    Delayed_insert_threadsAnzahl der Handler-Threads
    Delayed_writesAnzahl der mit INSERT DELAYED geschriebenen Datensätze
    Not_flushed_delayed_rowsAnzahl der Datensätze, die noch geschrieben werden müssen

    Sie können diese Variablen anzeigen, indem Sie eine SHOW STATUS-Anweisung absetzen oder den Befehl mysqladmin extended-status ausführen.

13.2.4.3. INSERT ... ON DUPLICATE KEY UPDATE

Wenn Sie ON DUPLICATE KEY UPDATE angeben und ein Datensatz eingefügt wird, der einen doppelten Wert in einem eindeutigen Index oder einem Primärschlüssel erzeugen würde, dann wird für den alten Datensatz UPDATE ausgeführt. Angenommen, die Spalte a wird als UNIQUE deklariert und enthält den Wert 1; in diesem Fall hätten die beiden folgenden Anweisungen dieselbe Wirkung:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;

Der Wert der betroffenen Datensätze ist 1, wenn der Datensatz als neuer Datensatz eingefügt wird, und 2, wenn ein vorhandener Eintrag aktualisiert wird.

Wenn die Spalte b ebenfalls eindeutig ist, ist die INSERT-Anweisung stattdessen gleichbedeutend mit der folgenden UPDATE-Anweisung:

UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

Wenn a=1 OR b=2 mehreren Datensätzen entspricht, wird nur ein Datensatz aktualisiert. Generell sollten Sie von der Verwendung einer ON DUPLICATE KEY-Klausel bei Tabellen mit mehreren eindeutigen Indizes absehen.

Sie können die Funktion VALUES(col_name) in der UPDATE-Klausel verwenden, um Spaltenwerte aus dem INSERT-Teil der INSERT ... UPDATE-Anweisung zu referenzieren. Anders gesagt, verweist VALUES(col_name) in der UPDATE-Klausel auf den Wert von col_name, der eingefügt worden wäre, wäre nicht ein Konflikt aufgrund einer Schlüsseldublette aufgetreten. Diese Funktion ist insbesondere bei Einfügevorgängen für mehrere Datensätze praktisch. Die Funktion VALUES() ist nur in INSERT ... UPDATE-Anweisungen sinnvoll zu verwenden; andernfalls gibt sie NULL zurück. Beispiel:

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

Diese Anweisung ist identisch mit den folgenden beiden Anweisungen:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
  ON DUPLICATE KEY UPDATE c=9;

Die Option DELAYED wird ignoriert, wenn Sie ON DUPLICATE KEY UPDATE verwenden.

13.2.5. LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number LINES]
    [(col_name_or_user_var,...)]
    [SET col_name = expr,...)]

Die Anweisung LOAD DATA INFILE liest Datensätze mit extrem hoher Geschwindigkeit aus einer Textdatei in eine Tabelle ein. Der Dateiname muss als literaler String übergeben werden.

Die Syntax für die FIELDS- und LINES-Klauseln gilt auch für die SELECT ... INTO OUTFILE-Anweisung, die im weiteren Verlauf dieses Abschnitts beschrieben wird. (Siehe auch Abschnitt 13.2.7, „SELECT.)

Weitere Informationen zur Effektivität von INSERT im Vergleich zu LOAD DATA INFILE und zur Beschleunigung von LOAD DATA INFILE finden Sie in Abschnitt 7.2.16, „Geschwindigkeit von INSERT-Anweisungen“.

Der von der Systemvariablen character_set_database angegebene Zeichensatz wird zur Interpretation der Daten in der Datei verwendet. SET NAMES und die Einstellung von character_set_client wirken sich hingegen nicht auf die Interpretation der Eingabe aus.

Beachten Sie, dass es derzeit nicht möglich ist, Datendateien zu laden, die den Zeichensatz ucs2 verwenden.

Sie können Datendateien auch mithilfe des Hilfsprogramms mysqlimport laden; dieses sendet dann eine LOAD DATA INFILE-Anweisung an den Server. Die Option --local bewirkt, dass mysqlimport Datendateien vom Clienthost liest. Sie können die Option --compress angeben, um bei langsamen Netzwerken eine bessere Leistung zu erzielen, sofern Client und Server das Komprimierungsprotokoll unterstützen. Siehe auch Abschnitt 8.12, „mysqlimport — Programm zum Datenimport“.

Wenn Sie das Schlüsselwort LOW_PRIORITY angeben, wird die Ausführung von LOAD DATA verzögert, bis kein Client mehr aus der Tabelle liest.

Geben Sie CONCURRENT bei einer MyISAM-Tabelle an, die die Bedingungen für gleichzeitige Einfügeoperationen erfüllt (d. h. keine freien Blöcke in der Mitte enthält), dann können andere Threads Daten aus der Tabelle abrufen, während LOAD DATA ausgeführt wird. Die Verwendung dieser Option beeinflusst die Leistungsfähigkeit von LOAD DATA auch dann geringfügig, wenn gleichzeitig kein anderer Thread die Tabelle verwendet.

Das Schlüsselwort LOCAL wird, sofern angegeben, in Bezug auf die Clientseite der Verbindung interpretiert:

  • Wenn LOCAL angegeben ist, wird die Datei vom Clientprogramm auf dem Clienthost gelesen und an den Server geschickt. Die Datei kann als vollständiger Pfadname angegeben werden, um die exakte Position zu beschreiben. Erfolgt die Angabe als relativer Pfadname, dann wird der Name relativ zum Verzeichnis interpretiert, in dem das Clientprogramm gestartet wurde.

  • Wird LOCAL nicht angegeben, dann muss die Datei sich auf dem Serverhost befinden und wird direkt vom Server gelesen. Der Server wendet zur Bestimmung der Dateiposition die folgenden Regeln an:

    • Wenn der Dateiname absolut angegeben wurde, verwendet ihn der Server wie angegeben.

    • Ist der Dateiname ein relativer Pfadname mit einer oder mehreren am Anfang stehenden Komponenten, dann sucht der Server nach der Datei relativ zum eigenen Datenverzeichnis.

    • Wird ein Dateiname ohne Komponenten am Anfang übergeben, dann sucht der Server im Datenbankverzeichnis der Standarddatenbank nach der Datei.

Beachten Sie, dass, sofern keine LOCAL-Option angegeben wurde, die Regeln zur Folge haben, dass eine Datei namens ./myfile.txt im Datenverzeichnis des Servers gesucht wird, während die Datei myfile.txt aus dem Datenbankverzeichnis der Standarddatenbank gelesen wird. Ist also beispielsweise db1 die Standarddatenbank, dann liest die folgende LOAD DATA-Anweisung die Datei data.txt aus dem Datenbankverzeichnis für db1 aus, obwohl die Anweisung die Datei explizit in die Datenbank db2 lädt:

LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;

Windows-Pfadnamen müssen unter Verwendung von Schrägstrichen (statt Backslashs) angegeben werden. Wenn Sie Backslashs (umgekehrte Schrägstriche) verwenden, müssen Sie sie doppelt angeben.

Aus Sicherheitsgründen müssen Textdateien, die auf dem Server ausgelesen werden, entweder im Datenbankverzeichnis liegen oder von allen gelesen werden können. Außerdem benötigen Sie zur Verwendung von LOAD DATA INFILE für Serverdateien die Berechtigung FILE. Siehe auch Abschnitt 5.8.3, „Von MySQL zur Verfügung gestellte Berechtigungen“.

Die Verwendung von LOCAL ist ein wenig langsamer als der Direktzugriff des Servers auf die Dateien, weil der Inhalt der Datei vom Client über die Verbindung an den Server gesendet werden muss. Die Berechtigung FILE benötigen Sie hingegen zum Laden lokaler Dateien nicht.

Die Option LOCAL funktioniert nur, wenn ihre Verwendung sowohl am Client als auch am Server aktiviert wurde. Wenn beispielsweise mysqld mit --local-infile=0 gestartet wurde, funktioniert LOCAL nicht. Siehe auch Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL.

Unter Unix können Sie, wenn LOAD DATA über eine Pipe lesen soll, die folgende Methode verwenden (hierbei laden wir das Listing des Verzeichnisses / in eine Tabelle):

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
find / -ls > /mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

Die Schlüsselwörter REPLACE und IGNORE steuern den Umgang mit eingegebenen Datensätzen, die Duplikate vorhandener Datensätze mit eindeutigen Schlüsselwerten darstellen.

Wenn Sie REPLACE angeben, ersetzt die Eingabe vorhandene Datensätze. Dies betrifft Datensätze, die denselben Wert bei einem Primärschlüssel oder einem eindeutigen Index wie die neuen Datensätze haben. Siehe auch Abschnitt 13.2.6, „REPLACE.

Bei Angabe von IGNORE hingegen werden neue Datensätze, deren eindeutiger Schlüsselwert bereits einem vorhandenen Datensatz zugewiesen ist, ignoriert. Wenn Sie keine Option angeben, hängt das Verhalten davon ab, ob das Schlüsselwort LOCAL angegeben wird. Ohne LOCAL tritt ein Fehler auf, wenn ein doppelter Schlüsselwert gefunden wird; in diesem Fall wird der Rest der Textdatei ignoriert. Mit LOCAL ist das Standardverhalten so, als ob IGNORE angegeben worden wäre. Das liegt daran, dass der Server keine Möglichkeit hat, die Übertragung der Datei während des Vorgangs zu beenden.

Wenn Sie Fremdschlüssel-Constraints während des Ladevorgangs ignorieren wollen, können Sie eine SET FOREIGN_KEY_CHECKS=0-Anweisung vor der Ausführung von LOAD DATA absetzen.

Wenn Sie LOAD DATA INFILE auf eine leere MyISAM-Tabelle anwenden, werden alle nichteindeutigen Indizes in einer separaten Stapeloperation erstellt (wie bei REPAIR TABLE). Dies sollte LOAD DATA INFILE erheblich beschleunigen, wenn Sie viele Indizes haben. In einigen Extremfällen können Sie die Indizes noch schneller erstellen, indem Sie sie vor dem Einladen der Datei in die Tabelle mit ALTER TABLE ... DISABLE KEYS abschalten und sie nach Abschluss des Ladevorgangs mit ALTER TABLE ... ENABLE KEYS neu erstellen. Siehe auch Abschnitt 7.2.16, „Geschwindigkeit von INSERT-Anweisungen“.

LOAD DATA INFILE ist das Gegenstück zu SELECT ... INTO OUTFILE. (Siehe auch Abschnitt 13.2.7, „SELECT.) Um Daten aus einer Tabelle in eine Datei zu schreiben, benutzen Sie SELECT ... INTO OUTFILE; wollen Sie die Datei wieder in eine Tabelle einlesen, dann verwenden Sie LOAD DATA INFILE. Die Syntax der Klauseln FIELDS und LINES ist bei beiden Anweisungen dieselbe. Beide sind optional, aber FIELDS muss LINES vorangehen, sofern beide angegeben sind.

Wenn Sie eine FIELDS-Klausel festlegen, ist auch jede einzelne Unterklausel (TERMINATED BY, [OPTIONALLY] ENCLOSED BY und ESCAPED BY) ebenfalls optional – Sie müssen lediglich mindestens eine dieser Unterklauseln angeben.

Wenn Sie keine FIELDS-Klausel angeben, entsprechen die Vorgabeeinstellungen dem Folgenden:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

Wenn Sie keine LINES-Klausel angeben, entsprechen die Vorgabeeinstellungen dem Folgenden:

LINES TERMINATED BY '\n' STARTING BY ''

Anders gesagt, die Standardwerte bewirken, dass LOAD DATA INFILE sich beim Einlesen wie folgt verhält:

  • Es wird nach Zeilenbegrenzungen bei Zeilenumbrüchen gesucht.

  • Zeilenpräfixe werden nicht übersprungen.

  • Zeilen werden bei Tabulatoren in Felder unterteilt.

  • Felder müssen nicht innerhalb von Anführungszeichen abgeschlossen werden.

  • Fälle von Tabulatoren, Zeilenumbrüchen oder ‘\’, denen ‘\’ vorangeht, werden als literale Zeichen interpretiert, die Teile von Feldwerten sind.

Umgekehrt bewirken die Voreinstellungen, dass sich SELECT ... INTO OUTFILE beim Schreiben einer Ausgabe wie folgt verhält:

  • Tabulatoren werden zwischen Felder gesetzt.

  • Mehrere Felder werden nicht zwischen Anführungszeichen gesetzt.

  • \’ wird zur Kennzeichnung von Tabulatoren, Zeilenumbrüchen und ‘\’ verwendet, die innerhalb von Feldwerten auftreten.

  • Am Ende von Zeilen werden Zeilenumbrüche geschrieben.

Der Backslash wird bei MySQL als Escape-Zeichen in Strings verwendet. Insofern müssen Sie, um FIELDS ESCAPED BY '\\' zu schreiben, zwei Backslashes angeben, damit der Wert als ein Backslash interpretiert wird.

Hinweis: Wenn Sie die Textdatei auf einem Windows-System erzeugt haben, müssen Sie unter Umständen LINES TERMINATED BY '\r\n' verwenden, um die Datei korrekt einzulesen, weil Windows-Programme normalerweise zwei Zeichen als Zeilenendzeichen verwenden. Einige Programme wie WordPad verwenden beim Schreiben von Dateien unter Umständen sogar \r als Zeilenendzeichen. Um solche Dateien zu lesen, verwenden Sie LINES TERMINATED BY '\r'.

Wenn alle Zeilen, die Sie einlesen wollen, ein gemeinsames Präfix aufweisen, das Sie ignorieren wollen, können Sie mit LINES STARTING BY 'prefix_string' das Präfix und alles, was davor steht, überspringen. Enthält eine Zeile das Präfix gar nicht, dann wird die gesamte Zeile übersprungen. Nehmen wir an, dass Sie folgende Anweisung absetzen:

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test
  FIELDS TERMINATED BY ','  LINES STARTING BY 'xxx';

Nehmen wir ferner an, dass die Datendatei wie folgt aussieht:

xxx"abc",1
something xxx"def",2
"ghi",3

In diesem Fall werden als Ergebnis die Datensätze ("abc",1) und ("def",2) erzeugt. Der dritte Datensatz in der Datei wird übersprungen, weil er das Präfix nicht enthält.

Die Option IGNORE number LINES kann verwendet werden, um Zeilen am Anfang der Datei zu ignorieren. So können Sie etwa IGNORE 1 LINES angeben, um eine Kopfzeile zu überspringen, die etwa die Spaltennamen enthält:

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test IGNORE 1 LINES;

Wenn Sie SELECT ... INTO OUTFILE gemeinsam mit LOAD DATA INFILE verwenden, um Daten aus einer Datenbank in eine Datei zu schreiben und die Datei später wieder in die Datenbank einzulesen, dann müssen die Optionen der beiden Anweisungen zur Behandlung von Feldern und Zeilen einander entsprechen. Andernfalls kann LOAD DATA INFILE den Inhalt der Datei nicht korrekt einlesen. Angenommen, Sie schreiben mit SELECT ... INTO OUTFILE eine Datei mit Feldern, die kommagetrennt sind:

SELECT * INTO OUTFILE 'data.txt'
  FIELDS TERMINATED BY ','
  FROM table2;

Um diese kommagetrennte Datei wieder einzulesen, müssen Sie folgende Anweisung verwenden:

LOAD DATA INFILE 'data.txt' INTO TABLE table2
  FIELDS TERMINATED BY ',';

Haben Sie stattdessen probiert, die Datei mit der folgenden Anweisung einzulesen, dann ist dies nicht gelungen, da LOAD DATA INFILE angewiesen wird, nach Tabulatoren zwischen den Feldern zu suchen:

LOAD DATA INFILE 'data.txt' INTO TABLE table2
  FIELDS TERMINATED BY '\t';

Infolgedessen wird jede Eingabezeile wohl als separates Feld interpretiert werden.

Mit LOAD DATA INFILE können Sie Dateien lesen, die Sie aus externen Quellen erhalten haben. Beispielsweise exportieren viele Programme Daten als kommagetrennte Werte im so genannten CSV-Format (Comma-Separate Values). Hierbei werden die Felder durch Kommata voneinander getrennt und in doppelte Anführungszeichen gesetzt. Wenn Zeilen in einer solchen Datei durch Zeilenumbrüche abgeschlossen werden, veranschaulicht die folgende Anweisung die Optionen zur Feld- und Zeilenbehandlung, wie Sie sie zum Laden der Datei verwenden würden:

LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\n';

Alle Optionen zur Feld- und Zeilenbehandlung können einen Leer-String ('') angeben. Wenn der String nicht leer ist, müssen die Werte FIELDS [OPTIONALLY] ENCLOSED BY und FIELDS ESCAPED BY genau ein Zeichen umfassen. Die Werte FIELDS TERMINATED BY, LINES STARTING BY und LINES TERMINATED BY können hingegen auch mehrere Zeichen enthalten. Um etwa Zeilen zu schreiben, die jeweils aus einem aus einer Absatzschaltung und einem Zeilenvorschub bestehenden Zeichenpaar bestehen, geben Sie die Klausel LINES TERMINATED BY '\r\n' an.

Um eine Datei mit Witzen zu lesen, die durch aus %% bestehenden Zeilen getrennt sind, können Sie Folgendes tun:

CREATE TABLE jokes
  (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  joke TEXT NOT NULL);
LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
  FIELDS TERMINATED BY ''
  LINES TERMINATED BY '\n%%\n' (joke);

FIELDS [OPTIONALLY] ENCLOSED BY steuert die Anführungszeichen um die Felder. Bei der Ausgabe (SELECT ... INTO OUTFILE) werden, wenn Sie das Wort OPTIONALLY weglassen, alle Felder vom durch ENCLOSED BY angegebenen Zeichen umschlossen. Hier ein Beispiel für eine solche Ausgabe (mit dem Komma als Feldtrennzeichen):

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

Wenn Sie OPTIONALLY angeben, wird das ENCLOSED BY-Zeichen nur zum Umschließen von Werten in Spalten verwendet, die einen String-Datentyp haben (z. B. CHAR, BINARY, TEXT oder ENUM):

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

Beachten Sie, dass das Auftreten des ENCLOSED BY-Zeichens in einem Feldwert gekennzeichnet wird, indem man ihm das ESCAPED BY-Zeichen voranstellt. Ferner ist wichtig, dass es, wenn Sie einen leeren ESCAPED BY-Wert angeben, möglich ist, versehentlich eine Ausgabe zu erzeugen, die von LOAD DATA INFILE nicht korrekt eingelesen werden kann. Die obige Ausgabe beispielsweise würde wie folgt angezeigt werden, wenn das Escape-Zeichen leer wäre. Sie werden bemerken, dass das zweite Feld in der vierten Zeile ein auf das Anführungszeichen folgendes Komma enthält, welches das Feld abzuschließen scheint (was nicht zutrifft).

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

Bei der Eingabe wird das ENCLOSED BY-Zeichen – sofern vorhanden – am Ende der jeweiligen Feldwerte entfernt. (Dies erfolgt unabhängig davon, ob OPTIONALLY angegeben ist oder nicht – OPTIONALLY hat keine Auswirkung auf die Eingabeinterpretation.) Instanzen des ENCLOSED BY-Zeichens, denen das ESCAPED BY-Zeichen vorangestellt ist, werden als Teil des aktuellen Feldwerts interpretiert.

Beginnt das Feld mit dem ENCLOSED BY-Zeichen, dann werden Instanzen dieses Zeichens nur dann als Feldtrennzeichen ausgewertet, wenn ihnen jeweils die TERMINATED BY-Sequenz für Feld oder Zeile folgt. Um Mehrdeutigkeiten zu vermeiden, können Fälle des ENCLOSED BY-Zeichens innerhalb eines Feldwerts verdoppelt werden; sie werden dann als einzelne Instanz des Zeichens ausgewertet. Wird also etwa ENCLOSED BY '"' angegeben, dann wird mit Anführungszeichen wie hier gezeigt verfahren:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY steuert, wie Sonderzeichen geschrieben oder gelesen werden. Wenn das FIELDS ESCAPED BY-Zeichen nicht leer ist, dann wird es bei der Ausgabe als Präfix für die folgenden Zeichen verwendet:

  • FIELDS ESCAPED BY-Zeichen

  • FIELDS [OPTIONALLY] ENCLOSED BY-Zeichen

  • das erste Zeichen der Werte FIELDS TERMINATED BY und LINES TERMINATED BY

  • ASCII 0 (eigentlich wird auf das Escape-Zeichen folgend ASCII ‘0’ und kein Nullwertbyte geschrieben)

Ist das FIELDS ESCAPED BY-Zeichen leer, dann werden keinerlei Zeichen gekennzeichnet und NULL wird als NULL (und nicht als \N) ausgegeben. Es ist wahrscheinlich nicht angeraten, ein leeres Escape-Zeichen anzugeben; dies gilt insbesondere dann, wenn Feldwerte in Ihren Daten eines der in der obigen Liste enthaltenen Zeichen enthalten.

Wenn das FIELDS ESCAPED BY-Zeichen nicht leer ist, werden Instanzen dieses Zeichens bei der Eingabe entfernt, und das nachfolgende Zeichen wird literal als Teil des Feldwerts verwendet. Ausnahmen sind die gekennzeichneten Zeichen ‘0’ oder ‘N’ (z. B. \0 oder \N, wenn das Escape-Zeichen ‘\’ ist). Diese Sequenzen werden als ASCII-NUL (Nullwertbyte) bzw. als NULL interpretiert. Die Regeln für den Umgang mit NULL werden im weiteren Verlauf dieses Abschnitts beschrieben.

Weitere Informationen zur ‘\’-Escape-Syntax finden Sie in Abschnitt 9.1, „Literale: wie Strings und Zahlen geschrieben werden“.

In bestimmten Fällen interagieren die Optionen zur Feld- und Zeilenbehandlung:

  • Wenn LINES TERMINATED BY ein Leer-String und FIELDS TERMINATED BY nicht leer ist, werden Zeilen auch mit FIELDS TERMINATED BY abgeschlossen.

  • Sind die Werte von FIELDS TERMINATED BY und FIELDS ENCLOSED BY beide leer (''), dann wird ein festes Datensatzformat (ohne Trennzeichen) verwendet. Bei einem solchen Format fehlt zwar das Trennzeichen, ein Zeilenabschlusszeichen kann aber nichtsdestoweniger vorhanden sein. Stattdessen werden Spaltenwerte unter Berücksichtigung der Anzeigebreiten der Spalten geschrieben und gelesen. Wird z. B. eine Spalte als INT(7) deklariert, dann werden Werte für diese Spalte unter Verwendung von Feldern mit einer Länge von sieben Zeichen geschrieben. Bei der Eingabe werden die Spaltenwerte dann ermittelt, indem sieben Zeichen ausgelesen werden.

    LINES TERMINATED BY wird nach wie vor zur Trennung von Zeilen verwendet. Wenn eine Zeile nicht alle Felder enthält, werden die verbleibenden Spalten auf ihre Vorgabewerte gesetzt. Wenn kein Zeilenabschlusszeichen vorhanden ist, sollten Sie dieses auf '' setzen. In diesem Fall muss die Textdatei alle Felder für jeden Datensatz enthalten.

    Das Festformat für Datensätze beeinflusst auch den Umgang mit NULL-Werten (siehe unten). Beachten Sie, dass dieses Format nicht funktioniert, wenn Sie einen Multibytezeichensatz verwenden.

Die Handhabung von NULL-Werten variiert entsprechend den verwendeten FIELDS- und LINES-Optionen:

  • Bei den FIELDS- und LINES-Standardwerten wird NULL als Feldwert \N in die Ausgabe geschrieben. Analog wird der Feldwert \N bei der Eingabe als NULL gelesen (vorausgesetzt, das ESCAPED BY-Zeichen ist ‘\’).

  • Wenn FIELDS ENCLOSED BY nicht leer ist, dann wird ein Feld, das das Wort NULL als Wert enthält, als NULL-Wert gelesen. Dies unterscheidet sich von dem Wort NULL, wenn es in FIELDS ENCLOSED BY-Zeichen gesetzt ist – dieses wird als 'NULL' gelesen.

  • Ist FIELDS ESCAPED BY leer, dann wird NULL als Wort NULL geschrieben.

  • Beim Festformat (welches verwendet wird, wenn FIELDS TERMINATED BY und FIELDS ENCLOSED BY beide leer sind), wird NULL als Leer-String geschrieben. Beachten Sie, dass dies zur Folge hat, dass NULL-Werte und Leer-Strings in der Tabelle nicht mehr unterschieden werden können, sobald sie in die Datei geschrieben werden, weil beide als Leer-Strings geschrieben werden. Müssen die beiden Werte nach dem Wiedereinlesen der Datei weiterhin unterscheidbar sein, dann sollten Sie das Festformat nicht verwenden.

Manche Fälle werden von LOAD DATA INFILE nicht unterstützt:

  • Datensätze fester Länge (FIELDS TERMINATED BY und FIELDS ENCLOSED BY sind leer) und BLOB- oder TEXT-Spalten.

  • Wenn Sie ein Trennzeichen angeben, das mit einem anderen Trennzeichen (oder dessen Präfix) identisch ist, kann LOAD DATA INFILE die Eingabe nicht korrekt interpretieren. Die folgende FIELDS-Klausel beispielsweise würde Probleme verursachen:

    FIELDS TERMINATED BY '"' ENCLOSED BY '"'
    
  • Wenn FIELDS ESCAPED BY leer ist, bewirkt ein Feldwert, der eine Instanz von FIELDS ENCLOSED BY oder LINES TERMINATED BY gefolgt vom FIELDS TERMINATED BY-Wert enthält, dass LOAD DATA INFILE das Einlesen eines Felds oder einer Zeile zu früh beendet. Dies geschieht, weil LOAD DATA INFILE nicht genau bestimmen kann, wo der Feld- oder Zeilenwert endet.

Das folgende Beispiel lädt alle Spalten der Tabelle persondata:

LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Standardmäßig wird, wenn keine Spaltenliste am Ende der LOAD DATA INFILE-Anweisung vorhanden ist, erwartet, dass Eingabezeilen ein Feld für jede Tabellenspalte enthalten. Wenn Sie nur einen Teil der Spalten einer Tabelle laden wollen, müssen Sie eine Spaltenliste angeben:

LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);

Ferner müssen Sie eine Spaltenliste festlegen, wenn die Reihenfolge der Felder in der Eingabedatei sich von der Reihenfolge der Spalten in der Tabelle unterscheidet. Andernfalls kann MySQL nicht ermitteln, wie die Eingabefelder den Tabellenspalten zuzuordnen sind.

Die Spaltenliste kann entweder Spaltennamen oder Benutzervariablen enthalten. Bei Benutzervariablen gestattet Ihnen die SET-Klausel die Durchführung einer Werteumwandlung vor der Zuweisung des Ergebnisses zu den Spalten.

Benutzervariablen in der SET-Klausel können auf unterschiedliche Weise verwendet werden. Die folgenden Werte benutzen die erste Eingabespalte direkt für den Wert von t1.column1 und weisen die zweite Eingabespalte einer Benutzervariablen zu, an der eine Division durchgeführt wird, bevor sie als Wert für t1.column2 verwendet wird:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @var1)
  SET column2 = @var1/100;

Die SET-Klausel kann zur Übermittlung von Werten benutzt werden, die nicht der Eingabedatei entnommen wurden. Die folgende Anweisung weist column3 das aktuelle Datum und die Uhrzeit zu:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, column2)
  SET column3 = CURRENT_TIMESTAMP;

Sie können einen Eingabewert auch verwerfen, indem Sie ihn einer Benutzervariablen zuweisen, der Variablen aber keine Tabellenspalte zuordnen:

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @dummy, column2, @dummy, column3);

Die Verwendung der Spalten-/Variablenliste und der SET-Klausel ist den folgenden Einschränkungen unterworfen:

  • Zuordnungen in der SET-Klausel sollten auf der linken Seite des Zuweisungsoperators nur Spaltennamen aufweisen.

  • Auf der rechten Seite einer SET-Zuordnung dürfen auch Unterabfragen zum Einsatz kommen. Eine Unterabfrage, die einen Wert zurückgibt, der einer Spalte zugeordnet werden soll, darf nur eine skalare Unterabfrage sein. Außerdem können Sie eine Unterabfrage nicht für Auswahlabfragen an die Tabelle verwenden, die gerade geladen wird.

  • Zeilen, die von einer IGNORE-Klausel ignoriert werden, werden für die Spalten-/Variablenliste oder die SET-Klausel nicht verarbeitet.

  • Benutzervariablen können nicht verwendet werden, wenn Daten mit Festformat geladen werden, da Benutzervariablen keine Anzeigebreite haben.

Wenn eine Eingabezeile verarbeitet wird, unterteilt LOAD DATA sie in Felder und verwendet die Werte entsprechend der Spalten-/Variablenliste und der SET-Klausel, sofern diese vorhanden sind. Der Ergebnisdatensatz wird dann in die Tabelle eingefügt. Sind BEFORE INSERT- oder AFTER INSERT-Trigger für die Tabelle vorhanden, so werden diese vor bzw. nach dem Einfügen des Datensatzes aktiviert.

Hat eine Eingabezeile zu viele Felder, dann werden die überzähligen Felder ignoriert und die Anzahl der Warnungen wird erhöht.

Hat eine Eingabezeile zu wenig Felder, dann werden die Tabellenspalten, deren Eingabefelder fehlen, auf ihre Standardwerte gesetzt. Die Zuweisung von Standardwerten ist in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben.

Ein leerer Feldwert wird anders interpretiert als ein fehlender Feldwert:

  • Bei String-Typen wird die Spalte auf den Leer-String gesetzt.

  • Bei numerischen Typen wird die Spalte auf 0 gesetzt.

  • Bei zeitbezogenen Typen wird die Spalte auf den passenden „Nullwert“ des Typs gesetzt. Siehe auch Abschnitt 11.3, „Datums- und Zeittypen“.

Dies sind dieselben Werte, die als Ergebnis ausgegeben werden, wenn Sie einem String, einem numerischen oder einem zeitbezogenen Wert in einer INSERT- oder UPDATE-Anweisung explizit den Leer-String zuweisen.

TIMESTAMP-Spalten werden nur dann auf die aktuellen Werte für Datum und Uhrzeit gesetzt, wenn ein NULL-Wert (d. h. \N) für die Spalte vorhanden ist oder der Standardwert der TIMESTAMP-Spalte der aktuelle Zeitstempel ist und in der Feldliste (sofern vorhanden) weggelassen wurde.

LOAD DATA INFILE betrachtet alle Eingaben als Strings, d. h., Sie können für ENUM- oder SET-Spalten numerische Werte nicht so eingeben wie von INSERT-Anweisungen her gewohnt. Alle ENUM- und SET-Werte müssen als Strings angegeben werden.

Wenn die LOAD DATA INFILE-Anweisung abgeschlossen ist, gibt sie einen Informations-String im folgenden Format zurück:

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Wenn Sie die C-API verwenden, können Sie Informationen zur Anweisung durch einen Aufruf der Funktion mysql_info() ermitteln. Siehe auch Abschnitt 24.2.3.34, „mysql_info().

Warnungen treten unter denselben Umständen auf wie beim Einfügen von Werten mithilfe der INSERT-Anweisung (siehe Abschnitt 13.2.4, „INSERT); der einzige Unterschied besteht darin, dass LOAD DATA INFILE auch dann Warnungen erzeugt, wenn zu wenig oder zu viel Felder im Eingabedatensatz vorhanden sind. Die Warnungen werden nirgends gespeichert; Sie können ihrer Anzahl lediglich entnehmen, ob alles geklappt hat oder nicht.

Mit SHOW WARNINGS erhalten Sie eine Liste der ersten max_error_count Warnungen mit Informationen dazu, was unter Umständen nicht geklappt hat. Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS.

13.2.6. REPLACE

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...

Oder:

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...

Oder:

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...

REPLACE funktioniert auf exakt gleiche Weise wie INSERT. Der Unterschied besteht darin, dass, wenn ein alter Datensatz denselben Wert wie ein neuer Datensatz für einen Primärschlüssel oder einen eindeutigen Index hat, der alte Datensatz gelöscht wird, bevor der neue eingefügt wird. Siehe auch Abschnitt 13.2.4, „INSERT.

REPLACE ist eine MySQL-Erweiterung zum SQL-Standard. Es kann Datensätze einfügen, oder es kann Datensätze löschen und einfügen. Wenn Sie eine Anweisung suchen, die dem SQL-Standard entspricht und die entweder einfügt oder aktualisiert, dann benutzen Sie die INSERT ... ON DUPLICATE KEY UPDATE-Anweisung (siehe auch Abschnitt 13.2.4.3, „INSERT ... ON DUPLICATE KEY UPDATE).

Beachten Sie, dass, sofern die Tabelle nicht einen Primärschlüssel oder einen eindeutigen Index hat, die Verwendung von REPLACE unsinnig ist. Die Anweisung wäre dann mit INSERT identisch, weil kein Index vorhanden ist, anhand dessen bestimmt werden könnte, ob ein neuer Datensatz ein Duplikat eines bereits vorhandenen darstellt.

Werte für alle Spalten werden den Werten entnommen, die in der REPLACE-Anweisung angegeben sind. Fehlende Spalten werden – wie bei INSERT – auf ihre Standardwerte gesetzt. Es ist nicht möglich, Werte aus dem aktuellen Datensatz zu referenzieren und diese dann im neuen Datensatz zu verwenden. Wenn Sie eine Zuordnung wie SET col_name = col_name + 1 verwenden, wird die Referenzierung des Spaltennamens auf der rechten Seite wie DEFAULT(col_name) behandelt, d. h., die Zuordnung ist äquivalent zu SET col_name = DEFAULT(col_name) + 1.

Um REPLACE zu verwenden, benötigen Sie die Berechtigungen INSERT und DELETE für die Tabelle.

Die REPLACE-Anweisung gibt einen Wert zurück, der die Anzahl der betroffenen Datensätze angibt. Konkret ist dies die Summe der gelöschten und eingefügten Datensätze. Wenn der Wert bei einer REPLACE-Anweisung für einen Datensatz 1 beträgt, dann wurde ein Datensatz eingefügt und keiner gelöscht. Ist der Wert größer als 1, dann wurden ein oder mehrere alte Datensätze gelöscht, bevor der neue Datensatz eingefügt wurde. Ein einzelner Datensatz kann durchaus mehr als nur einen alten Datensatz ersetzen, sofern die Tabelle mehrere eindeutige Indizes hat und der neue Datensatz Werte verschiedener alter Datensätze in verschiedenen eindeutigen Indizes dupliziert.

Die Anzahl der betroffenen Datensätze erlaubt also die einfache Bestimmung, ob REPLACE nur einen Datensatz hinzugefügt hat oder ob auch Datensätze ersetzt wurden: Überprüfen Sie, ob der Wert 1 (Hinzufügung) oder größer ist (Ersetzung).

Wenn Sie die C-API verwenden, kann die Anzahl der betroffenen Datensätze durch die Funktion mysql_affected_rows() ermittelt werden.

Zurzeit können Sie in einer Unterabfrage keine Ersetzungsoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.

MySQL verwendet für REPLACE (und LOAD DATA ... REPLACE) den folgenden Algorithmus:

  1. Es wird versucht, den neuen Datensatz in die Tabelle einzufügen.

  2. Wenn die Einfügeoperation aufgrund einer Schlüsseldublette in einem Primärschlüssel oder einem eindeutigen Index fehlschlägt,

    1. wird der konfliktauslösende Datensatz mit dem doppelten Schlüsselwert aus der Tabelle entfernt,

    2. wird erneut versucht, den neuen Datensatz in die Tabelle einzufügen.

13.2.7. SELECT

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [FROM table_references
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name' export_options
      | INTO DUMPFILE 'file_name']
    [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT wird zum Abrufen von Datensätzen verwendet, die aus einer oder mehreren Tabellen ausgewählt wurden, und kann UNION-Anweisungen und Unterabfragen enthalten. Siehe auch Abschnitt 13.2.7.2, „UNION, und Abschnitt 13.2.8, „Syntax von Unterabfragen“.

Die meistverwendeten Klauseln für SELECT sind die folgenden:

  • Jede select_expr gibt eine Spalte an, die Sie abrufen wollen. Es muss mindestens ein select_expr vorhanden sein.

  • table_references gibt die Tabelle(n) an, aus der oder denen die Datensätze abgerufen werden sollen. Die Syntax ist in Abschnitt 13.2.7.1, „JOIN, beschrieben.

  • Die WHERE-Klausel gibt, soweit vorhanden, die Bedingung(en) an, die Datensätze erfüllen müssen, damit sie ausgewählt werden. where_condition ist ein Ausdruck, der für jeden auszuwählenden Datensatz wahr ist. Die Anweisung wählt, wenn keine WHERE-Klausel vorhanden ist, alle Datensätze aus.

    Sie können in der WHERE-Klausel alle von MySQL unterstützten Funktionen und Operatoren mit Ausnahme der Zusammenfassungsfunktionen einsetzen. Siehe auch Kapitel 12, Funktionen für die Benutzung in SELECT- und WHERE-Klauseln.

SELECT kann auch verwendet werden, um Datensätze abzurufen, die ohne Referenzierung einer Tabelle berechnet wurden.

Zum Beispiel:

mysql> SELECT 1 + 1;
        -> 2

Sie können DUAL als Pseudotabellenname in Situationen angeben, in denen keine Tabellen referenziert werden:

mysql> SELECT 1 + 1 FROM DUAL;
        -> 2

DUAL ist ausschließlich zum Zweck der Kompatibilität mit anderen Datenbankservern vorhanden, die eine FROM-Klausel erfordern. MySQL benötigt keine solche Klausel, wenn keine Tabellen referenziert werden.

Generell müssen Klauseln in genau der Reihenfolge angegeben werden, die in der Syntaxbeschreibung erscheint. So muss etwa eine HAVING-Klausel hinter den GROUP BY-Klauseln und vor den ORDER BY-Klauseln stehen. Die einzige Ausnahme ist die INTO-Klausel, die entweder wie in der Syntaxbeschreibung gezeigt oder unmittelbar vor der FROM-Klausel stehen kann.

  • Einem Ausdruck select_expr lässt sich mit AS alias_name ein Alias zuweisen. Der Alias wird als Spaltenname des Ausdrucks benutzt und kann in GROUP BY-, ORDER BY- oder HAVING-Klauseln verwendet werden. Zum Beispiel:

    SELECT CONCAT(last_name,', ',first_name) AS full_name
      FROM mytable ORDER BY full_name;
    

    Das Schlüsselwort AS ist beim Zuweisen eines Alias zu select_expr optional. Das obige Beispiel hätte auch wie folgt geschrieben sein können:

    SELECT CONCAT(last_name,', ',first_name) full_name
      FROM mytable ORDER BY full_name;
    

    Allerdings kann, weil AS optional ist, ein kleines Problem auftreten, wenn Sie das Komma zwischen zwei select_expr-Ausdrücken vergessen: MySQL interpretiert den zweiten Ausdruck als Aliasnamen. Sie wird etwa in der folgenden Anweisung columnb als Aliasname behandelt:

    SELECT columna columnb FROM mytable;
    

    Aus diesem Grund hat es sich bewährt, AS beim Festlegen von Spaltenaliasen immer explizit anzugeben.

  • Es ist nicht zulässig, einen Spaltenalias in einer WHERE-Klausel zu verwenden, weil der Spaltenwert unter Umständen nicht bestimmt werden kann, wenn die WHERE-Klausel ausgeführt wird. Siehe auch Abschnitt A.5.4, „Probleme mit alias.

  • Die Klausel FROM table_references gibt die Tabelle(n) an, aus der oder denen die Datensätze abgerufen werden sollen. Wenn Sie mehr als eine Tabelle angeben, führen Sie einen Join durch. Informationen zur Join-Syntax finden Sie in Abschnitt 13.2.7.1, „JOIN. Für jede angegebene Tabelle können Sie optional einen Alias angeben.

    tbl_name [[AS] alias]
        [{USE|IGNORE|FORCE} INDEX (key_list)]
    

    Wie Sie dem Optimierer mit USE INDEX, IGNORE INDEX und FORCE INDEX Hinweise zur Auswahl der Indizes geben, ist in Abschnitt 13.2.7.1, „JOIN, beschrieben.

    Sie können SET max_seeks_for_key=value als alternative Möglichkeit verwenden, um MySQL zur Verwendung von Schlüssel- statt Tabellenscans (sofern möglich) zu zwingen. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“.

  • Sie können eine Tabelle in der Standarddatenbank als tbl_name oder – wenn Sie eine Datenbank ausdrücklich angeben wollen – als db_name.tbl_name referenzieren. Eine Spalte können Sie als col_name, tbl_name.col_name oder db_name.tbl_name.col_name referenzieren. Sie müssen das Präfix tbl_name oder db_name.tbl_name für eine Spaltenreferenzierung nicht angeben, sofern die Referenzierung eindeutig ist. Beispiele für Mehrdeutigkeiten, die die spezifischeren Formen der Spaltenreferenzierung erfordern, finden Sie in Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“.

  • Für einen Tabellenverweis kann mit tbl_name AS alias_name oder tbl_name alias_name ein Alias erstellt werden:

    SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      WHERE t1.name = t2.name;
    
    SELECT t1.name, t2.salary FROM employee t1, info t2
      WHERE t1.name = t2.name;
    
  • Spalten, die für die Ausgabe ausgewählt werden, lassen sich in ORDER BY- und GROUP BY-Klauseln als Spaltennamen, Spaltenaliase oder Spaltenpositionen referenzieren. Spaltenpositionen sind ganze Zahlen, die bei 1 beginnen:

    SELECT college, region, seed FROM tournament
      ORDER BY region, seed;
    
    SELECT college, region AS r, seed AS s FROM tournament
      ORDER BY r, s;
    
    SELECT college, region, seed FROM tournament
      ORDER BY 2, 3;
    

    Um in umgekehrter (absteigender) Reihenfolge zu sortieren, fügen Sie in der ORDER BY-Klausel das Schlüsselwort DESC zum Namen der Spalte zu, nach der die Sortierung erfolgt: Standardmäßig erfolgt die Sortierung aufsteigend. Dies kann mit dem Schlüsselwort ASC explizit festgelegt werden.

    Die Verwendung von Spaltenpositionen ist veraltet, weil die Syntax im SQL-Standard nicht mehr vorhanden ist.

  • Wenn Sie GROUP BY verwenden, werden die Ausgabedatensätze entsprechend den GROUP BY-Spalten sortiert, so als ob Sie eine ORDER BY-Klausel für dieselben Spalten angegeben hätten. Um eine Mehrbelastung durch das Sortieren mit GROUP BY zu vermeiden, fügen Sie ORDER BY NULL hinzu:

    SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
    
  • MySQL erweitert die GROUP BY-Klausel dahingehend, dass Sie ASC und DESC auch nach den in der Klausel benannten Spalten angeben können:

    SELECT a, COUNT(b) FROM test_table GROUP BY a DESC;
    
  • MySQL erweitert die Verwendung von GROUP BY so, dass die Auswahl von Feldern möglich ist, die in der GROUP BY-Klausel nicht genannt sind. Wenn Sie bei einer Abfrage nicht die erwarteten Ergebnisse erhalten, lesen Sie bitte die Beschreibung von GROUP BY in Abschnitt 12.11, „Funktionen und Modifizierer für die Verwendung in GROUP BY-Klauseln“.

  • GROUP BY unterstützt den Modifizierer WITH ROLLUP. Siehe auch Abschnitt 12.11.2, „GROUP BY-Modifizierer“.

  • Die HAVING-Klausel wird fast als Letztes angewandt – unmittelbar bevor die Elemente an den Client gesendet werden, und ohne Optimierung. (Nur LIMIT wird noch nach HAVING angewandt.)

    Der SQL-Standard sieht vor, dass HAVING nur Spalten in der GROUP BY-Klausel oder solche Spalten referenzieren darf, die in Zusammenfassungsfunktionen verwendet werden. Allerdings unterstützt MySQL eine Erweiterung dieses Verhaltens und gestattet HAVING ferner die Referenzierung von Spalten in der SELECT-Liste und Spalten in äußeren Unterabfragen.

    Wenn die HAVING-Klausel eine Spalte referenziert, die mehrdeutig ist, erscheint eine Warnung. In der folgenden Anweisung ist col2 mehrdeutig, weil es sowohl als Alias als auch als Spaltenname verwendet wird:

    SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
    

    Hier wird das SQL-Standardverhalten angewandt, d. h., wenn ein HAVING-Spaltenname sowohl in einer GROUP BY-Klausel als auch als Spaltenalias in der Liste der Ausgabespalten enthalten ist, hat die Spalte in der GROUP BY-Spalte Vorrang.

  • Verwenden Sie HAVING nicht für Elemente, die in der WHERE-Klausel aufgeführt sein sollten. So sollten Sie beispielsweise nicht Folgendes schreiben:

    SELECT col_name FROM tbl_name HAVING col_name > 0;
    

    Formulieren Sie stattdessen wie folgt:

    SELECT col_name FROM tbl_name WHERE col_name > 0;
    
  • Die HAVING-Klausel kann Zusammenfassungsfunktionen referenzieren, was der WHERE-Klausel nicht möglich ist:

    SELECT user, MAX(salary) FROM users
      GROUP BY user HAVING MAX(salary) > 10;
    

    (Dies funktionierte bei einigen älteren MySQL-Versionen nicht.)

  • Die LIMIT-Klausel kann zur Beschränkung der Anzahl der von der SELECT-Anweisung zurückgegebenen Datensätze verwendet werden. LIMIT nimmt ein oder zwei numerische Argumente entgegen, die (außer bei Verwendung vorbereiteter Anweisungen) beide nichtnegative Integer-Konstanten sein müssen.

    Von den beiden Argumenten gibt das erste den Versatz des ersten zurückzugebenden Datensatzes an, das zweite die maximale Anzahl zurückzugebender Datensätze. Der Versatz des ersten Datensatzes ist 0 (nicht 1):

    SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15
    

    Um alle Datensätze beginnend bei einem bestimmten Versatz bis zum Ende der Ergebnismenge zurückzugeben, können Sie als zweiten Parameter eine sehr große Zahl angeben. Die folgende Anweisung ruft alle Datensätze beginnend beim 96. bis zum letzten Datensatz ab:

    SELECT * FROM tbl LIMIT 95,18446744073709551615;
    

    Sofern nur ein Argument angegeben ist, gibt der Wert die Anzahl der Datensätze an, die beginnend beim ersten Datensatz zurückgegeben werden sollen:

    SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows
    

    Anders gesagt, ist LIMIT row_count äquivalent zu LIMIT 0, row_count.

    Bei vorbereiteten Anweisungen können Sie Platzhalter verwenden. Die folgende Anweisung gibt genau einen Datensatz aus der Tabelle tbl zurück:

    SET @a=1;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?';
    EXECUTE STMT USING @a;
    

    Die folgenden Anweisungen geben den zweiten bis sechsten Datensatz aus der Tabelle tbl zurück:

    SET @skip=1; SET @numrows=5;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?';
    EXECUTE STMT USING @skip, @numrows;
    

    Aus Gründen der Kompatibilität mit PostgreSQL unterstützt MySQL auch die Syntax LIMIT row_count OFFSET offset.

  • Die Form SELECT ... INTO OUTFILE 'file_name' der SELECT-Anweisung schreibt die ausgewählten Datensätze in eine Datei. Die Datei wird auf dem Serverhost erstellt, d. h., Sie benötigen die Berechtigung FILE, um die Syntax verwenden zu können. file_name darf keine vorhandene Datei sein, wodurch u. a. verhindert werden soll, dass Dateien wie /etc/passwd und Datenbanktabellen zerstört werden.

    Die Anweisung SELECT ... INTO OUTFILE ist in erster Linie dazu vorgesehen, eine Tabelle sehr schnell in eine Textdatei auf dem Server zu speichern. Wenn Sie die resultierende Datei auf einem Clienthost statt auf dem Serverhost erstellen wollen, dürfen Sie SELECT ... INTO OUTFILE nicht verwenden. In diesem Fall sollten Sie stattdessen einen Befehl wie mysql -e "SELECT ..." > file_name benutzen, um die Datei auf dem Clienthost anzulegen.

    SELECT ... INTO OUTFILE ist das Gegenstück zu LOAD DATA INFILE. Die Syntax für den export_options-Teil der Anweisung umfasst dieselben FIELDS- und LINES-Klauseln, die bei LOAD DATA INFILE benutzt werden. Siehe auch Abschnitt 13.2.5, „LOAD DATA INFILE.

    FIELDS ESCAPED BY steuert, wie Sonderzeichen geschrieben werden. Wenn das FIELDS ESCAPED BY-Zeichen nicht leer ist, dann wird es bei der Ausgabe als Präfix für die folgenden Zeichen verwendet:

    • FIELDS ESCAPED BY-Zeichen

    • FIELDS [OPTIONALLY] ENCLOSED BY-Zeichen

    • das erste Zeichen der Werte FIELDS TERMINATED BY und LINES TERMINATED BY

    • ASCII NUL (das Nullwertbyte; eigentlich wird auf das Escape-Zeichen folgend ASCII ‘0’ und kein Nullwertbyte geschrieben)

    Die FIELDS TERMINATED BY-, ENCLOSED BY-, ESCAPED BY- oder LINES TERMINATED BY-Zeichen müssen mit Escape-Zeichen gekennzeichnet werden, damit Sie die Datei zuverlässig wiedereinlesen können. ASCII NUL wird gekennzeichnet, um das Ablesen bei manchen Pagern zu vereinfachen.

    Die Ergebnisdatei muss nicht der SQL-Syntax entsprechen, weswegen weitere Zeichen nicht gekennzeichnet werden müssen.

    Ist das FIELDS ESCAPED BY-Zeichen leer, dann werden keinerlei Zeichen gekennzeichnet und NULL wird als NULL (und nicht als \N) ausgegeben. Es ist wahrscheinlich nicht angeraten, ein leeres Escape-Zeichen anzugeben; dies gilt insbesondere dann, wenn Feldwerte in Ihren Daten eines der in der obigen Liste enthaltenen Zeichen enthalten.

    Es folgt ein Beispiel, das eine Datei im CSV-Format erzeugt, welches von vielen Programmen verwendet wird:

    SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt'
      FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
      LINES TERMINATED BY '\n'
      FROM test_table;
    
  • Wenn Sie INTO DUMPFILE statt INTO OUTFILE verwenden, schreibt MySQL nur einen Datensatz ohne Spalten- oder Zeilentrennzeichen und ohne Escape-Kennzeichnung in die Datei. Dies ist praktisch, wenn Sie einen BLOB-Wert in die Datei speichern wollen.

  • Hinweis: In Dateien, die durch INTO OUTFILE oder INTO DUMPFILE erstellt wurden, kann von allen Benutzern geschrieben werden. Grund hierfür ist die Tatsache, dass der MySQL Server keine Datei erstellen kann, deren Besitzer jemand anders als der Benutzer ist, unter dessen Konto der Server ausgeführt wird. (Sie sollten aus diesem und anderen Gründen mysqld niemals als root ausführen.) Die Datei muss von allen schreibbar sein, damit Sie ihren Inhalt modifizieren können.

  • Die Beschreibung der SELECT-Syntax am Anfang dieses Abschnitts zeigt die INTO-Klausel gegen Ende der Anweisung. INTO OUTFILE oder INTO DUMPFILE können auch unmittelbar auf die FROM-Klausel folgend angegeben werden.

  • Eine PROCEDURE-Klausel benennt eine Prozedur, die die Daten in der Ergebnismenge verarbeitet. Ein Beispiel finden Sie in Abschnitt 26.4.1, „PROCEDURE ANALYSE“.

  • Wenn Sie FOR UPDATE mit einer Speicher-Engine verwenden, die Seiten- oder Datensatzsperren verwendet, dann werden die von der Abfrage untersuchten Datensätze bis zum Ende der laufenden Transaktion schreibgesperrt. Mithilfe von LOCK IN SHARE MODE wird eine gemeinsame Sperre gesetzt, die anderen Transaktionen das Lesen, nicht jedoch das Ändern oder Löschen der untersuchten Datensätze gestattet. Siehe auch Abschnitt 14.2.10.5, „Lesevorgänge sperren“.

Sie können auf das Schlüsselwort SELECT folgend eine Reihe von Optionen angeben, die den Betrieb der Anweisung beeinflusst.

Die Optionen ALL, DISTINCT und DISTINCTROW geben an, ob doppelte Datensätze zurückgegeben werden sollen. Wird keine dieser Optionen angegeben, dann wird ALL als Vorgabe vorausgesetzt (d. h., alle passenden Datensätze werden zurückgegeben). DISTINCT und DISTINCTROW sind Synonyme; sie legen fest, dass doppelte Datensätze aus der Ergebnismenge entfernt werden.

HIGH_PRIORITY, STRAIGHT_JOIN und Optionen, die mit SQL_ beginnen, sind MySQL-Erweiterungen zum SQL-Standard.

  • HIGH_PRIORITY gibt SELECT Vorrang vor einer Anweisung, die eine Tabelle aktualisiert. Sie sollten die Option nur bei Abfragen verwenden, die sehr schnell sind und sofort erledigt werden müssen. Eine SELECT HIGH_PRIORITY-Anweisung, die abgesetzt wird, während die Tabelle zum Lesen gesperrt ist, wird auch ausgeführt, wenn eine Aktualisierungsanweisung darauf wartet, dass die Tabelle frei wird.

    HIGH_PRIORITY kann nicht bei SELECT-Anweisungen verwendet werden, die Teil einer Union sind.

  • STRAIGHT_JOIN zwingt den Optimierer zur Verknüpfung der Tabellen in der Reihenfolge, in der sie in der FROM-Klausel angegeben sind. Sie können hiermit eine Abfrage beschleunigen, wenn der Optimierer die Tabellen nicht optimal anordnet. Siehe auch Abschnitt 7.2.1, „EXPLAIN-Syntax (Informationen über ein SELECT erhalten)“. STRAIGHT_JOIN kann auch in der table_references-Liste angegeben werden. Siehe auch Abschnitt 13.2.7.1, „JOIN.

  • SQL_BIG_RESULT kann mit GROUP BY oder DISTINCT verwendet werden. Sie teilen dem Optimierer hierdurch mit, dass die Ergebnismenge viele Datensätze enthält. In diesem Fall verwendet MySQL bei Bedarf direkt festplattenbasierte Temporärtabellen und zieht die Sortierung der Verwendung einer Temporärtabelle mit einem Schlüssel auf GROUP BY-Elemente vor.

  • SQL_BUFFER_RESULT erzwingt das Ablegen des Ergebnisses in einer Temporärtabelle. Auf diese Weise kann MySQL die Tabellensperren schnell wieder aufheben. Die Option ist zudem in Fällen hilfreich, in denen die Übermittlung des Ergebnisses an den Client sehr lange dauert.

  • SQL_SMALL_RESULT kann mit GROUP BY oder DISTINCT verwendet werden. Sie teilen dem Optimierer hierdurch mit, dass die Ergebnismenge klein ist. In diesem Fall verwendet MySQL schnelle Temporärtabellen zur Speicherung der Ergebnistabelle anstelle einer Sortierung. Normalerweise werden Sie diese Option nicht benötigen.

  • SQL_CALC_FOUND_ROWS weist MySQL an, zu berechnen, wie viele Datensätze ohne Berücksichtigung einer ggf. vorhandenen LIMIT-Klausel in der Ergebnismenge enthalten wären. Die Anzahl der Datensätze kann dann mit SELECT FOUND_ROWS() abgerufen werden. Siehe auch Abschnitt 12.10.3, „Informationsfunktionen“.

  • Mit SQL_CACHE weisen Sie MySQL an, das Abfrageergebnis im Abfrage-Cache zu speichern, wenn Sie einen query_cache_type-Wert von 2 oder DEMAND verwenden. Bei einer Abfrage, die UNION oder Unterabfragen verwendet, betrifft diese Option alle SELECT-Klauseln in der Abfrage. Siehe auch Abschnitt 5.14, „MySQL-Anfragen-Cache“.

  • SQL_NO_CACHE weist MySQL an, das Abfrageergebnis nicht im Abfrage-Cache zu speichern. Siehe auch Abschnitt 5.14, „MySQL-Anfragen-Cache“. Bei einer Abfrage, die UNION oder Unterabfragen verwendet, betrifft diese Option alle SELECT-Klauseln in der Abfrage.

13.2.7.1. JOIN

MySQL unterstützt die folgenden JOIN-Syntaxen für den table_references-Teil von SELECT-Anweisungen sowie von DELETE- und UPDATE-Anweisungen für mehrere Tabellen:

table_references:
    table_reference [, table_reference] ...

table_reference:
    table_factor
  | join_table

table_factor:
    tbl_name [[AS] alias]
        [{USE|IGNORE|FORCE} INDEX (key_list)]
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }

join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor ON condition
  | table_reference LEFT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
  | table_reference RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor

join_condition:
    ON conditional_expr
  | USING (column_list)

Eine Tabellenreferenzierung heißt auch Join-Ausdruck.

Die Syntax von table_factor ist im Vergleich zum SQL-Standard erweitert. SQL akzeptiert nur table_reference, nicht aber eine in Klammern gesetzte Liste mit Referenzierungen.

Dies ist eine konservative Erweiterung, sofern wir jedes Komma in einer Liste mit table_reference-Elementen als äquivalent zu einem inneren Join betrachten. Zum Beispiel:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

ist äquivalent mit

SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

In MySQL ist CROSS JOIN syntaktisch ein Äquivalent zu INNER JOIN (diese lassen sich gegeneinander austauschen). Nach SQL-Standard hingegen sind beide nicht äquivalent. INNER JOIN wird bei einer ON-Klausel und CROSS JOIN andernfalls verwendet.

Klammern können in Join-Ausdrücken, die nur innere Join-Operationen enthalten, ignoriert werden. MySQL unterstützt auch verschachtelte Joins (siehe auch Abschnitt 7.2.10, „Optimierung verschachtelter Joins“).

Im ON-Teil sollten keine Bedingungen vorhanden sein, die zur Beschränkung der Datensätze in der Ergebnismenge verwendet werden; geben Sie solche Bedingungen besser in der WHERE-Klausel an. Es gibt aber Ausnahmen zu dieser Regel.

Die oben gezeigte Syntax { OJ ... LEFT OUTER JOIN ...} ist nur aus Gründen der Kompatibilität mit ODBC vorhanden. Die geschweiften Klammern in der Syntax sollten literal notiert werden, sind also keine Metasyntax, wie sie andernorts in Syntaxbeschreibungen verwendet wird.

  • Für einen Tabellenverweis kann mit tbl_name AS alias_name oder tbl_name alias_name ein Alias erstellt werden:

    SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      WHERE t1.name = t2.name;
    
    SELECT t1.name, t2.salary FROM employee t1, info t2
      WHERE t1.name = t2.name;
    
  • Die Bedingungsanweisung ON ist ein beliebiger Bedingungsausdruck der Form, die in einer WHERE-Klausel verwendet werden kann.

  • Ist für die rechte Tabelle im ON- oder USING-Teil eines LEFT JOIN kein passender Datensatz vorhanden, dann wird für die rechte Tabelle ein Datensatz verwendet, bei dem alle Spalten auf NULL gesetzt sind. Sie können diesen Umstand nutzen, um Datensätze in einer Tabelle zu finden, die kein Gegenstück in einer anderen Tabelle aufweisen:

    SELECT table1.* FROM table1
      LEFT JOIN table2 ON table1.id=table2.id
      WHERE table2.id IS NULL;
    

    Dieses Beispiel findet alle Datensätze in table1 mit einem id-Wert, der nicht in table2 vorhanden ist (d. h. alle Datensätze in table1 ohne entsprechenden Datensatz in table2). Dies setzt voraus, dass table2.id als NOT NULL deklariert wurde. Siehe auch Abschnitt 7.2.9, „Optimierung von LEFT JOIN und RIGHT JOIN.

  • Die USING(column_list)-Klausel benennt eine Liste mit Spalten, die in beiden Tabellen vorhanden sein müssen. Wenn die Tabellen a und b jeweils die Spalten c1, c2 und c3 enthalten, dann vergleicht der folgende Join die entsprechenden Spalten der beiden Tabellen:

    a LEFT JOIN b USING (c1,c2,c3)
    
  • Der NATURAL [LEFT] JOIN beider Tabellen wird als semantisch äquivalent zu einem INNER JOIN oder einem LEFT JOIN mit einer USING-Klausel definiert, die alle Spalten aufführt, die in beiden Tabellen vorhanden sind.

  • INNER JOIN und , (Komma) sind semantisch gleichwertig, wenn keine Join-Bedingung vorhanden ist: Beide erzeugen ein kartesisches Produkt zwischen den angegebenen Tabellen (d. h., jeder Datensatz in der ersten Tabelle wird mit jedem Datensatz in der zweiten Tabelle verknüpft).

  • RIGHT JOIN funktioniert analog zu LEFT JOIN. Um den Code datenbankübergreifend portierbar zu halten, wird empfohlen, LEFT JOIN anstelle von RIGHT JOIN zu verwenden.

  • STRAIGHT_JOIN ist bis auf die Tatsache, dass die linke Tabelle immer vor der rechten gelesen wird, identisch mit JOIN. Dies kann für die (wenigen) Fälle genutzt werden, in denen der Join-Optimierer die Tabellen in der falschen Reihenfolge anordnet.

Sie können Hinweise dazu angeben, welchen Index MySQL beim Abrufen von Informationen aus einer Tabelle verwenden soll. Durch Angabe von USE INDEX (key_list) können Sie MySQL anweisen, nur einen der möglichen Indizes zum Ermitteln von Datensätzen in der Tabelle zu verwenden. Mit der alternativen Syntax IGNORE INDEX (key_list) können Sie MySQL anweisen, einen bestimmten Index nicht zu verwenden. Solche Hinweise sind nützlich, wenn EXPLAIN zeigt, dass MySQL aus einer Liste möglicher Indizes den falschen verwendet.

Sie können auch FORCE INDEX verwenden. Diese Option agiert wie USE INDEX (key_list), es wird aber zusätzlich vorausgesetzt, dass ein Tabellenscan sehr kostspielig ist. Anders gesagt: Ein Tabellenscan wird nur verwendet, wenn die Datensätze in der Tabelle nicht unter der Verwendung eines der gegebenen Indizes gefunden werden können.

USE INDEX, IGNORE INDEX und FORCE INDEX wirken sich erst darauf aus, welche Indizes verwendet werden, wenn MySQL entschieden hat, wie Datensätze in der Tabelle ermittelt werden und wie der Join durchgeführt wird. Sie haben keine Auswirkungen darauf, ob ein Index benutzt wird, wenn eine ORDER BY- oder GROUP BY-Klausel aufgelöst wird.

USE KEY, IGNORE KEY und FORCE KEY sind Synonyme von USE INDEX, IGNORE INDEX und FORCE INDEX.

Hier einige Beispiele für Joins:

SELECT * FROM table1,table2 WHERE table1.id=table2.id;

SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;

SELECT * FROM table1 LEFT JOIN table2 USING (id);

SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
  LEFT JOIN table3 ON table2.id=table3.id;

SELECT * FROM table1 USE INDEX (key1,key2)
  WHERE key1=1 AND key2=2 AND key3=3;

SELECT * FROM table1 IGNORE INDEX (key3)
  WHERE key1=1 AND key2=2 AND key3=3;

Hinweis: Natürliche Joins und Joins mit USING (einschließlich Varianten mit äußeren Joins) werden entsprechend Standard SQL:2003 verarbeitet. Diese Änderungen erhöhen die Kompatibilität von MySQL mit dem SQL-Standard. Allerdings kann es bei manchen Joins zu unterschiedlichen Ausgabespalten kommen. Ferner müssen einige Abfragen, die in älteren Versionen (vor 5.0.12) zu funktionieren schienen, neu geschrieben werden, um dem Standard zu entsprechen. Die folgende Liste enthält weitere Angaben zu verschiedenen Auswirkungen der aktuellen Join-Verarbeitung im Vergleich zur Verarbeitung in älteren Versionen. Der Begriff „älter“ bezeichnet hier Versionen vor MySQL 5.0.12.

  • Die Spalten eines NATURAL- oder USING-Joins können sich von denen älterer Versionen unterscheiden. Insbesondere erscheinen keine redundanten Ausgabespalten mehr, und die Reihenfolge der Spalten für die Erweiterung SELECT * kann anders aussehen.

    Beachten Sie die folgenden Anweisungen:

    CREATE TABLE t1 (i INT, j INT);
    CREATE TABLE t2 (k INT, j INT);
    INSERT INTO t1 VALUES(1,1);
    INSERT INTO t2 VALUES(1,1);
    SELECT * FROM t1 NATURAL JOIN t2;
    SELECT * FROM t1 JOIN t2 USING (j);
    

    In den älteren Versionen erzeugten sie folgende Ausgabe:

    +------+------+------+------+
    | i    | j    | k    | j    |
    +------+------+------+------+
    |    1 |    1 |    1 |    1 |
    +------+------+------+------+
    +------+------+------+------+
    | i    | j    | k    | j    |
    +------+------+------+------+
    |    1 |    1 |    1 |    1 |
    +------+------+------+------+
    

    In der ersten SELECT-Anweisung erscheint Spalte i in beiden Tabellen und wird insofern eine Join-Spalte, d. h., sie sollte laut SQL-Standard nur einmal (und nicht zweimal) in der Ausgabe erscheinen. Ähnlich ist die Spalte j in der zweiten SELECT-Anweisung in der USING-Klausel aufgeführt und sollte ebenfalls nur einmal (und nicht zweimal) in der Ausgabe auftauchen. In beiden Fällen wird die redundante Spalte nicht beseitigt. Auch ist die Reihenfolge der Spalten nicht korrekt im Sinne des SQL-Standards.

    Heute erzeugen die Anweisungen folgende Ausgabe:

    +------+------+------+
    | j    | i    | k    |
    +------+------+------+
    |    1 |    1 |    1 |
    +------+------+------+
    +------+------+------+
    | j    | i    | k    |
    +------+------+------+
    |    1 |    1 |    1 |
    +------+------+------+
    

    Die redundante Spalte ist beseitigt. Auch die Spaltenreihenfolge ist nun korrekt im Sinne des SQL-Standards:

    • Zuerst werden die Spalten, die in beiden Tabellen vorhanden sind, in der Reihenfolge aufgeführt, in der sie in der ersten Tabelle erscheinen.

    • Als Zweites erscheinen Spalten, die nur in der ersten Tabelle vorhanden sind, und zwar in der Reihenfolge, in der sie in der Tabelle erscheinen.

    • Als Drittes erscheinen Spalten, die nur in der zweiten Tabelle vorhanden sind, und zwar in der Reihenfolge, in der sie in der Tabelle erscheinen.

  • Die Auswertung eines natürlichen Vielfach-Joins unterscheidet sich auf eine Weise, die ein Neuformulieren von Abfragen erforderlich machen kann. Angenommen, Sie haben drei Tabellen t1(a,b), t2(c,b) und t3(a,c), die jeweils einen Datensatz aufweisen: t1(1,2), t2(10,2) und t3(7,10). Nehmen wir ferner an, dass Sie folgenden NATURAL JOIN auf die drei Tabellen haben:

    SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
    

    In älteren Versionen wurde der linke Operand des zweiten Joins als t2 betrachtet, wohingegen er eigentlich der verschachtelte Join (t1 NATURAL JOIN t2) sein sollte. Infolgedessen werden die Spalten von t3 nur auf gemeinsame Spalten in t2 geprüft; hat t3 gemeinsame Spalten mit t1, dann werden diese nicht als Equi-Join-Spalten betrachtet. Insofern wurde obige Abfrage bei älteren Versionen in den folgenden Equi-Join transformiert:

    SELECT ... FROM t1, t2, t3
      WHERE t1.b = t2.b AND t2.c = t3.c;
    

    Diesem Join fehlt aber ein weiteres Equi-Join-Prädikat (t1.a = t3.a). Aufgrund dessen wird als Ergebnis ein Datensatz ausgegeben – und nicht das korrekte leere Ergebnis. Die korrekte äquivalente Abfrage sieht wie folgt aus:

    SELECT ... FROM t1, t2, t3
      WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
    

    Wenn Sie in aktuellen MySQL-Versionen dasselbe Abfrageergebnis wie bei den älteren Versionen erhalten, dann formulieren Sie den natürlichen Join als Equi-Join um.

  • Früher hatten der Kommaoperator (,) und JOIN dieselbe Rangstufe, d. h., der Join-Ausdruck t1, t2 JOIN t3 wurde als ((t1, t2) JOIN t3) interpretiert. Jetzt hat JOIN Vorrang vor dem Komma, d. h., der Ausdruck wird als (t1, (t2 JOIN t3)) ausgewertet. Diese Änderung betrifft Anweisungen, die eine ON-Klausel verwenden, denn diese Klausel kann nur Spalten in den Operanden des Joins referenzieren, und die Änderung in der Rangstufe wirkt sich darauf aus, wie interpretiert wird, was diese Operanden sind.

    Beispiel:

    CREATE TABLE t1 (i1 INT, j1 INT);
    CREATE TABLE t2 (i2 INT, j2 INT);
    CREATE TABLE t3 (i3 INT, j3 INT);
    INSERT INTO t1 VALUES(1,1);
    INSERT INTO t2 VALUES(1,1);
    INSERT INTO t3 VALUES(1,1);
    SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
    

    In älteren Versionen war die SELECT-Anweisung aufgrund der impliziten Gruppierung von t1,t2 als (t1,t2) zulässig. Jetzt hat JOIN Vorrang, d. h., die Operanden für die ON-Klausel sind t2 und t3. Da t1.i1 keine Spalte in einem der Operanden ist, ist das Ergebnis der Fehler Unknown column 't1.i1' in 'on clause'. Um die Verarbeitung des Joins zuzulassen, gruppieren Sie die ersten beiden Tabellen explizit mithilfe von Klammern, sodass die Operanden für die ON-Klausel (t1,t2) und t3 sind:

    SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
    

    Alternativ umgehen Sie die Verwendung des Kommaoperators und verwenden stattdessen JOIN:

    SELECT * FROM t1 JOIN t2 JOIN t3 ON (t1.i1 = t3.i3);
    

    Diese Änderung gilt auch für INNER JOIN, CROSS JOIN, LEFT JOIN und RIGHT JOIN: Sie alle haben nun Vorrang vor dem Kommaoperator.

  • Früher konnte die ON-Klausel Spalten in Tabellen referenzieren, die auf ihrer rechten Seite aufgeführt wurden. Jetzt kann eine ON-Klausel nur ihre Operanden referenzieren.

    Beispiel:

    CREATE TABLE t1 (i1 INT);
    CREATE TABLE t2 (i2 INT);
    CREATE TABLE t3 (i3 INT);
    SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;
    

    Früher war diese SELECT-Anweisung zulässig. Nun schlägt die Anweisung mit dem Fehler Unknown column 'i3' in 'on clause' fehl, weil i3 eine Spalte in t3 ist, die kein Operand der ON-Klausel ist. Die Anweisung sollte wie folgt umgeschrieben werden:

    SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);
    
  • Früher konnte eine USING-Klausel als ON-Klausel neugeschrieben werden, die die entsprechenden Spalten vergleichen konnte. Die beiden folgenden Klauseln etwa sind semantisch identisch:

    a LEFT JOIN b USING (c1,c2,c3)
    a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
    

    Heute haben diese beiden Klauseln nicht mehr dieselbe Bedeutung:

    • Bezüglich der Ermittlung, welche Datensätze die Join-Bedingung erfüllen, bleiben beide Joins semantisch identisch.

    • Allerdings ist diese semantische Identität nicht mehr in Bezug auf die Frage vorhanden, wie die für die SELECT *-Erweiterung anzuzeigenden Spalten bestimmt werden. Der USING-Join wählt den zusammengefassten Wert der entsprechenden Spalten, während der ON-Join alle Spalten aus allen Tabellen auswählt. Bei obigem USING-Join wählt SELECT * die folgenden Werte aus:

      COALESCE(a.c1,b.c1), COALESCE(a.c2,b.c2), COALESCE(a.c3,b.c3)
      

      Beim ON-Join wählt SELECT * die folgenden Werte aus:

      a.c1, a.c2, a.c3, b.c1, b.c2, b.c3
      

      Bei einem inneren Join ist COALESCE(a.c1,b.c1) das Gleiche wie a.c1 oder b.c1, weil beide Spalten denselben Wert haben. Bei einem äußeren Join (wie LEFT JOIN) darf eine der beiden Spalten NULL sein. Diese Spalte wird im Ergebnis weggelassen.

13.2.7.2. UNION

SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]

UNION wird verwendet, um das Ergebnis einer Anzahl von SELECT-Anweisungen zu einer Ergebnismenge zusammenzufassen.

Ausgewählte Spalten, die an den entsprechenden Positionen jeder SELECT-Anweisung aufgelistet sind, sollten vom selben Typ sein. (So sollte etwa die erste von der ersten Anweisung ausgewählte Spalte denselben Typ haben wie die erste von den anderen Anweisungen gewählte Spalte.) Die in der ersten SELECT-Anweisung verwendeten Spaltennamen werden als Spaltennamen für die zurückgegebenen Ergebnisse benutzt.

Die SELECT-Anweisungen sind normale Auswahlanweisungen, es gelten jedoch die folgenden Einschränkungen:

  • Nur die letzte SELECT-Anweisung kann INTO OUTFILE verwenden.

  • HIGH_PRIORITY kann nicht bei SELECT-Anweisungen verwendet werden, die Teil einer Union sind. Wenn Sie es für die erste SELECT-Anweisung angeben, hat dies keine Auswirkungen. Bei einer Angabe für eine nachfolgende SELECT-Anweisung tritt ein Syntaxfehler auf.

Geben Sie das Schlüsselwort ALL an, dann enthält das Ergebnis alle passenden Datensätze aus allen SELECT-Anweisungen. Wenn Sie DISTINCT angeben, werden doppelte Datensätze aus dem Ergebnis entfernt. Wird kein Schlüsselwort benutzt, dann entspricht das Standardverhalten dem von DISTINCT (Entfernung doppelter Datensätze).

Das Schlüsselwort DISTINCT ist optional ohne Wirkung, ist aber in der Syntax zulässig, da der SQL-Standard dies vorschreibt. (In MySQL stellt DISTINCT das Standardverhalten einer Union dar.)

Sie können UNION ALL und UNION DISTINCT in derselben Abfrage gemeinsam verwenden. Derart gemischte UNION-Typen werden dahingehend verarbeitet, dass eine DISTINCT-Union Vorrang vor einer ALL-Union zu ihrer Linken hat. Eine DISTINCT-Union kann explizit mit UNION DISTINCT oder implizit durch Verwendung von UNION ohne nachfolgende Schlüsselwörter DISTINCT oder ALL erzeugt werden.

Wenn Sie eine ORDER BY- oder LIMIT-Klausel zur Sortierung bzw. Beschränkung des gesamten Ergebnisses der Union benutzen wollen, setzen Sie die einzelnen SELECT-Anweisungen in Klammern und platzieren Sie die ORDER BY- oder LIMIT-Klausel an dem Ende. Das folgende Beispiel verwendet beide Klauseln:

(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

Diese Art von ORDER BY kann keine Spaltenreferenzierungen verwenden, die einen Tabellennamen enthalten (d. h. Namen im Format tbl_name.col_name). Geben Sie stattdessen einen Spaltenalias in der ersten SELECT-Anweisung an und referenzieren Sie diesen Alias in der ORDER BY-Klausel. Alternativ können Sie die Spalten auch in der ORDER BY-Klausel unter Angabe ihrer Spaltenposition referenzieren. (Ein Alias ist allerdings vorzuziehen, weil das Angeben von Spaltenpositionen veraltet ist.)

Ferner muss, wenn einer zu sortierenden Spalte ein Alias zugewiesen wird, die ORDER BY-Klausel den Alias und nicht den Spaltennamen referenzieren. Die erste der folgenden Anweisungen funktioniert – im Gegensatz zur zweiten, die mit dem Fehler Unknown column 'a' in 'order clause' fehlschlägt:

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;

Um ORDER BY oder LIMIT auf eine einzelne SELECT-Anweisung anzuwenden, setzen Sie die Klausel mit in die Klammern, die die SELECT-Anweisung umschließen:

(SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

Das Einfügen von ORDER BY bei einzelnen SELECT-Anweisungen in Klammern hat nur in Kombination mit LIMIT Auswirkungen. Andernfalls wird ORDER BY wegoptimiert.

Typen und Längen der Spalten in der Ergebnismenge einer Union berücksichtigen Werte, die von allen SELECT-Anweisungen abgerufen wurden. Betrachten Sie etwa einmal Folgendes:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| bbbbbbbbbb    |
+---------------+

In einigen früheren Versionen von MySQL würde der zweite Datensatz auf eine Länge von 1 gekürzt.

13.2.8. Syntax von Unterabfragen

Eine Unterabfrage ist eine SELECT-Anweisung innerhalb einer anderen Anweisung.

Seit MySQL 4.1 werden alle Unterabfrageformen und -operationen, die der SQL-Standard vorsieht, ebenso unterstützt wie einige weitere Funktionen, die MySQL-spezifisch sind.

Hier ein Beispiel für eine Unterabfrage:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

In diesem Beispiel ist SELECT * FROM t1 ... die äußere Abfrage (oder äußere Anweisung), und (SELECT column1 FROM t2) ist die Unterabfrage. Man sagt, die Unterabfrage ist in der äußeren Abfrage verschachtelt, und tatsächlich ist es möglich, Unterabfragen bis zu einer beträchtlichen Tiefe zu verschachteln. Eine Unterabfrage muss immer in Klammern stehen.

Unterabfragen haben die folgenden Vorteile:

  • Sie gestatten Abfragen, die strukturiert sind. Auf diese Weise ist es möglich, jeden Teil einer Anweisung zu isolieren.

  • Sie bieten alternative Wege zur Durchführung von Operationen, die andernfalls komplexe Joins und Unions erfordern würden.

  • Sie sind – zumindest nach Meinung vieler – lesbar. Die Unterabfragen waren die eigentliche Innovation, aufgrund derer man auf die Idee kam, SQL seinerzeit als „strukturierte Abfragesprache“ zu bezeichnen.

Hier eine Beispielanweisung, die die wichtigsten Aspekte der Unterabfragensyntax zeigt, wie sie im SQL-Standard spezifiziert ist und von MySQL unterstützt wird:

DELETE FROM t1
WHERE s11 > ANY
(SELECT COUNT(*) /* no hint */ FROM t2
WHERE NOT EXISTS
(SELECT * FROM t3
WHERE ROW(5*t2.s1,77)=
(SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
(SELECT * FROM t5) AS t5)));

Eine Unterabfrage kann einen Skalar (einen einzelnen Wert), einen einzelnen Datensatz, eine einzelne Spalte oder eine Tabelle (d. h. eine oder mehrere Spalten von einem oder mehreren Datensätzen) zurückgeben. Man bezeichnet diese als Skalar-, Spalten-, Datensatz- und Tabellenunterabfragen. Unterabfragen, die einen bestimmten Ergebnistyp zurückgeben, können häufig nur in bestimmten Kontexten verwendet werden, die in den folgenden Abschnitten beschrieben werden.

Es gibt ein paar wenige Einschränkungen bezüglich des Typs der Anweisungen, in denen Unterabfragen verwendet werden können. Eine Unterabfrage kann die gleichen Schlüsselwörter oder Klauseln enthalten wie eine gewöhnliche SELECT-Anweisung: DISTINCT, GROUP BY, ORDER BY, LIMIT, Joins, Indexhinweise, UNION-Konstrukte, Kommentare, Funktionen usw.

Eine Einschränkung besteht darin, dass die äußere Anweisung einer Unterabfrage einen der folgenden Typen aufweisen muss: SELECT, INSERT, UPDATE, DELETE, SET oder DO. Eine weitere Einschränkung ist die Tatsache, dass Sie eine Tabelle derzeit nicht ändern und gleichzeitig in einer Unterabfrage eine Auswahl aus dieser Tabelle treffen können. Dies gilt für Anweisungen wie DELETE, INSERT, REPLACE, UPDATE und (da Unterabfragen in der SET-Klausel verwendet werden können) LOAD DATA INFILE. Eine umfassendere Beschreibung der Einschränkungen bei Unterabfragen finden Sie in Abschnitt I.3, „Beschränkungen von Unterabfragen“.

13.2.8.1. Die Unterabfrage als skalarer Operand

In ihrer einfachsten Form ist eine Unterabfrage eine Skalarunterabfrage, die einen Einzelwert zurückgibt. Eine Skalarunterabfrage ist ein einfacher Operand, und Sie können sie fast überall dort benutzen, wo ein einzelner Spaltenwert oder ein Literal zulässig ist. Sie können dabei voraussetzen, dass eine solche Unterabfrage die Eigenschaften aufweist, die alle Operanden haben: einen Datentyp, eine Länge, eine Angabe dazu, ob sie NULL sein darf oder nicht usw. Zum Beispiel:

CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
INSERT INTO t1 VALUES(100, 'abcde');
SELECT (SELECT s2 FROM t1);

Die Unterabfrage in dieser SELECT-Anweisung gibt einen einzelnen Wert ('abcde') zurück, der den Datentyp CHAR und die Länge 5 aufweist, Zeichensatz und Sortierfolge den mit CREATE TABLE konfigurierten Vorgaben entnimmt und die Information enthält, dass der Wert in der Spalte auch NULL sein kann. Tatsächlich können fast alle Unterabfragen NULL werden. Wäre die im Beispiel verwendete Tabelle leer, dann wäre der Wert der Unterabfrage NULL.

Es gibt nur ganz wenig Kontexte, in denen eine skalare Unterabfrage nicht verwendet werden kann. Wenn eine Anweisung nur einen literalen Wert zulässt, können Sie keine Unterabfrage einsetzen. So erfordert beispielsweise LIMIT literale Integer-Argumente, und LOAD DATA INFILE verlangt einen literalen String für den Dateinamen. Zur Übermittlung solcher Werte können Sie Unterabfragen nicht benutzen.

Wenn die Beispiele in den folgenden Abschnitten das recht spartanische Konstrukt (SELECT column1 FROM t1) enthalten, dann vergegenwärtigen Sie sich, dass Ihr eigener Code wesentlich komplexere und unterschiedlichere Konstruktionen enthalten kann (und wird).

Nehmen wir an, wir erstellen zwei Tabellen:

CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);

Nun führen Sie eine SELECT-Anweisung aus:

SELECT (SELECT s1 FROM t2) FROM t1;

Das Ergebnis ist 2, weil in Tabelle t2 eine Spalte s1 vorhanden ist, die den Wert 2 hat.

Eine skalare Unterabfrage kann Teil eines Ausdrucks sein. Denken Sie aber immer an die Klammern – auch dann, wenn die Unterabfrage ein Operand ist, der ein Argument für eine Funktion bereitstellt. Zum Beispiel:

SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

13.2.8.2. Vergleiche mit Unterabfragen

Die häufigste Form einer Unterabfrage hat das folgende Aussehen:

non_subquery_operand comparison_operator (subquery)

Hierbei ist comparison_operator einer der folgenden Operatoren:

=  >  <  >=  <=  <>

Zum Beispiel:

  ... 'a' = (SELECT column1 FROM t1)

Früher befand sich der einzige zulässige Ort für eine Unterabfrage auf der rechten Seite eines Vergleichs; einige wenige alte Datenbanksysteme halten nach wie vor an dieser Regel fest.

Hier ein Beispiel für einen Unterabfragenvergleich in der gängigen Form, den Sie mit einem Join nicht durchführen können. Hierbei werden alle Werte in Tabelle t1 gefunden, die einem Maximalwert in Tabelle t2 entsprechen:

SELECT column1 FROM t1
WHERE column1 = (SELECT MAX(column2) FROM t2);

Es folgt ein weiteres Beispiel, welches ebenfalls mit einem Join nicht zu realisieren ist, da für eine der Tabellen eine Zusammenfassung erfolgt. Gefunden werden hier alle Datensätze in der Tabelle t1, die einen Wert enthalten, der in einer gegebenen Spalte zweimal auftritt:

SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);

Bei einem Vergleich, der mit einem dieser Operatoren durchgeführt wird, muss die Unterabfrage einen Skalar zurückgeben. Eine Ausnahme besteht lediglich darin, dass = mit Datensatzunterabfragen verwendet werden kann. Siehe auch Abschnitt 13.2.8.5, „Zeilenunterabfragen“.

13.2.8.3. Unterabfragen mit ANY, IN und SOME

Syntax:

operand comparison_operator ANY (subquery)
operand IN (subquery)
operand comparison_operator SOME (subquery)

Das Schlüsselwort ANY, das einem Vergleichsoperator folgen muss, bedeutet „Gib TRUE zurück, wenn der Vergleich für jeden beliebigen Wert in der Spalte, die die Unterabfrage zurückgibt, wahr ist“. Zum Beispiel:

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

Nehmen wir an, dass die Tabelle t1 einen Datensatz mit dem Inhalt (10) umfasst. Der Ausdruck ist wahr, wenn Tabelle t2 (21,14,7) enthält, weil ein Wert 7 in t2 vorhanden ist, der kleiner als 10 ist. Der Ausdruck ist hingegen falsch, wenn Tabelle t2 (20,10) enthält oder leer ist. Der Ausdruck ist schließlich unbekannt (UNKNOWN), wenn Tabelle t2 (NULL,NULL,NULL) enthält.

Das Wort IN ist ein Alias für = ANY. Insofern sind die folgenden beiden Anweisungen gleichwertig:

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

Allerdings ist NOT IN kein Alias für <> ANY, wohl aber für <> ALL. Siehe auch Abschnitt 13.2.8.4, „Unterabfragen mit ALL.

Das Wort SOME ist ein Alias für ANY. Insofern sind die folgenden beiden Anweisungen gleichwertig:

SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

Das Wort SOME wird zwar nur selten verwendet, dieses Beispiel zeigt aber, wofür es nützlich sein kann. Die meisten Menschen fassen die Phrase „a ist nicht gleich irgendeinem b“ als „Es gibt kein b, welches gleich a ist“ auf, aber das ist bei der SQL-Syntax nicht gemeint. Hier bedeutet dies vielmehr „Es gibt (mindestens) ein b, dem a nicht gleich ist“. Indem Sie stattdessen <> SOME verwenden, gewährleisten Sie, dass jeder die tatsächliche Meinung der Abfrage versteht.

13.2.8.4. Unterabfragen mit ALL

Syntax:

operand comparison_operator ALL (subquery)

Das Wort ALL, das einem Vergleichsoperator folgen muss, bedeutet „Gib TRUE zurück, wenn der Vergleich für jeden beliebigen Wert in der Spalte, die die Unterabfrage zurückgibt, wahr ist“. Zum Beispiel:

SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

Nehmen wir an, dass die Tabelle t1 einen Datensatz mit dem Inhalt (10) umfasst. Der Ausdruck ist wahr, wenn Tabelle t2 (-5,0,+5) enthält, weil 10 größer als alle drei Werte in t2 ist. Der Ausdruck ist hingegen falsch, wenn Tabelle t2 (12,6,NULL,-100) enthält, weil es einen Wert (12) in Tabelle t2 gibt, der größer als 10 ist. Der Ausdruck ist unbekannt (d. h. NULL), wenn Tabelle t2 (0,NULL,1) enthält.

Schließlich ist, wenn Tabelle t2 leer ist, das Ergebnis wahr. Aufgrund dessen ist die folgende Anweisung wahr, wenn Tabelle t2 leer ist:

SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

Folgende Anweisung ist hingegen NULL, wenn Tabelle t2 leer ist:

SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

Ferner ist auch folgende Anweisung NULL, wenn Tabelle t2 leer ist:

SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

Generell sind Tabellen, die NULL-Werte enthalten, und leere Tabellen Grenzfälle. Wenn Sie Unterabfragencode formulieren, vergewissern Sie sich immer, dass Sie diese beiden Fälle berücksichtigt haben.

NOT IN ist ein Alias für <> ALL. Insofern sind die folgenden beiden Anweisungen gleichwertig:

SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);

13.2.8.5. Zeilenunterabfragen

Bis zu diesem Punkt haben wir ausschließlich Skalar- und Spaltenunterabfragen beschrieben, also Unterabfragen, die einen einzelnen Wert oder eine Wertespalte zurückgeben. Eine Datensatzunterabfrage ist eine Unterabfragenvariante, die einen einzelnen Datensatz zurückgibt – und insofern auch mehrere Spaltenwerte zurückgeben kann. Hier zwei Beispiele:

SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

Die gezeigten Abfragen sind beide wahr, wenn Tabelle t2 einen Datensatz enthält, bei dem column1 = 1 und column2 = 2 sind.

Die Ausdrücke (1,2) und ROW(1,2) heißen manchmal auch Datensatzkonstruktoren. Beide sind äquivalent. Sie sind zudem auch in anderen Kontexten zulässig. So sind etwa die beiden folgenden Anweisungen semantisch äquivalent (obwohl derzeit nur die zweite optimiert werden kann):

  SELECT * FROM t1 WHERE (column1,column2) = (1,1);
  SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

Der normale Anwendungsfall von Datensatzkonstruktoren sind Vergleiche mit Unterabfragen, die zwei oder mehr Spalten zurückgeben. So entspricht die folgende Abfrage der Aufforderung „Suche alle Datensätze in Tabelle t1, die auch in Tabelle t2 vorhanden sind“:

SELECT column1,column2,column3
FROM t1
WHERE (column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2);

13.2.8.6. EXISTS und NOT EXISTS

Wenn eine Unterabfrage irgendwelche Datensätze zurückgibt, ist EXISTS subquery wahr und NOT EXISTS subquery ist falsch. Zum Beispiel:

SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

Traditionell beginnt eine EXISTS-Unterabfrage mit SELECT *, sie könnte aber auch mit SELECT 5 oder SELECT column1 oder etwas ganz anderem anfangen: MySQL ignoriert die SELECT-Liste in einer solchen Unterabfrage, mithin macht es keinen Unterschied.

Bei obigem Beispiel ist die Bedingung wahr, wenn t2 überhaupt Datensätze enthält (und sogar dann, wenn es sich ausschließlich um NULL-Werte handelt). Dies ist aber ein recht abwegiges Beispiel, weil eine [NOT] EXISTS-Unterabfrage fast immer Korrelationen enthält. Hier einige pragmatischere Beispiele:

  • Welche Arten von Geschäften sind in einer oder mehreren Städten vorhanden?

    SELECT DISTINCT store_type FROM stores
      WHERE EXISTS (SELECT * FROM cities_stores
                    WHERE cities_stores.store_type = stores.store_type);
    
  • Welche Art von Geschäften ist in keiner Stadt vorhanden?

    SELECT DISTINCT store_type FROM stores
      WHERE NOT EXISTS (SELECT * FROM cities_stores
                        WHERE cities_stores.store_type = stores.store_type);
    
  • Welche Art von Geschäften ist in allen Städten vorhanden?

    SELECT DISTINCT store_type FROM stores s1
      WHERE NOT EXISTS (
        SELECT * FROM cities WHERE NOT EXISTS (
          SELECT * FROM cities_stores
           WHERE cities_stores.city = cities.city
           AND cities_stores.store_type = stores.store_type));
    

Das letzte Beispiel ist eine doppelt verschachtelte NOT EXISTS-Abfrage: Sie enthält eine NOT EXISTS-Klausel in einer NOT EXISTS-Klausel. Formell beantwortet sie die Frage „Gibt es eine Stadt mit einem Geschäft, das nicht in Stores vorhanden ist?“. Aber es ist einfacher zu sagen, dass eine verschachtelte NOT EXISTS-Klausel die Frage „Ist x für alle y wahr?“ beantwortet.

13.2.8.7. Korrelierte Unterabfragen

Eine korrelierte Unterabfrage ist eine Unterabfrage, die eine Tabelle referenziert, die auch in der äußeren Abfrage erscheint. Zum Beispiel:

SELECT * FROM t1 WHERE column1 = ANY
(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

Beachten Sie, dass die Unterabfrage eine Spalte von t1 referenziert, obwohl die FROM-Klausel der Unterabfrage keine Tabelle t1 erwählt. Also sucht MySQL außerhalb der Unterabfrage und findet t1 in der äußeren Abfrage.

Angenommen, Tabelle t1 enthielte einen Datensatz, bei dem column1 = 5 und column2 = 6 sind. Gleichzeitig enthält Tabelle t2 einen Datensatz, bei dem column1 = 5 und column2 = 7 sind. Der einfache Ausdruck ... WHERE column1 = ANY (SELECT column1 FROM t2) wäre wahr, aber in diesem Beispiel ist die WHERE-Klausel innerhalb der Unterabfrage falsch (weil nämlich (5,6) nicht gleich (5,7)); also ist auch die Unterabfrage als Ganzes falsch.

Bereichsregel: MySQL wertet von innen nach außen aus. Zum Beispiel:

SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));

In dieser Anweisung muss x.column2 eine Spalte in der Tabelle t2 sein, weil SELECT column1 FROM t2 AS x ... t2 umbenennt. Es ist keine Spalte in Tabelle t1, weil SELECT column1 FROM t1 ... eine äußere Abfrage ist, die weiter außen ist.

Bei Unterabfragen in HAVING- oder ORDER BY-Klauseln sucht MySQL auch nach Spaltennamen in der äußeren Auswahlliste.

In bestimmten Fällen wird eine korrelierte Unterabfrage optimiert. Zum Beispiel:

val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

Andernfalls sind sie ineffizient und zudem wahrscheinlich recht langsam. Das Umschreiben der Abfrage als Join kann die Leistung unter Umständen verbessern.

Korrelierte Unterabfragen können Ergebnisse von Zusammenfassungsfunktionen in der äußeren Abfrage nicht referenzieren.

13.2.8.8. Unterabfragen in der FROM-Klausel

Unterabfragen sind in der FROM-Klausel einer SELECT-Anweisung zulässig. Die eigentliche Syntax lautet:

SELECT ... FROM (subquery) [AS] name ...

Die [AS] name-Klausel ist obligatorisch, weil jede Tabelle in einer FROM-Klausel einen Namen haben muss. Alle Spalten, die in der subquery-Auswahlliste aufgeführt sind, benötigen eindeutige Namen. Sie finden diese Syntax an anderer Stelle in diesem Handbuch beschrieben. Dort wird der Begriff „abgeleitete Tabellen“ verwendet.

Zur Veranschaulichung nehmen wir an, dass Sie folgende Tabelle haben:

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

Eine Unterabfrage in der FROM-Klausel verwenden Sie bei der Beispieltabelle wie folgt:

INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;

Ergebnis: 2, '2', 4.0.

Es folgt ein weiteres Beispiel: Nehmen wir an, Sie wollen den Durchschnitt einer Anzahl von Summen für eine gruppierte Tabelle ermitteln. Folgendes funktioniert nicht:

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

Die nächste Abfrage dagegen übermittelt die gewünschte Information:

SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;

Beachten Sie, dass der Spaltenname, der in der Unterabfrage verwendet wird (sum_column1), in der äußeren Abfrage erkannt wird.

Unterabfragen in der FROM-Klausel können einen Skalar, eine Spalte, einen Datensatz oder eine Tabelle zurückgeben. Unterabfragen in der FROM-Klausel dürfen keine korrelierten Unterabfragen sein.

Unterabfragen in der FROM-Klausel werden auch für die EXPLAIN-Anweisung ausgeführt (d. h., es werden abgeleitete Temporärtabellen erstellt). Grund hierfür ist, dass Abfragen höherer Ebenen während der Optimierungsphase Informationen zu allen Tabellen benötigen.

13.2.8.9. Fehler bei Unterabfragen

Es gibt eine Reihe von Fehlern, die sich nur auf Unterabfragen beziehen. Sie werden in diesem Abschnitt beschrieben.

  • Falsche Anzahl von Spalten aus der Unterabfrage:

    ERROR 1241 (ER_OPERAND_COL)
    SQLSTATE = 21000
    Message = "Operand should contain 1 column(s)"
    

    Dieser Fehler tritt in Fällen wie dem folgenden auf:

    SELECT (SELECT column1, column2 FROM t2) FROM t1;
    

    Sie können eine Unterabfrage verwenden, die mehrere Spalten zurückgibt, sofern das Ziel ein Vergleich ist. Siehe auch Abschnitt 13.2.8.5, „Zeilenunterabfragen“. Allerdings muss die Unterabfrage in anderen Kontexten ein skalarer Operand sein.

  • Falsche Anzahl von Datensätzen aus der Unterabfrage:

    ERROR 1242 (ER_SUBSELECT_NO_1_ROW)
    SQLSTATE = 21000
    Message = "Subquery returns more than 1 row"
    

    Dieser Fehler tritt bei Anweisungen auf, bei denen die Unterabfrage mehr als einen Datensatz zurückgibt. Betrachten Sie einmal das folgende Beispiel:

    SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
    

    Wenn SELECT column1 FROM t2 nur einen Datensatz zurückgibt, funktioniert obige Abfrage. Gibt die Abfrage jedoch mehrere Datensätze zurück, dann tritt der Fehler 1242 auf. In diesem Fall sollten Sie die Abfrage wie folgt neu formulieren:

    SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);
    
  • Falsch verwendete Tabelle in der Unterabfrage:

    Error 1093 (ER_UPDATE_TABLE_USED)
    SQLSTATE = HY000
    Message = "You can't specify target table 'x'
    for update in FROM clause"
    

    Dieser Fehler tritt in Fällen wie dem folgenden auf:

    UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);
    

    Sie können eine Unterabfrage zur Zuweisung innerhalb einer UPDATE-Anweisung verwenden, da Unterabfragen in UPDATE- und DELETE-Anweisungen ebenso zulässig sind wie in SELECT-Anweisungen. Allerdings können Sie nicht dieselbe Tabelle (in diesem Fall Tabelle t1) sowohl in der FROM-Klausel der Unterabfrage als auch als Aktualisierungsziel angeben.

Bei transaktionssicheren Speicher-Engines schlägt bei einem Fehlschlag einer Unterabfrage die gesamte Anweisung fehl. Bei nichttransaktionssicheren Speicher-Engines bleiben Datenänderungen, die vor Auftreten des Fehlers durchgeführt wurden, erhalten.

13.2.8.10. Optimierung von Unterabfragen

Die Entwicklung erfolgt kontinuierlich, d. h., Optimierungstipps sind niemals auf Dauer gültig. Die folgende Liste zeigt einige interessante Tricks, mit denen Sie ein wenig herumprobieren können:

  • Verwendung von Klauseln in Unterabfragen, die die Anzahl oder Reihenfolge der Datensätze in der Unterabfrage betreffen. Zum Beispiel:

    SELECT * FROM t1 WHERE t1.column1 IN
    (SELECT column1 FROM t2 ORDER BY column1);
    SELECT * FROM t1 WHERE t1.column1 IN
    (SELECT DISTINCT column1 FROM t2);
    SELECT * FROM t1 WHERE EXISTS
    (SELECT * FROM t2 LIMIT 1);
    
  • Ersetzen Sie einen Join durch eine Unterabfrage. Probieren Sie z. B. Folgendes aus.

    SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
    SELECT column1 FROM t2);
    

    So hätte dies ursprünglich ausgesehen:

    SELECT DISTINCT t1.column1 FROM t1, t2
    WHERE t1.column1 = t2.column1;
    
  • Einige Unterabfragen können aus Gründen der Kompatibilität mit älteren MySQL-Versionen, die Unterabfragen nicht unterstützen, in Joins umgewandelt werden. Allerdings wird hierdurch in einigen Fällen die Leistungsfähigkeit beeinträchtigt. Siehe auch Abschnitt 13.2.8.11, „Umschreiben von Unterabfragen in Joins für frühere MySQL-Versionen“.

  • Verschieben Sie Klauseln von außen in die Unterabfrage. Verwenden Sie beispielsweise diese Abfrage …

    SELECT * FROM t1
    WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
    

    … statt dieser:

    SELECT * FROM t1
    WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
    

    Ein weiteres Beispiel: Verwenden Sie diese Abfrage …

    SELECT (SELECT column1 + 5 FROM t1) FROM t2;
    

    … statt dieser:

    SELECT (SELECT column1 FROM t1) + 5 FROM t2;
    
  • Verwenden Sie eine Datensatzunterabfrage statt einer korrelierten Unterabfrage. Verwenden Sie beispielsweise diese Abfrage …

    SELECT * FROM t1
    WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
    

    … statt dieser:

    SELECT * FROM t1
    WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
    AND t2.column2=t1.column2);
    
  • Verwenden Sie NOT (a = ANY (...)) statt a <> ALL (...).

  • Verwenden Sie x = ANY (table containing (1,2)) statt x=1 OR x=2.

  • Verwenden Sie = ANY statt EXISTS.

  • Bei unkorrelierten Unterabfragen, die immer genau einen Datensatz zurückgeben, ist IN immer langsamer als =. Verwenden Sie beispielsweise diese Abfrage …

    SELECT * FROM t1 WHERE t1.col_name
    = (SELECT a FROM t2 WHERE b = some_const);
    

    … statt dieser:

    SELECT * FROM t1 WHERE t1.col_name
    IN (SELECT a FROM t2 WHERE b = some_const);
    

Aufgrund dieser Tricks können Programme schneller, aber auch langsamer werden. Mithilfe von MySQL-Funktionen wie BENCHMARK() können Sie überprüfen, was in Ihrer speziellen Situation hilfreich sein kann. Siehe auch Abschnitt 12.10.3, „Informationsfunktionen“.

Die folgenden Optimierungen nimmt MySQL selbst vor:

  • MySQL führt nichtkorrelierte Unterabfragen nur einmal aus. Mit EXPLAIN können Sie sicherstellen, dass eine gegebene Unterabfrage wirklich nichtkorreliert ist.

  • MySQL schreibt IN-, ALL-, ANY- und SOME-Unterabfragen neu, um möglichst davon zu profitieren, dass die Auswahllistenspalten in der Unterabfrage indiziert sind.

  • MySQL ersetzt Unterabfragen der folgenden Form durch eine Indexsuchfunktion, die EXPLAIN als speziellen Join-Typ beschreibt (unique_subquery oder index_subquery):

    ... IN (SELECT indexed_column FROM single_table ...)
    
  • MySQL erweitert Ausdrücke der folgenden Form mit einem Ausdruck mit MIN() oder MAX(), sofern NULL-Werte oder Leermengen vorhanden sind:

    value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
    

    Betrachten Sie etwa folgende WHERE-Klausel:

    WHERE 5 > ALL (SELECT x FROM t)
    

    Diese könnte vom Optimierer wie folgt geändert werden:

    WHERE 5 > (SELECT MAX(x) FROM t)
    

Es gibt ein Kapitel „How MySQL Transforms Subqueries“ („Wie MySQL Unterabfragen transformiert“) im Handbuch „MySQL Internals“ (MySQL-Interna, derzeit nur auf Englisch verfügbar), welches Sie unter http://dev.mysql.com/doc/ erhalten.

13.2.8.11. Umschreiben von Unterabfragen in Joins für frühere MySQL-Versionen

Bei älteren MySQL-Versionen (vor Version 4.1) wurden nur verschachtelte Abfragen der Formen INSERT ... SELECT ... und REPLACE ... SELECT ... unterstützt. Zwar trifft dies bei MySQL 5.1 nicht mehr zu, aber nach wie vor werden gelegentlich andere Möglichkeiten eingesetzt, um auf Mitgliedschaft in einer Wertemenge zu prüfen. Außerdem ist es unter bestimmten Umständen nicht nur möglich, eine Abfrage ohne Unterabfrage zu schreiben, sondern es kann auch effizienter sein, einige der folgenden Methoden zu verwenden, statt Unterabfragen einzusetzen. Eine dieser Methode ist das Konstrukt IN():

Betrachten Sie etwa folgende Abfrage:

SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

Sie kann wie folgt umgeschrieben werden:

SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;

Ein anderes Beispiel sind folgende Abfragen:

SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

Auch sie lassen sich mithilfe von IN() umschreiben:

SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
WHERE table2.id IS NULL;

Ein LEFT [OUTER] JOIN kann schneller sein als die äquivalente Unterabfrage, weil der Server unter Umständen in der Lage ist, ihn besser zu optimieren – eine Tatsache, die nicht nur für den MySQL Server gilt. Vor SQL-92 waren äußere Joins nicht vorhanden, d. h., Unterabfragen stellten für bestimmte Aufgaben die einzige Lösung dar. Heute bieten MySQL Server und viele andere moderne Datenbanksysteme eine Vielzahl von Typen für äußere Joins.

MySQL Server unterstützt DELETE-Anweisungen über mehrere Tabellen, die zur effizienten gleichzeitigen Löschung von Datensätzen basierend auf Daten in einer Tabelle (oder sogar mehreren Tabellen) benutzt werden. Auch UPDATE-Anweisungen über mehrere Tabellen werden unterstützt.

13.2.9. TRUNCATE

TRUNCATE [TABLE] tbl_name

TRUNCATE TABLE leert eine Tabelle vollständig. Logisch gesehen ist dies äquivalent zu einer DELETE-Anweisung, die alle Datensätze löscht, aber es gibt unter bestimmten Umständen praktische Unterschiede.

Bei InnoDB-Tabellen wird TRUNCATE TABLE auf DELETE umgesetzt, sofern keine Fremdschlüssel-Constraints vorhanden sind, die die Tabelle referenzieren; andernfalls wird das schnelle Leeren (durch Löschen und Neuerstellen der Tabelle) verwendet. Der AUTO_INCREMENT-Zähler wird von TRUNCATE TABLE unabhängig vom Vorhandensein eines Fremdschlüssel-Constraints zurückgesetzt.

Bei anderen Speicher-Engines unterscheidet sich TRUNCATE TABLE in MySQL 5.1 wie folgt von DELETE:

  • Leerungsoperationen löschen die Tabelle und erstellen sie dann neu, was wesentlich schneller ist als das aufeinander folgende Löschen aller Datensätze.

  • Leerungsoperationen sind nicht transaktionssicher: Wenn Sie eine solche Operation während einer aktiven Transaktion oder einer aktiven Tabellensperrung durchführen wollen, tritt ein Fehler auf.

  • Die Anzahl gelöschter Datensätze wird nicht zurückgegeben.

  • Solange die Tabellenformatdatei tbl_name.frm gültig ist, lässt sich die Tabelle mit TRUNCATE TABLE auch dann als leere Tabelle neu erstellen, wenn die Daten- oder Indexdateien beschädigt wurden.

  • Der Tabellen-Handler speichert den zuletzt verwendeten AUTO_INCREMENT-Wert nicht, sondern fängt mit der Zählung von vorne an. Dies gilt auch für MyISAM- und InnoDB-Tabellen, die Sequenzwerte normalerweise nicht erneut verwenden.

  • Bei der Verwendung mit partitionierten Tabellen behält TRUNCATE TABLE die Partitionierung bei, d. h., Daten- und Indexdateien werden gelöscht und neu erstellt, während die Partitionsdefinitionsdatei (.par) hiervon unberührt bleibt.

TRUNCATE TABLE ist eine Oracle SQL-Erweiterung, die in MySQL übernommen wurde.

13.2.10. UPDATE

Syntax für eine Tabelle:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

Syntax für mehrere Tabellen:

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_condition]

Bei der Ein-Tabellen-Syntax aktualisiert die UPDATE-Anweisung Spalten in vorhandenen Datensätzen in tbl_name mit neuen Werten. Die SET-Klausel gibt an, welche Spalten geändert werden und welche Werte diese erhalten sollen. Sofern angegeben, bestimmt die WHERE-Klausel die Bedingungen dafür, welche Datensätze geändert werden. Ohne WHERE-Klausel werden alle Datensätze aktualisiert. Wenn die ORDER BY-Klausel vorhanden ist, werden die Datensätze in der angegebenen Reihenfolge aktualisiert. Die LIMIT-Klausel kann die Anzahl der zu aktualisierenden Datensätze beschränken.

Bei der Mehrtabellensyntax aktualisiert UPDATE in jeder Tabelle table_references die Datensätze, die die Bedingungen erfüllen. In diesem Fall können ORDER BY und LIMIT nicht verwendet werden.

where_condition ist ein Ausdruck, der für jeden zu aktualisierenden Datensatz wahr ist. Er wird wie in Abschnitt 13.2.7, „SELECT, beschrieben angegeben.

Die UPDATE-Anweisung unterstützt die folgenden Modifizierer:

  • Wenn Sie das Schlüsselwort LOW_PRIORITY angeben, wird die Ausführung von UPDATE verzögert, bis kein Client mehr aus der Tabelle liest.

  • Wenn Sie das Schlüsselwort IGNORE verwenden, bricht die UPDATE-Anweisung auch dann nicht ab, wenn während der Aktualisierung Fehler auftreten. Datensätze, bei denen Konflikte aufgrund von Schlüsseldubletten auftreten, werden nicht geändert. Datensätze, bei denen Spalten auf Werte gesetzt werden würden, die Datenkonvertierungsfehler zur Folge hätten, werden stattdessen auf den nächstgelegenen gültigen Wert gesetzt.

Wenn Sie in einem Ausdruck auf eine Spalte in der Tabelle tbl_name zugreifen, verwendet UPDATE den aktuellen Wert der Spalte. So erhöht die folgende Anweisung beispielsweise den aktuellen Wert in der Spalte age um 1:

UPDATE persondata SET age=age+1;

UPDATE-Zuordnungen werden von links nach rechts ausgewertet. Die folgende Anweisung etwa verdoppelt die Spalte age und erhöht sie dann um 1:

UPDATE persondata SET age=age*2, age=age+1;

Wenn Sie eine Spalte auf den Wert aktualisieren, den sie ohnehin gerade hat, dann bemerkt MySQL dies und führt keine Aktualisierung durch.

Wenn Sie eine als NOT NULL deklarierte Spalte aktualisieren, indem Sie sie auf NULL setzen, wird die Spalte stattdessen auf den für den jeweiligen Datentyp vorgesehenen Standardwert gesetzt und der Warnungszähler erhöht. Der Vorgabewert ist 0 bei numerischen Typen, der Leer-String ('') bei String-Typen und der „Nullwert“ für Datums- und Uhrzeittypen.

UPDATE gibt die Anzahl der tatsächlich geänderten Datensätze zurück. Die C-API-Funktion mysql_info() hingegen gibt die Anzahl der Datensätze, die gefunden und aktualisiert wurden, sowie die Anzahl der Warnungen zurück, die während der UPDATE-Operation aufgetreten sind.

Sie können LIMIT row_count verwenden, um den Geltungsbereich von UPDATE einzuschränken. Eine LIMIT-Klausel ist eine Beschränkung für Datensätze. Die Anweisung endet, sobald eine Anzahl von row_count Datensätzen gefunden wurde, die der WHERE-Klausel entsprechen – unabhängig davon, ob sie dann auch geändert wurden oder nicht.

Wenn eine UPDATE-Anweisung eine ORDER BY-Klausel enthält, werden die Datensätze in der in der Klausel angegebenen Reihenfolge aktualisiert.

Sie können auch UPDATE-Operationen durchführen, die sich auf mehrere Tabellen beziehen. Allerdings können Sie ORDER BY oder LIMIT nicht in einer UPDATE-Anweisung für mehrere Tabellen verwenden. Die Klausel table_references listet die Tabellen auf, die im Join berücksichtigt werden. Die Syntax ist in Abschnitt 13.2.7.1, „JOIN, beschrieben. Hier ein Beispiel:

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

Das obige Beispiel zeigt einen inneren Join, der den Kommaoperator verwendet. UPDATE-Anweisungen für mehrere Tabellen können jedoch einen beliebigen Join-Typ verwenden, der für SELECT-Anweisungen zulässig ist, also etwa LEFT JOIN.

Sie benötigen die Berechtigung UPDATE nur für diejenigen in einer UPDATE-Anweisung für mehrere Tabellen referenzierten Spalten, die tatsächlich geändert werden. Die Berechtigung SELECT hingegen benötigen Sie für alle Spalten, die gelesen, aber nicht modifiziert werden.

Wenn Sie eine UPDATE-Anweisung für mehrere Tabellen verwenden, die auch InnoDB-Tabellen einbezieht, für die Fremdschlüssel-Constraints vorhanden sind, dann verarbeitet der MySQL-Optimierer die Tabellen unter Umständen in einer Reihenfolge, die sich von der ihrer Parent/Child-Beziehung unterscheidet. In diesem Fall schlägt die Anweisung fehl, und es wird ein Rollback durchgeführt. Stattdessen sollten Sie die Änderung dann in nur einer Tabelle durchführen und sich auf die ON UPDATE-Funktionalität verlassen, die InnoDB bietet, um andere Tabellen entsprechend zu ändern. Siehe auch Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.

Zurzeit können Sie in einer Unterabfrage keine Aktualisierungsoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.

13.3. Grundlegende Befehle des MySQL-Dienstprogramms für Benutzer

13.3.1. DESCRIBE (Informationen über Spalten abrufen)

{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBE vermittelt Informationen zu Spalten in einer Tabelle. Es handelt sich um ein Synonym für SHOW COLUMNS FROM. Diese Anweisungen erlauben auch die Anzeige von Informationen zu Views. (Siehe auch Abschnitt 13.5.4.3, „SHOW COLUMNS.)

col_name kann ein Spaltenname oder aber ein String sein, der die SQL-Jokerzeichen ‘%’ und ‘_’ enthält, um eine Ausgabe nur zu Spalten zu erhalten, die dem String entsprechen. Sie müssen den String nicht in Anführungszeichen setzen, sofern er nicht Leerzeichen oder andere Sonderzeichen enthält.

mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

Field gibt den Spaltennamen an.

Das Feld Null zeigt an, ob NULL-Werte in der Spalte gespeichert werden können.

Das Feld Key gibt an, ob die Spalte indiziert ist. Mit PRI wird angegeben, dass die Spalte Teil des Primärschlüssels der Tabelle ist, mit UNI hingegen, dass sie Teil eines eindeutigen Indexes ist. Der Wert MUL schließlich signalisiert, dass mehrere Instanzen eines gegebenen Werts innerhalb der Spalte zulässig sind.

Ein möglicher Grund für die Anzeige von MUL in einem eindeutigen Index besteht darin, dass mehrere Spalten einen zusammengesetzten eindeutigen Index bilden. Dann ist die Kombination der Spalten eindeutig, während die einzelnen Spalten durchaus mehrere Instanzen eines gegebenen Werts enthalten können. Beachten Sie, dass in einem zusammengesetzten Index nur die links stehende Spalte einen Eintrag im Feld Key hat.

Das Feld Default gibt den Standardwert der Spalte an.

Das Feld Extra enthält zusätzliche Angaben, die zu einer gegebenen Spalte verfügbar sind. Im gezeigten Beispiel gibt Extra an, dass die Spalte Id mit dem Schlüsselwort AUTO_INCREMENT erstellt wurde.

Die Anweisung DESCRIBE ist aus Gründen der Kompatibilität mit Oracle vorhanden.

Auch die Anweisungen SHOW CREATE TABLE und SHOW TABLE STATUS bieten Informationen zu Tabellen. Siehe auch Abschnitt 13.5.4, „SHOW.

13.3.2. USE

USE db_name

Die Anweisung USE db_name weist MySQL an, die Datenbank db_name als Standarddatenbank (d. h. als aktuelle Datenbank) zu benutzen, auf die sich nachfolgende Anweisungen beziehen. Die Datenbank wird bis zum Ende der Sitzung oder aber so lange als Vorgabe verwendet, bis eine andere USE-Anweisung abgesetzt wird:

USE db1;
SELECT COUNT(*) FROM mytable;   # selects from db1.mytable
USE db2;
SELECT COUNT(*) FROM mytable;   # selects from db2.mytable

Wenn Sie eine bestimmte Datenbank mit USE zur Standarddatenbank machen, können Sie trotzdem auf Tabellen in anderen Datenbanken zugreifen. Im folgenden Beispiel wird auf die Tabelle author in der Datenbank db1 und die Tabelle editor in der Datenbank db2 zugegriffen:

USE db1;
SELECT author_name,editor_name FROM author,db2.editor
  WHERE author.editor_id = db2.editor.editor_id;

Die Anweisung USE ist aus Gründen der Kompatibilität mit Sybase vorhanden.

13.4. Transaktionale und Sperrbefehle von MySQL

MySQL unterstützt lokale Transaktionen (über eine gegebene Clientverbindung) unter Verwendung von Anweisungen wie SET AUTOCOMMIT, START TRANSACTION, COMMIT und ROLLBACK. Siehe auch Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK. Die Unterstützung von XA-Transaktionen erlaubt MySQL außerdem die Teilnahme an verteilten Transaktionen. Siehe auch Abschnitt 13.4.7, „XA-Transaktionen“.

13.4.1. BEGIN/COMMIT/ROLLBACK

START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}

Die Anweisungen START TRANSACTION und BEGIN starten eine neue Transaktion. COMMIT übergibt die aktuelle Transaktion, macht also die entsprechenden Änderungen permanent. Mit ROLLBACK machen Sie die laufende Transaktion rückgängig, d. h., alle Änderungen werden zurückgenommen. Die Anweisung SET AUTOCOMMIT schließlich aktiviert oder deaktiviert den standardmäßigen Autocommit-Modus für die aktuelle Verbindung.

Das optionale Schlüsselwort WORK wird für COMMIT und RELEASE unterstützt, ebenso die CHAIN- und RELEASE-Klauseln. CHAIN und RELEASE können verwendet werden, um den Transaktionsabschluss besser steuern zu können. Der Wert der Systemvariablen completion_type bestimmt das Standardverhalten beim Transaktionsabschluss. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“.

Die AND CHAIN-Klausel bewirkt, dass eine neue Transaktion beginnt, sobald die aktuelle endet. Die neue Transaktion hat dabei dieselbe Isolierungsstufe wie die zuvor beendete Transaktion. Die RELEASE-Klausel bewirkt, dass der Server die aktuelle Clientverbindung nach Abschluss der aktuellen Transaktion beendet. Das Schlüsselwort NO unterdrückt den Abschluss von CHAIN oder RELEASE. Dies kann nützlich sein, wenn aufgrund der Einstellung der Systemvariablen completion_type der Abschluss von CHAIN oder RELEASE standardmäßig erzwungen wird.

Standardmäßig läuft MySQL im Autocommit-Modus. Das bedeutet, dass, sobald eine Anweisung ausgeführt wird, die eine Tabelle aktualisiert (also ändert), MySQL diese Änderung auf Festplatte speichert.

Verwenden Sie eine transaktionssichere Speicher-Engine (wie InnoDB, BDB oder NDB Cluster), dann können Sie den Autocommit-Modus mit der folgenden Anweisung deaktivieren:

SET AUTOCOMMIT=0;

Nach der Deaktivierung des Autocommit-Modus durch Setzen der AUTOCOMMIT-Variablen auf Null müssen Sie Ihre Änderungen mit COMMIT auf Festplatte speichern oder mit ROLLBACK rückgängig machen, wenn Sie die seit Beginn der Transaktion vorgenommenen Änderungen nicht übernehmen wollen.

Um den Autocommit-Modus für eine einzelne Abfolge von Anweisungen zu deaktivieren, verwenden Sie die Anweisung START TRANSACTION:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

Bei START TRANSACTION bleibt Autocommit deaktiviert, bis Sie die Transaktion mit COMMIT oder ROLLBACK beenden. Der Autocommit-Modus kehrt dann in seinen vorherigen Status zurück.

BEGIN und BEGIN WORK werden als Aliase für START TRANSACTION benutzt, um eine Transaktion zu starten. START TRANSACTION ist die SQL-Standardsyntax und wird als Möglichkeit zur Durchführung spontaner Transaktionen empfohlen.

Die BEGIN-Anweisung unterscheidet sich von der Verwendung des Schlüsselworts BEGIN, welches eine mehrteilige BEGIN ... END-Anweisung einleitet. Mit Letzterem wird keine Transaktion begonnen. Siehe auch Abschnitt 19.2.5, „BEGIN ... END-Syntax für komplexe Anweisungen“.

Sie können eine Transaktion auch wie folgt einleiten:

START TRANSACTION WITH CONSISTENT SNAPSHOT;

Die Klausel WITH CONSISTENT SNAPSHOT startet eine konsistente Leseoperation für Speicher-Engines, die diese unterstützen. Derzeit betrifft dies nur InnoDB. Der Effekt ist derselbe wie beim Absetzen einer START TRANSACTION-Anweisung gefolgt von einer SELECT-Anweisung für eine beliebige InnoDB-Tabelle. Siehe auch Abschnitt 14.2.10.4, „Konsistentes Lesen“.

Die Klausel WITH CONSISTENT SNAPSHOT ändert die aktuelle Isolationsstufe der Transaktion nicht, d. h., eine konsistente Momentaufnahme wird nur dann erstellt, wenn die aktuelle Isolationsstufe konsistente Leseoperationen gestattet (REPEATABLE READ oder SERIALIZABLE).

Bei Beginn einer Transaktion wird implizit UNLOCK TABLES ausgeführt.

Beste Ergebnisse erhalten Sie, wenn Sie Transaktionen nur bei Tabellen durchführen, die mit einer einzelnen transaktionssicheren Speicher-Engine verwaltet werden. Andernfalls können die folgenden Probleme auftreten:

  • Wenn Ihre Tabellen mehrere transaktionssichere Speicher-Engines verwenden (z. B. InnoDB und BDB) und die Isolationsstufe nicht SERIALIZABLE ist, besteht die Möglichkeit, dass, wenn eine Transaktion übergeben wird, eine andere laufende Transaktion, die dieselben Tabellen benutzt, nur einen Teil der durch die erste Transaktion vorgenommenen Änderungen erkennt. Die Atomizität der Transaktionen ist mithin bei Verwendung mehrerer Engines nicht gewährleistet, und es können Inkonsistenzen auftreten. (Wenn Transaktionen mehrerer Engines nicht häufig vorkommen, können Sie die Isolationsstufe mit SET TRANSACTION ISOLATION LEVEL für eine Transaktion nach Bedarf auf SERIALIZABLE setzen.)

  • Verwenden Sie in einer Transaktion nichttransaktionssichere Tabellen, dann werden alle Änderungen an diesen Tabellen unabhängig vom Status des Autocommit-Modus sofort gespeichert.

    Wenn Sie nach Aktualisierung einer nichttransaktionssicheren Tabelle in einer Transaktion eine ROLLBACK-Anweisung absetzen, erscheint die Warnung ER_WARNING_NOT_COMPLETE_ROLLBACK. Änderungen an transaktionssicheren Tabellen werden in diesem Fall rückgängig gemacht, nicht jedoch Änderungen an nichttransaktionssicheren Tabellen.

Jede Transaktion wird nach Absetzen von COMMIT am Stück in das Binärlog geschrieben. Transaktionen, die per Rollback rückgängig gemacht wurden, werden nicht geloggt. (Ausnahme: Für Modifikationen an nicht transaktionssicheren Tabellen kann kein Rollback durchgeführt werden. Wenn eine Transaktion, für die ein Rollback erfolgt, Änderungen an nicht transaktionssicheren Tabellen enthält, dann wird die gesamte Transaktion am Ende mit einer ROLLBACK-Anweisung geloggt, um sicherzustellen, dass die Modifikationen an diesen Tabellen repliziert werden.) Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.

Sie können die Isolationsstufe für Transaktionen mit SET TRANSACTION ISOLATION LEVEL ändern. Siehe auch Abschnitt 13.4.6, „SET TRANSACTION.

Ein Rollback kann ein relativ langsamer Vorgang sein, der zudem stattfinden kann, ohne dass der Benutzer dies explizit angefordert hat (z. B. wenn ein Fehler aufgetreten ist). Aufgrund dieser Tatsache zeigt SHOW PROCESSLIST in der Spalte State für die Verbindung Rolling back an, solange implizite oder (durch die SQL-Anweisung ROLLBACK) explizite Rollbacks durchgeführt werden.

13.4.2. Statements können nicht zurückgerollt werden

Es gibt Anweisungen, für die kein Rollback möglich ist. Hierzu gehören DDL-Anweisungen (Data Definition Language), z. B. solche, mit denen Datenbanken erstellt oder gelöscht oder Tabellen oder gespeicherte Routinen erstellt, gelöscht oder geändert werden.

Sie sollten Ihre Transaktionen so entwickeln, dass solche Anweisungen nicht vorhanden sind. Wenn Sie eine Anweisung früh in einer Transaktion absetzen, für die kein Rollback möglich ist, und dann später eine andere Anweisung fehlschlägt, dann können durch Absetzen der ROLLBACK-Anweisung nicht alle Auswirkungen der Transaktion rückgängig gemacht werden.

13.4.3. Anweisungen, die implizite Commits verursachen

Alle folgenden Anweisungen (und ggf. auch ihre Synonyme) beenden eine Transaktion implizit – so als ob Sie vor Ausführung der Anweisung eine COMMIT-Anweisung abgesetzt hätten:

  • ALTER FUNCTION, ALTER PROCEDURE, ALTER TABLE, BEGIN, CREATE DATABASE, CREATE FUNCTION, CREATE INDEX, CREATE PROCEDURE, CREATE TABLE, DROP DATABASE, DROP FUNCTION, DROP INDEX, DROP PROCEDURE, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE TABLE, UNLOCK TABLES.

  • UNLOCK TABLES übergibt eine Transaktion nur dann, wenn zum betreffenden Zeitpunkt Tabellen gesperrt sind.

  • Die Anweisung CREATE TABLE in InnoDB wird als einzelne Transaktion verarbeitet. Das bedeutet, dass eine ROLLBACK-Anweisung seitens des Benutzers die CREATE TABLE-Anweisungen, die der Benutzer während der Transaktion abgesetzt hat, nicht rückgängig machen kann.

Transaktionen können nicht verschachtelt werden. Dies ist eine Folge des impliziten COMMIT, das für jede laufende Transaktion ausgeführt wird, wenn Sie eine START TRANSACTION-Anweisung (oder ein entsprechendes Synonym) absetzen.

13.4.4. SAVEPOINT und ROLLBACK TO SAVEPOINT

SAVEPOINT identifier
ROLLBACK [WORK] TO SAVEPOINT identifier
RELEASE SAVEPOINT identifier

InnoDB unterstützt die SQL-Anweisungen SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT und das optionale Schlüsselwort WORK für ROLLBACK.

Die SAVEPOINT-Anweisung setzt einen benannten Transaktionsspeicherpunkt mit dem Namen identifier. Hat die laufende Transaktion einen Speicherpunkt gleichen Namens, dann wird der alte Speicherpunkt gelöscht und ein neuer gesetzt.

Die Anweisung ROLLBACK TO SAVEPOINT macht eine Transaktion bis zum benannten Speicherpunkt rückgängig. Änderungen, die die aktuelle Transaktion an Datensätzen nach dem Speicherpunkt vorgenommen hat, werden im Rollback rückgängig gemacht; allerdings hebt InnoDB Datensatzsperren, die nach dem Speicherpunkt im Speicher abgelegt wurden, nicht auf. (Beachten Sie, dass bei einem neu eingefügten Datensatz die Sperrinformation in dem im Datensatz gespeicherten Transaktionsbezeichner enthalten ist, d. h., die Sperre wird nicht separat im Speicher abgelegt. In diesem Fall wird die Datensatzsperre beim Rückgängigmachen aufgehoben.) Speicherpunkte, die zeitlich nach dem genannten Speicherpunkt liegen, werden gelöscht.

Wenn die ROLLBACK TO SAVEPOINT-Anweisung den folgenden Fehler zurückgibt, heißt das, dass es keinen Speicherpunkt des angegebenen Namens gibt:

ERROR 1181: Got error 153 during ROLLBACK

Die Anweisung RELEASE SAVEPOINT entfernt den genannten Speicherpunkt aus der Menge der Speicherpunkte für die laufende Transaktion. Es findet weder eine Übergabe noch ein Rollback statt. Existiert der Speicherpunkt nicht, dann tritt ein Fehler auf.

Alle Speicherpunkte der aktuellen Transaktion werden gelöscht, wenn Sie eine COMMIT- oder ROLLBACK-Anweisung absetzen, die keinen Speicherpunkt benennt.

Seit MySQL 5.0.17 wird eine neue Speicherpunktstufe erstellt, wenn eine gespeicherte Funktion aufgerufen oder ein Trigger aktiviert wird. Die Speicherpunkte der vorherigen Stufen sind dann nicht mehr verfügbar, damit Konflikte mit Speicherpunkten der neuen Stufe vermieden werden. Wenn die Funktion oder der Trigger beendet wird, werden alle hierdurch erstellten Speicherpunkte gelöscht und die vorherige Speicherpunktstufe wird wiederhergestellt.

13.4.5. LOCK TABLES und UNLOCK TABLES

LOCK TABLES
    tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
    [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
UNLOCK TABLES

LOCK TABLES sperrt Tabellen für den aktuellen Thread. Wenn eine Tabelle von anderen Threads gesperrt ist, wird der laufende Vorgang angehalten, bis alle Sperren erwirkt werden können. UNLOCK TABLES hebt Sperren auf, die vom aktuellen Thread gehalten werden. Die Sperren aller Tabellen, die vom aktuellen Thread gesperrt werden, werden implizit aufgehoben, wenn der Thread eine andere LOCK TABLES-Anweisung absetzt oder die Verbindung zum Server geschlossen wird.

Eine Tabellensperre schützt nur gegen unangemessene Lese- und Schreiboperationen durch andere Clients. Der Client, der die Sperre (auch eine Lesesperre) hält, kann Operationen auf Tabellenebene – wie etwa DROP TABLE – durchführen.

Beachten Sie die folgenden Angaben zur Verwendung von LOCK TABLES bei transaktionssicheren Tabellen:

  • LOCK TABLES ist nicht transaktionssicher und übergibt implizit alle aktiven Transaktionen, bevor versucht wird, die Sperre für die Tabelle zu erwirken. Auch das Starten einer Transaktion (z. B. bei START TRANSACTION) führt implizit eine UNLOCK TABLES-Anweisung aus. (Siehe auch Abschnitt 13.4.3, „Anweisungen, die implizite Commits verursachen“.)

  • Die korrekte Vorgehensweise bei der Verwendung von LOCK TABLES in Verbindung mit transaktionssicheren Tabellen wie InnoDB besteht darin, AUTOCOMMIT = 0 zu setzen und UNLOCK TABLES erst dann aufzurufen, wenn die Transaktion explizit übergeben werden soll. Wenn Sie LOCK TABLES aufrufen, setzt InnoDB intern eine eigene Tabellensperre. Auch MySQL setzt eine eigene Tabellensperre. InnoDB hebt seine Sperre beim nächsten Commit-Vorgang auf; damit MySQL seinerseits die Sperre aufhebt, müssen Sie UNLOCK TABLES aufrufen. Sie sollten AUTOCOMMIT = 1 nicht setzen, weil InnoDB dann seine Tabellensperre direkt nach dem Aufruf von LOCK TABLES aufhebt; auf diese Weise kann es zu einer vollständigen Sperrung kommen. Beachten Sie, dass bei AUTOCOMMIT = 1 die InnoDB-Tabellensperre überhaupt nicht gesetzt wird, damit ältere Anwendungen sich nicht versehentlich vollständig ausschließen.

  • ROLLBACK hebt die Sperren bei den nichttransaktionssicheren Tabellen von MySQL nicht auf.

Um LOCK TABLES zu verwenden, benötigen Sie die Berechtigungen LOCK TABLES und SELECT für die betreffenden Tabellen.

Die wichtigsten Gründe zur Verwendung von LOCK TABLES sind die Emulation von Transaktionen oder die Beschleunigung der Aktualisierung von Tabellen. Wir werden dies weiter unten ausführlicher erläutern.

Wenn ein Thread eine Lesesperre für eine Tabelle erwirkt, kann dieser Thread (wie auch alle übrigen Threads) aus der Tabelle nur lesen. Wenn ein Thread eine Schreibsperre für eine Tabelle erwirkt, dann kann nur der Thread, der die Sperre hält, in die Tabelle schreiben. Anderen Threads wird dies untersagt, bis die Sperre aufgehoben ist.

Der Unterschied zwischen READ LOCAL und READ besteht darin, dass READ LOCAL bei aktiver Sperre die Ausführung von INSERT-Anweisungen (also nebenläufigen Einfügeoperationen) zulässt, sofern sie keine Konflikte auslösen. Allerdings kann diese Funktion nicht verwendet werden, um die Datenbankdateien bei aktiver Sperre außerhalb von MySQL zu manipulieren. Bei InnoDB-Tabellen entspricht READ LOCAL READ.

Wenn Sie LOCK TABLES einsetzen, müssen Sie alle Tabellen sperren, die Sie in Ihren Abfragen zu benutzen beabsichtigen. Solange die mit einer LOCK TABLES-Anweisung erwirkten Sperren gültig sind, können Sie nicht auf Tabellen zugreifen, die nicht durch die Anweisung gesperrt wurden. Ferner können Sie eine gesperrte Tabelle auch nicht mehrfach in derselben Abfrage verwenden. Benutzen Sie stattdessen Aliase. In diesem Fall müssen Sie allerdings für jeden Alias separat eine Sperre erwirken.

mysql> LOCK TABLE t WRITE, t AS t1 WRITE;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;

Wenn Ihre Abfragen eine Tabelle unter Verwendung eines Alias referenzieren, müssen Sie die Tabelle sperren, die denselben Alias benutzt. Die Tabelle zu sperren, ohne den Alias anzugeben, funktioniert nicht:

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

Umgekehrt müssen Sie, wenn Sie eine Tabelle unter Verwendung eines Alias sperren, diese Tabelle unter Verwendung dieses Alias in Ihren Abfragen referenzieren:

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

WRITE-Sperren haben in der Regel Vorrang vor READ-Sperren. Hierdurch soll sichergestellt werden, dass Aktualisierungen so schnell wie möglich verarbeitet werden. Das bedeutet, dass, wenn ein Thread eine READ-Sperre erwirkt und dann ein anderer Thread eine WRITE-Sperre anfordert, nachfolgende READ-Sperranforderungen warten müssen, bis der WRITE-Thread die Sperre wieder aufgehoben hat. Sie können mit LOW_PRIORITY WRITE-Sperren anderen Threads das Erwirken von READ-Sperren gestatten, während der Thread auf die WRITE-Sperre wartet. LOW_PRIORITY WRITE-Sperren sollten Sie nur dann verwenden, wenn Sie sicher sind, dass zu einem nachfolgenden Zeitpunkt keine Threads mehr eine READ-Sperre halten werden.

LOCK TABLES funktioniert wie folgt:

  1. Alle zu sperrenden Tabellen werden in einer intern definierten Reihenfolge sortiert. Aus Sicht des Benutzers ist diese Reihenfolge undefiniert.

  2. Wenn eine Tabelle mit einer Lese- und einer Schreibsperre gesperrt ist, wird die Schreib- vor der Lesesperre gesetzt.

  3. Es wird immer nur eine Tabelle gleichzeitig gesperrt, bis der Thread alle Sperren erhalten hat.

Diese Vorgehensweise gewährleistet, dass ein Aussperren ausgeschlossen ist. Es gibt jedoch ein paar andere Aspekte, die Sie bezüglich der Vorgehensweise beachten sollten:

Wenn Sie eine LOW_PRIORITY WRITE-Sperre für eine Tabelle verwenden, bedeutet dies lediglich, dass MySQL auf diese bestimmte Sperre wartet, bis keine Threads mehr vorhanden sind, die eine READ-Sperre benötigen. Wenn der Thread die WRITE-Sperre erwirkt hat und darauf wartet, die Sperre für die nächste Tabelle in der Sperrliste zu erwirken, warten alle anderen Threads darauf, dass die WRITE-Sperre aufgehoben wird. Wenn dies in Bezug auf Ihre Anwendung ein schwerwiegendes Problem darstellen sollte, dann sollten Sie in Betracht ziehen, einige Ihrer Tabellen in transaktionssichere Tabellen umzuwandeln.

Sie können einen Thread, der auf eine Tabellensperre wartet, problemlos mit KILL terminieren. Siehe auch Abschnitt 13.5.5.3, „KILL.

Beachten Sie, dass Sie keine Tabellen sperren sollen, die Sie mit INSERT DELAYED verwenden, weil die Einfügeoperation in diesem Fall durch einen separaten Thread durchgeführt wird.

Normalerweise müssen Sie Tabellen nicht sperren, weil alle UPDATE-Anweisungen für sich atomisch sind: Kein anderer Thread kann eine andere derzeit ausgeführte SQL-Anweisung unterbrechen. Allerdings gibt es einige wenige Fälle, in denen das Sperren von Tabellen von Vorteil sein kann:

  • Wenn Sie viele Operationen für eine Anzahl von MyISAM-Tabellen ausführen wollen, geht dies schneller, wenn Sie die zu verwendenden Tabellen sperren. Das Sperren von MyISAM-Tabellen beschleunigt das Einfügen, Aktualisieren und Löschen in diesen Tabellen. Der Nachteil besteht darin, dass kein Thread eine READ-gesperrte Tabelle ändern kann (einschließlich derjenigen, die die Sperre hält) und dass kein Thread auf eine WRITE-gesperrte Tabelle mit Ausnahme derjenigen zugreifen kann, die die Sperre hält.

    Der Grund dafür, dass MyISAM-Operationen unter LOCK TABLES schneller ausgeführt werden, besteht darin, dass MySQL den Schlüssel-Cache gesperrter Tabellen erst beim Aufruf von UNLOCK TABLES synchronisiert. Normalerweise wird der Schlüssel-Cache nach jeder SQL-Anweisung synchronisiert.

  • Wenn Sie eine Speicher-Engine in MySQL verwenden, die Transaktionen nicht unterstützt, müssen Sie LOCK TABLES einsetzen, um sicherzustellen, dass kein anderer Thread zwischen eine SELECT- und eine UPDATE-Anweisung gelangt. Folgendes Beispiel erfordert LOCK TABLES, um sicher ausgeführt werden zu können:

    LOCK TABLES trans READ, customer WRITE;
    SELECT SUM(value) FROM trans WHERE customer_id=some_id;
    UPDATE customer
      SET total_value=sum_from_previous_statement
      WHERE customer_id=some_id;
    UNLOCK TABLES;
    

    Ohne LOCK TABLES könnte ein anderer Thread unter Umständen zwischen der Ausführung der SELECT- und der Ausführung der UPDATE-Anweisung einen neuen Datensatz in die trans-Tabelle einfügen.

Sie können die Verwendung von LOCK TABLES in vielen Fällen umgehen, indem Sie relative Updates (UPDATE customer SET value=value+new_value) oder die Funktion LAST_INSERT_ID() verwenden. Siehe auch Abschnitt 1.9.5.3, „Transaktionen“.

Sie können das Sperren von Tabellen in manchen Fällen auch umgehen, indem Sie Funktionen für beratende Sperrungen auf Benutzerebene (GET_LOCK() und RELEASE_LOCK()) verwenden. Diese Sperren werden in einer Hash-Tabelle auf dem Server gespeichert und mit pthread_mutex_lock() und pthread_mutex_unlock() mit dem Ziel einer hohen Geschwindigkeit implementiert. Siehe auch Abschnitt 12.10.4, „Verschiedene Funktionen“.

Weitere Informationen zu Methoden beim Sperren finden Sie in Abschnitt 7.3.1, „Wie MySQL Tabellen sperrt“.

Sie können mit der Anweisung FLUSH TABLES WITH READ LOCK Lesesperren für alle Tabellen in allen Datenbanken setzen. Siehe auch Abschnitt 13.5.5.2, „FLUSH. Dies ist eine recht praktische Möglichkeit der Datensicherung, wenn Sie ein Dateisystem wie Veritas einsetzen, das rechtzeitig Schnappschüsse erstellt.

Hinweis: Wenn Sie ALTER TABLE für eine gesperrte Tabelle ausführen, kann die Sperre unter Umständen aufgehoben werden. Siehe auch Abschnitt A.7.1, „Probleme mit ALTER TABLE.

13.4.6. SET TRANSACTION

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

Diese Anweisung bestimmt die Transaktionsisolationsstufe für die nächste Transaktion, global oder für die aktuelle Sitzung.

Das Standardverhalten von SET TRANSACTION besteht darin, die Isolationsstufe für die nächste (d. h. noch nicht gestartete) Transaktion einzustellen. Wenn Sie das Schlüsselwort GLOBAL verwenden, setzt die Anweisung die Standardtransaktionsstufe global für alle neuen Verbindungen, die nachfolgend hergestellt werden. Vorhandene Verbindungen werden hiervon nicht berührt. Für diesen Zweck benötigen Sie die Berechtigung SUPER. Bei Verwendung des Schlüsselworts SESSION wird die standardmäßige Transaktionsstufe für alle zukünftigen Transaktionen gesetzt, die über die aktuelle Verbindung durchgeführt werden.

Beschreibungen aller InnoDB-Transaktionsisolationsstufen finden Sie in Abschnitt 14.2.10.3, „InnoDB und TRANSACTION ISOLATION LEVEL. InnoDB unterstützt in MySQL 5.1 alle Stufen. Die Standardstufe ist REPEATABLE READ.

Um die globale Standardisolationsstufe für mysqld festzulegen, verwenden Sie die Option --transaction-isolation. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld.

13.4.7. XA-Transaktionen

Die Unterstützung von XA-Transaktionen ist für die InnoDB-Speicher-Engine verfügbar. Die XA-Implementierung bei MySQL basiert auf dem X/Open CAE-Dokument Distributed Transaction Processing: The XA Specification („Verteilte Transaktionsverarbeitung: Die XA-Spezifikation“). Dieses Dokument wurde von The Open Group veröffentlicht und ist unter http://www.opengroup.org/public/pubs/catalog/c193.htm erhältlich. Die Grenzen der aktuellen XA-Implementierung sind in Abschnitt I.5, „Beschränkungen bei XA-Transaktionen“ beschrieben.

Clientseitig gibt es keine besonderen Anforderungen. Die XA-Schnittstelle zu einem MySQL Server besteht aus SQL-Anweisungen, die mit dem Schlüsselwort XA beginnen. MySQL-Clientprogramme müssen SQL-Anweisungen senden und die Semantik der XA-Anweisungsschnittstelle verstehen können. Sie müssen nicht mit einer aktuellen Clientbibliothek verknüpft sein: Es können auch ältere Clientbibliotheken verwendet werden.

Derzeit unterstützt MySQL Connector/J 5.0.0 XA direkt (mithilfe einer Klassenschnittstelle, die die XA-SQL-Anweisungsschnittstelle für Sie verwaltet).

XA unterstützt verteilte Transaktionen, d. h., mehrere separate transaktionssichere Ressourcen können an einer globalen Transaktion teilnehmen. Transaktionssichere Ressourcen sind häufig relationale Datenbanksysteme, es gibt aber auch andere Ressourcentypen.

Eine globale Transaktion umfasst mehrere Aktionen, die für sich transaktionssicher sind; sie alle aber müssen entweder als Gruppe erfolgreich abgeschlossen werden, oder sie werden im Rahmen eines Rollbacks gemeinsam rückgängig gemacht. Im Endeffekt erweitert dies die ACID-Eigenschaften um eine „Ebene nach oben“, sodass mehrere ACID-Transaktionen konzertiert als Komponenten einer globalen Operation ausgeführt werden, die ebenfalls ACID-Eigenschaften hat. (Allerdings müssen Sie bei einer verteilten Transaktion die Isolationsstufe SERIALIZABLE benutzen, um ACID-Eigenschaften zu erhalten. Bei nichtverteilten Transaktionen ist REPEATABLE READ ausreichend, nicht aber bei verteilten Transaktionen.)

Es folgen einige Beispiele für verteilte Transaktionen:

  • Eine Anwendung kann als Integrations-Tool agieren, welches einen Messaging-Dienst mit einem relationalen Datenbanksystem kombiniert. Die Anwendung stellt sicher, dass Transaktionen, die Versand, Abruf und Verarbeitung von Mitteilungen in Verbindung mit einer transaktionssicheren Datenbank regeln, auch alle in einer globalen Transaktion erfolgen. Man könnte sich dies als „transaktionssichere E-Mail“ vorstellen.

  • Eine Anwendung führt Aktionen durch, die verschiedene Datenbankserver betrifft, z. B. einen MySQL und einen Oracle-Server (oder auch mehrere MySQL Server). Hierbei müssen Aktionen, die mehrere Server betreffen, als Teil einer globalen Transaktion statt als separate Transaktionen stattfinden, die auf jedem Server getrennt ausgeführt werden.

  • Eine Bank speichert Kontendaten in einem relationalen Datenbanksystem. Empfang und Versand von Geld erfolgen über Bankautomaten. Es muss dabei gewährleistet sein, dass alle Vorgänge an den Automaten auf den Konten umgesetzt werden. Dies ist aber nicht allein mit dem Datenbanksystem möglich: Ein globaler Transaktionsmanager integriert Bankautomat- und Datenbankressourcen, um die Gesamtkonsistenz der Finanztransaktionen sicherzustellen.

Anwendungen, die globale Transaktionen verwenden, umfassen einen oder mehrere Ressourcenmanager und einen Transaktionsmanager:

  • Der Ressourcenmanager (RM) ermöglicht den Zugriff auf transaktionssichere Ressourcen. Ein Datenbankserver ist eine Art von Ressourcenmanager. Transaktionen, die vom RM verwaltet werden, müssen entweder im Rahmen eines Commits geschrieben oder im Zuge eines Rollbacks rückgängig gemacht werden können.

  • Ein Transaktionsmanager (TM) koordiniert die Transaktionen, die Teil einer globalen Transaktion sind. Er kommuniziert mit den RMs, die die einzelnen Transaktionen verwalten. Die einzelnen Transaktionen innerhalb einer globalen Transaktion sind die „Verzweigungen“ der globalen Transaktion. Globale Transaktionen und ihre Verzweigungen werden anhand eines Namensschemas unterschieden, welches weiter unten beschrieben werden wird.

Die MySQL-Implementierung von XA erlaubt es einem MySQL Server, als RM zu agieren, der XA-Transaktionen innerhalb einer globalen Transaktion verwaltet. Ein Clientprogramm, das eine Verbindung mit dem MySQL Server herstellt, agiert als TM.

Um eine globale Transaktion auszuführen, ist es erforderlich zu wissen, welche Komponenten betroffen sind, und jede dieser Komponenten an einen Punkt zu bringen, an dem sie übergeben oder rückgängig gemacht werden kann. Abhängig davon, was jede Komponente bezüglich ihres Erfolgs oder Fehlschlags meldet, müssen sie alle als atomische Gruppe übergeben oder rückgängig gemacht werden: Es müssen also entweder alle Komponenten geschrieben werden oder alle Komponenten werden im Zuge eines Rollbacks ungeschehen gemacht. Um eine globale Transaktion verwalten zu können, muss berücksichtigt werden, dass jede Komponente fehlschlagen oder auch das sie verbindende Netzwerk ausfallen kann.

Der Prozess zur Ausführung einer globalen Transaktion basiert auf 2PC (2-Phase Commit, Übergabe in zwei Phasen). Dies findet statt, nachdem die von den Verzweigungen der globalen Transaktion durchgeführten Vorgänge erledigt sind.

  1. In der ersten Phase werden alle Verzweigungen vorbereitet: Sie werden vom TM angewiesen, sich für die Übergabe bereitzuhalten. Normalerweise bedeutet dies, dass jeder RM, der eine Verzweigung verwaltet, die Aktionen für diese Verzweigung in einem zuverlässigen Speicher ablegt. Die Verzweigungen geben an, ob dies jeweils für sie möglich ist. Die Ergebnisse werden in der zweiten Phase verwendet.

  2. In der zweiten Phase weist der TM die RMs an, eine Übergabe oder einen Rollback durchzuführen. Wenn alle Verzweigungen bei der Vorbereitung angegeben haben, dass sie für eine Übergabe bereit sind, werden sie alle zur Übergabe angewiesen. Hat jedoch mindestens eine Verzweigung im Zuge der Vorbereitung gemeldet, dass bei ihr keine Übergabe möglich ist, dann werden alle Verzweigungen zu einem Rollback angewiesen.

In manchen Fällen verwendet eine globale Transaktion unter Umständen nur eine einphasige Übergabe (1PC). Stellt beispielsweise ein TM fest, dass eine globale Transaktion nur eine einzige transaktionssichere Ressource (also nur eine Verzweigung) umfasst, dann kann diese Ressource zur selben Zeit zur Vorbereitung und Übergabe angewiesen werden.

13.4.7.1. SQL-Syntax von XA-Transaktionen

Um XA-Transaktionen in MySQL durchzuführen, verwenden Sie die folgenden Anweisungen:

XA {START|BEGIN} xid [JOIN|RESUME]

XA END xid [SUSPEND [FOR MIGRATE]]

XA PREPARE xid

XA COMMIT xid [ONE PHASE]

XA ROLLBACK xid

XA RECOVER

Bei XA START werden die Klauseln JOIN und RESUME nicht unterstützt.

Bei XA END wird die Klausel SUSPEND [FOR MIGRATE] nicht unterstützt.

Jede XA-Anweisung beginnt mit dem Schlüsselwort XA. Die meisten dieser Anweisungen erfordern einen xid-Wert. xid ist ein XA-Transaktionsbezeichner. Er gibt an, für welche Transaktion die Anweisung gilt. xid-Werte werden vom Client übergeben oder auf dem MySQL Server erzeugt. Ein xid-Wert besteht aus einem bis drei Teilen:

xid: gtrid [, bqual [, formatID ]]

gtrid ist ein globaler Transaktionsbezeichner, bqual ein Verzweigungsbezeichner und formatID eine Zahl, die das Format angibt, welches von den gtrid- und bqual-Werten verwendet wird. Wie aus der Syntax hervorgeht, sind bqual und formatID optional. Der Standardwert von bqual ist '', sofern nichts anderes angegeben ist. Der Standardwert von formatID ist 1, sofern nichts anderes angegeben ist.

gtrid und bqual müssen String-Literale sein, die jeweils bis zu 64 Byte (nicht Zeichen) lang sein dürfen. gtrid und bqual können auf unterschiedliche Art und Weise angegeben werden. Sie können einen String in Anführungszeichen ('ab'), einen Hexadezimal-String (0x6162, X'ab') oder einen Bitwert (b'nnnn') angeben.

formatID ist ein vorzeichenloser Integer.

Die gtrid - und bqual-Werte werden von den XA-Supportroutinen auf dem MySQL Server als Bytewerte interpretiert. Allerdings benutzt der Server bei der Analyse einer SQL-Anweisung, die eine XA-Anweisung enthält, einen speziellen Zeichensatz. Wenn Sie sichergehen wollen, notieren Sie gtrid und bqual als Hexadezimal-String.

xid-Werte werden normalerweise vom TM erzeugt. Die Werte, die von einem TM erzeugt werden, müssen sich von denen unterscheiden, die von anderen TMs gebildet werden. Ein gegebener TM muss seine eigenen xid-Werte in einer Werteliste, die von der Anweisung XA RECOVER zurückgegeben wird, erkennen können.

XA START xid startet eine XA-Transaktion mit dem gegebenen xid-Wert. Jede XA-Transaktion benötigt einen eindeutigen xid-Wert, d. h., der Wert darf nicht gleichzeitig von einer anderen XA-Transaktion verwendet werden. Diese Eindeutigkeit wird mithilfe der Werte gtrid und bqual erzielt. Alle nachfolgenden XA-Anweisungen für die XA-Transaktion müssen unter Verwendung desselben xid-Werts angegeben werden, der in der XA START-Anweisung übergeben wurde. Verwenden Sie eine dieser Anweisungen und geben dabei keinen xid-Wert an, der einer laufenden XA-Transaktion entspricht, dann tritt ein Fehler auf.

Eine oder mehrere XA-Transaktionen können Teil derselben globalen Transaktion sein. Alle XA-Transaktionen in einer gegebenen globalen Transaktion müssen denselben gtrid-Wert im xid-Wert benutzen. Aus diesem Grund müssen gtrid-Werte global eindeutig sein, damit keine Mehrdeutigkeiten darüber aufkommen können, zu welcher globalen Transaktion eine gegebene XA-Transaktion gehört. Der Teil bqual des xid-Werts muss sich für jede XA-Transaktion innerhalb einer globalen Transaktion unterscheiden. (Die Anforderung, dass bqual-Werte unterschiedlich sein müssen, stellt eine Einschränkung der aktuellen XA-Implementierung in MySQL dar. Sie ist nicht Teil der XA-Spezifikation.)

Die Anweisung XA RECOVER gibt Informationen zu denjenigen XA-Transaktionen auf dem MySQL Server zurück, die den Status PREPARED haben. (Siehe auch Abschnitt 13.4.7.2, „XA-Transaktionszustände“.) Die Ausgabe enthält einen Datensatz für jede derartige XA-Transaktion auf dem Server – unabhängig davon, welcher Client sie gestartet hat.

Die Ausgabedatensätze von XA RECOVER sehen wie folgt aus (für einen xid-Beispielwert, der aus den Teilen 'abc', 'def' und 7 besteht):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
|        7 |            3 |            3 | abcdef |
+----------+--------------+--------------+--------+

Die Ausgabespalten haben die nachfolgend beschriebenen Bedeutungen:

  • formatID ist der formatID-Teil der Transaktion xid.

  • gtrid_length ist die Länge des gtrid-Teils der Transaktion xid in Byte.

  • bqual_length ist die Länge des bqual-Teils der Transaktion xid in Byte.

  • data ist die Verkettung der Teile gtrid und bqual der Transaktion xid.

13.4.7.2. XA-Transaktionszustände

Eine XA-Transaktion umfasst die folgenden Phasen:

  1. Starten Sie mit XA START eine XA-Transaktion und versetzen Sie sie in den Status ACTIVE.

  2. Sobald die XA-Transaktion aktiv ist, setzen Sie die SQL-Anweisungen für die Transaktion ab. Zuletzt setzen Sie eine XA END-Anweisung ab, mit der Sie die Transaktion in den Zustand IDLE versetzen.

  3. Bei einer XA-Transaktion in diesem Zustand können Sie entweder eine XA PREPARE-Anweisung oder eine XA COMMIT ... ONE PHASE-Anweisung absetzen:

    • XA PREPARE versetzt die Transaktion in den Zustand PREPARED. Bei Eingabe einer XA RECOVER -Anweisung an dieser Stelle wird der xid-Wert der Transaktion in die Ausgabe integriert, weil XA RECOVER alle XA-Transaktionen auflistet, deren Zustand PREPARED ist.

    • XA COMMIT ... ONE PHASE bereit die Transaktion vor und übergibt sie dann direkt. Der xid-Wert wird von XA RECOVER nicht aufgelistet, weil die Transaktion endet.

  4. Bei einer XA-Transaktion im Zustand PREPARED können Sie eine XA COMMIT-Anweisung absetzen, um sie zu übergeben und zu beenden, oder Sie machen sie mit einer XA ROLLBACK-Anweisung rückgängig (sie wird dann ebenfalls beendet).

Es folgt eine einfache XA-Transaktion, die im Rahmen einer globalen Transaktion einen Datensatz in eine Tabelle einfügt:

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)

mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)

Im Kontext einer gegebenen Clientverbindung schließen sich XA-Transaktionen und lokale Transaktionen (also Nicht-XA-Transaktionen) gegenseitig aus. Wenn beispielsweise mit XA START eine XA-Transaktion gestartet wurde, dann kann eine lokale Transaktion erst begonnen werden, wenn die XA-Transaktion übergeben oder rückgängig gemacht wurde. Umgekehrt können, wenn eine lokale Transaktion mit START TRANSACTION begonnen wurde, XA-Anweisungen erst dann verwendet werden, wenn die Transaktion übergeben oder rückgängig gemacht wurde.

13.5. Anweisungen zur Datenbankadministration

13.5.1. Anweisungen zur Benutzerkontenverwaltung

MySQL-Kontendaten sind in Tabellen der Datenbank mysql gespeichert. Diese Datenbank und das Zugriffssteuerungssystem sind in Kapitel 5, Datenbankverwaltung, ausführlich beschrieben. Sie finden dort weitere Informationen.

Wichtig: Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.

13.5.1.1. CREATE USER

CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
    [, user [IDENTIFIED BY [PASSWORD] 'password']] ...

Die CREATE USER-Anweisung erstellt neue MySQL-Konten. Um sie zu verwenden, benötigen Sie die globale Berechtigung CREATE USER oder die Berechtigung INSERT für die Datenbank mysql. Für jedes Konto richtet CREATE USER einen neuen Datensatz in der Tabelle mysql.user ein, der keine Berechtigungen hat. Ist das Konto bereits vorhanden, dann tritt ein Fehler auf. Jedes Konto wird im selben Format wie bei der GRANT-Anweisung benannt (z. B. 'jeffrey'@'localhost'). Die Benutzer- und Hostbestandteile des Kontonamens entsprechen den Werten der Spalten User und Host des kontenspezifischen Datensatzes in der Tabelle user.

Das Konto erhält ein Passwort mit der optionalen IDENTIFIED BY-Klausel. Der Wert user und das Passwort werden auf gleiche Weise übergeben wie bei der GRANT-Anweisung. Insbesondere müssen Sie das Schlüsselwort PASSWORD weglassen, um das Passwort im Klartext angeben zu können. Wenn Sie das Passwort hingegen als von der Funktion PASSWORD() zurückgegebenen Hash-Wert angeben wollen, schließen Sie das Schlüsselwort PASSWORD mit ein. Siehe auch Abschnitt 13.5.1.3, „GRANT und REVOKE.

13.5.1.2. DROP USER

DROP USER user [, user] ...

Die Anweisung DROP USER entfernt ein oder mehrere MySQL-Konten. Sie löscht die Berechtigungsdatensätze des Kontos aus allen Grant-Tabellen. Um diese Anweisung zu verwenden, benötigen Sie die globale Berechtigung CREATE USER oder die Berechtigung DELETE für die Datenbank mysql. Jedes Konto wird im selben Format wie bei der GRANT-Anweisung benannt (z. B. 'jeffrey'@'localhost'). Die Benutzer- und Hostbestandteile des Kontonamens entsprechen den Werten der Spalten User und Host des kontenspezifischen Datensatzes in der Tabelle user.

Mit DROP USER können Sie ein Konto und seine Berechtigungen wie folgt entfernen:

DROP USER user;

Wichtig : DROP USER schließt offene Benutzersitzungen nicht automatisch. Stattdessen wird, wenn ein zu löschender Benutzer gerade eine offene Sitzung hat, die Anweisung erst umgesetzt, wenn die Sitzung dieses Benutzers beendet wurde. Sobald die Sitzung beendet ist, wird der Benutzer gelöscht: Nachfolgende Versuche des Benutzers, sich anzumelden, schlagen dann fehl. Dies ist bewusst so implementiert.

13.5.1.3. GRANT und REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    TO user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
    [REQUIRE
        NONE |
        [{SSL| X509}]
        [CIPHER 'cipher' [AND]]
        [ISSUER 'issuer' [AND]]
        [SUBJECT 'subject']]
    [WITH with_option [with_option] ...]

object_type =
    TABLE
  | FUNCTION
  | PROCEDURE

with_option =
    GRANT OPTION
  | MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count

Die GRANT-Anweisung erlaubt Systemadministratoren die Erstellung von MySQL-Benutzerkonten und die Vergabe von Rechten an diese Konten. Um GRANT verwenden zu können, benötigen Sie die Berechtigung GRANT OPTION sowie alle Berechtigungen, die Sie selbst gewähren. Die REVOKE-Anweisung ist in diesem Zusammenhang ebenfalls zu nennen: Sie gestattet Administratoren das Entfernen von Kontenberechtigungen. Siehe auch Abschnitt 13.5.1.5, „REVOKE.

MySQL-Kontendaten sind in Tabellen der Datenbank mysql gespeichert. Diese Datenbank und das Zugriffssteuerungssystem sind in Kapitel 5, Datenbankverwaltung, ausführlich beschrieben. Sie finden dort weitere Informationen.

Wichtig: Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.

Wenn in den Grant-Tabellen Berechtigungsdatensätze vorhanden sind, die Datenbank- oder Tabellennamen mit gemischter Groß-/Kleinschreibung enthalten, und die Systemvariable lower_case_table_names auf einen Nicht-Null-Wert gesetzt ist, dann können diese Berechtigungen nicht mit REVOKE widerrufen werden. Es ist dann erforderlich, die Grant-Tabellen direkt zu manipulieren. (GRANT erstellt solche Datensätze zwar nicht, wenn lower_case_table_names eingestellt ist, aber unter Umständen wurden derartige Datensätze bereits vor Einstellen der Variablen erstellt.)

Berechtigungen können auf unterschiedlichen Ebenen gewährt werden:

  • Globale Ebene

    Globale Berechtigungen gelten für alle Datenbanken auf einem gegebenen Server. Sie werden in der Tabelle mysql.user gespeichert. GRANT ALL ON *.* und REVOKE ALL ON *.* gewähren bzw. widerrufen nur globale Berechtigungen.

  • Datenbankebene

    Datenbankberechtigungen gelten für alle Objekte in einer gegebenen Datenbank. Sie werden in den Tabellen mysql.db und mysql.host gespeichert. GRANT ALL ON db_name.* und REVOKE ALL ON db_name.* gewähren bzw. widerrufen nur Datenbankberechtigungen.

  • Tabellenebene

    Tabellenberechtigungen gelten für alle Spalten in einer gegebenen Tabelle. Sie werden in der Tabelle mysql.tables_priv gespeichert. GRANT ALL ON db_name.tbl_name und REVOKE ALL ON db_name.tbl_name gewähren bzw. widerrufen nur Tabellenberechtigungen.

  • Spaltenebene

    Spaltenberechtigungen gelten für einzelne Spalten in einer gegebenen Tabelle. Sie werden in der Tabelle mysql.columns_priv gespeichert. Wenn Sie REVOKE verwenden, müssen Sie dieselben Spalten angeben, denen die Berechtigungen zuvor gewährt wurden.

  • Routinenebene

    Die Berechtigungen CREATE ROUTINE, ALTER ROUTINE, EXECUTE und GRANT gelten für gespeicherte Routinen (Funktionen und Prozeduren). Sie können auf der globalen und der Datenbankebene gewährt werden. Ferner lassen sich diese Berechtigungen mit Ausnahme von CREATE ROUTINE auf Routinenebene für einzelne Routinen gewähren und werden in der Tabelle mysql.procs_priv gespeichert.

Die Klausel object_type sollte als TABLE, FUNCTION bzw. als PROCEDURE angegeben werden, wenn das nachfolgende Objekt eine Tabelle, eine gespeicherte Funktion oder eine gespeicherte Prozedur ist.

Für die Anweisungen GRANT und REVOKE kann priv_type wie folgt angegeben werden:

BerechtigungBedeutung
ALL [PRIVILEGES]Setzt alle einfachen Berechtigungen außer GRANT OPTION.
ALTERErlaubt die Verwendung von ALTER TABLE.
ALTER ROUTINEErlaubt die Änderung oder Löschung gespeicherter Routinen.
CREATEErlaubt die Verwendung von CREATE TABLE.
CREATE ROUTINEErlaubt die Erstellung gespeicherter Routinen.
CREATE TEMPORARY TABLESErlaubt die Verwendung von CREATE TEMPORARY TABLE.
CREATE USERErlaubt die Verwendung von CREATE USER, DROP USER, RENAME USER und REVOKE ALL PRIVILEGES.
CREATE VIEWErlaubt die Verwendung von CREATE VIEW.
DELETEErlaubt die Verwendung von DELETE.
DROPErlaubt die Verwendung von DROP TABLE.
EVENTErlaubt die Erstellung von Ereignissen für den Ereignisplaner.
EXECUTEErlaubt dem Benutzer die Ausführung gespeicherter Routinen.
FILEErlaubt die Verwendung von SELECT ... INTO OUTFILE und LOAD DATA INFILE.
INDEXErlaubt die Verwendung von CREATE INDEX und DROP INDEX.
INSERTErlaubt die Verwendung von INSERT.
LOCK TABLESErlaubt die Verwendung von LOCK TABLES für Tabellen, für die Sie die Berechtigung SELECT haben.
PROCESSErlaubt die Verwendung von SHOW FULL PROCESSLIST.
REFERENCESNicht implementiert.
RELOADErlaubt die Verwendung von FLUSH.
REPLICATION CLIENTErlaubt dem Benutzer, die Positionen von Slave- oder Master-Servern zu erfragen.
REPLICATION SLAVEFür Replikationsslaves erforderlich (zum Lesen von Binärlogeinträgen auf dem Master).
SELECTErlaubt die Verwendung von SELECT.
SHOW DATABASESSHOW DATABASES zeigt alle Datenbanken.
SHOW VIEWErlaubt die Verwendung von SHOW CREATE VIEW.
SHUTDOWNErlaubt die Verwendung von mysqladmin shutdown.
SUPERErlaubt die Verwendung der Anweisungen CHANGE MASTER, KILL, PURGE MASTER LOGS und SET GLOBAL und des Befehls mysqladmin debug. Erlaubt ferner die (einmalige) Verbindungsherstellung auch in dem Fall, dass der Wert für max_connections erreicht wurde.
TRIGGERErlaubt dem Benutzer das Erstellen und Löschen von Triggern.
UPDATEErlaubt die Verwendung von UPDATE.
USAGESynonym für „keine Berechtigungen
GRANT OPTIONErlaubt die Gewährung von Berechtigungen.

Die Berechtigungen EVENT und TRIGGER wurden in MySQL 5.1.6 hinzugefügt. Ein Trigger ist mit einer Tabelle verknüpft, d. h., um einen Trigger zu erstellen oder zu löschen, benötigen Sie die Berechtigung TRIGGER für die Tabelle, nicht für den Trigger. (Vor MySQL 5.1.6 war für das Erstellen und Löschen von Triggern die Berechtigung SUPER erforderlich.)

Die Berechtigung REFERENCES wird derzeit nicht benutzt.

USAGE kann angegeben werden, wenn Sie einen Benutzer ohne Berechtigungen erstellen wollen.

Verwenden Sie SHOW GRANTS, um zu bestimmen, welche Berechtigungen ein Konto hat. Siehe auch Abschnitt 13.5.4.11, „SHOW GRANTS.

Sie können globale Berechtigungen mit der Syntax ON *.* oder Berechtigungen auf Datenbankebene mit der Syntax ON db_name.* konfigurieren. Wenn Sie ON * angeben und eine Standarddatenbank festgelegt haben, werden die Berechtigungen in dieser Datenbank gewährt. (Warnung: Wenn Sie ON * angeben und keine Standarddatenbank ausgewählt haben, werden die Berechtigungen global gewährt.)

Die Berechtigungen FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN und SUPER sind administrative Berechtigungen, die nur global gewährt werden können (hierzu wird die Syntax ON *.* verwendet).

Andere Berechtigungen können wahlweise global oder auf individuellen Ebenen festgelegt werden.

Die priv_type-Werte, die Sie für eine Tabelle angeben können, sind SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEX, ALTER, CREATE VIEW, SHOW VIEW und TRIGGER.

Die priv_type-Werte, die Sie (bei Verwendung einer column_list-Klausel) für eine Spalte angeben können, sind SELECT, INSERT und UPDATE.

Die priv_type-Werte, die Sie auf der Routinenebene angeben können, sind ALTER ROUTINE, EXECUTE und GRANT OPTION. CREATE ROUTINE ist keine Berechtigung auf Routinenebene, weil Sie diese Berechtigung bereits zur Erstellung einer Routine benötigen.

Auf der globalen, der Datenbank-, der Tabellen- und der Routinenebene weist GRANT ALL nur diejenigen Berechtigungen zu, die auf der gewährten Ebene vorhanden sind. So ist beispielsweise GRANT ALL ON db_name.* eine Anweisung auf Datenbankebene, d. h., es lassen sich hiermit keine nur auf globaler Ebene vorhandenen Berechtigungen (wie z. B. FILE) gewähren.

MySQL gestattet die Konfiguration von Berechtigungen auch für Datenbankobjekte, die nicht existieren. In diesen Fällen muss zu den zu gewährenden Berechtigungen auch die Berechtigung CREATE gehören. Dies ist bewusst so implementiert und soll es dem Datenbankadministrator gestatten, Benutzerkonten und Berechtigungen für Datenbankobjekte vorzubereiten, die erst später erstellt werden.

Wichtig: Wenn Sie eine Tabelle oder Datenbank löschen, widerruft MySQL Berechtigungen nicht automatisch. Wenn Sie allerdings eine Routine löschen, werden alle Berechtigungen auf Routinenebene widerrufen, die für diese Routine gewährt wurden.

Hinweis: Die Jokerzeichen ‘_’ und ‘%’ sind bei der Angabe von Datenbanknamen in GRANT-Anweisungen, die Berechtigungen auf der globalen und der Datenbankebene gewähren, zulässig. Das bedeutet beispielsweise, dass Sie, wenn Sie das Zeichen ‘_’ als Bestandteil eines Datenbanknamens verwenden wollen, dieses Zeichen als ‘\_’ in der GRANT-Anweisung angeben müssen, damit der Benutzer nicht auf weitere Datenbanken zugreifen kann, die dem entstandenen Muster entsprechen (z. B. GRANT ... ON `foo\_bar`.* TO ...).

Um das Gewähren von Rechten an Benutzer über beliebige Hosts zu gestatten, unterstützt MySQL die Angabe des user-Werts in der Form user_name@host_name. Wenn ein user_name- oder host_name-Wert als vorzeichenloser Bezeichner zulässig ist, müssen Sie ihn nicht in Anführungszeichen setzen. Allerdings sind Anführungszeichen erforderlich, um einen user_name-String mit Sonderzeichen (z. B. ‘-’) oder einen host_name-String mit Sonder- oder Jokerzeichen (wie ‘%’) anzugeben. Ein Beispiel hierfür wäre 'test-user'@'test-hostname'. Setzen Sie Benutzer- und Hostnamen separat in Anführungszeichen.

Sie können Jokerzeichen im Hostnamen verwenden. So bezeichnet etwa user_name@'%.loc.gov' jeden user_name auf einem beliebigen Host in der Domäne loc.gov, und user_name@'144.155.166.%' bezeichnet user_name auf einem beliebigen Host im Klasse-C-Subnetz 144.155.166.

Die einfache Form user_name ist ein Synonym für user_name@'%'.

MySQL unterstützt keine Jokerzeichen in Benutzernamen. Anonyme Benutzer werden durch Einfügen von Einträgen mit User='' in die Tabelle mysql.user oder durch Erstellen eines Benutzers mit einem leeren Namen mit der GRANT-Anweisung definiert:

GRANT ALL ON test.* TO ''@'localhost' ...

Wenn Sie Werte in Anführungszeichen angeben, setzen Sie Datenbank-, Tabellen-, Spalten- und Routinenamen als Bezeichner in Backticks (‘`’). Host- und Benutzernamen sowie Passwörter werden als Strings in einfache Anführungszeichen (‘'’) gesetzt.

Warnung: Wenn Sie anonymen Benutzern eine Verbindung zum MySQL Server gestatten wollen, sollten Sie auch allen lokalen Benutzern als user_name@localhost Berechtigungen gewähren. Andernfalls wird das anonyme Benutzerkonto für localhost in der Tabelle mysql.user verwendet, wenn benannte Benutzer versuchen, sich über das lokale System am MySQL Server anzumelden (die Tabelle wird bei der Installation von MySQL erstellt). Detaillierte Informationen finden Sie in Abschnitt 5.8.5, „Zugriffskontrolle, Phase 1: Verbindungsüberprüfung“.

Sie können feststellen, ob dies für Sie zutrifft, indem Sie die folgende Abfrage ausführen, die alle ggf. vorhandenen anonymen Benutzer auflistet:

SELECT Host, User FROM mysql.user WHERE User='';

Wenn Sie das lokale anonyme Benutzerkonto löschen wollen, um das beschriebene Problem zu umgehen, dann verwenden Sie folgende Anweisungen:

DELETE FROM mysql.user WHERE Host='localhost' AND User='';
FLUSH PRIVILEGES;

GRANT unterstützt Hostnamen mit einer Länge von bis zu 60 Zeichen. Die Namen von Datenbanken, Tabellen, Spalten und Routinen dürfen bis zu 64 Zeichen lang sein. Benutzernamen können bis zu 16 Zeichen umfassen. Hinweis: Die zulässige Länge für Benutzernamen kann nicht durch Änderungen an der Tabelle mysql.user modifiziert werden. Wenn Sie dies dennoch versuchen, kann dies zu unvorhersehbaren Folgen führen, die schlimmstenfalls sogar ein Anmelden von Benutzern am MySQL Server verhindern können. Sie sollten die Tabellen in der mysql-Datenbank grundsätzlich nicht auf eine andere als die von MySQL AB vorgeschriebene, in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“, geschilderte Weise ändern.

Die Berechtigungen für eine Tabelle, eine Spalte oder eine Routine werden kumulativ über ein logisches OR der Berechtigungen auf jeder der einzelnen Ebenen gebildet. Wenn die Tabelle mysql.user beispielsweise angibt, dass ein Benutzer die globale Berechtigung SELECT hat, kann ihm diese Berechtigung nicht auf der Datenbank-, der Tabellen- oder der Spaltenebene verweigert werden.

Die Berechtigungen für eine Spalte lassen sich wie folgt berechnen:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
OR routine privileges

In den meisten Fällen gewähren Sie einem Benutzer nur auf einer dieser Berechtigungsebenen Rechte – das Leben ist also normalerweise nicht so kompliziert. Ausführlich beschrieben wird die Überprüfung von Berechtigungen in Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.

Wenn Sie Berechtigungen für eine Kombination aus Benutzer- und Hostnamen gewähren, die nicht in der Tabelle mysql.user vorhanden ist, wird ein Eintrag hinzugefügt und verbleibt dort, bis er mit einer DELETE-Anweisung gelöscht wird. Anders gesagt, GRANT kann Einträge in der Tabelle user erstellen; diese lassen sich aber nicht mit REVOKE entfernen, sondern müssen explizit mit DROP USER oder DELETE gelöscht werden.

Warnung: Wenn Sie einen neuen Benutzer ohne IDENTIFIED BY-Klausel erstellen, hat der Benutzer kein Passwort. Dies ist sehr unsicher. Sie können jedoch den SQL-Modus NO_AUTO_CREATE_USER aktivieren: Hierbei wird verhindert, dass GRANT Benutzer automatisch erstellt, wenn diesem nicht mit der IDENTIFIED BY-Klausel ein nichtleeres Passwort zugewiesen wird.

Wenn ein neuer Benutzer erstellt wird oder Sie globale Gewährungsberechtigungen haben, dann wird das Passwort des Benutzers auf das in der IDENTIFIED BY-Klausel gewählte Passwort gesetzt (sofern vorhanden). Hat der Benutzer bereits ein Passwort, so wird dieses durch das neue Passwort ersetzt.

Passwörter können auch mit der Anweisung SET PASSWORD eingestellt werden. Siehe auch Abschnitt 13.5.1.6, „SET PASSWORD.

In der IDENTIFIED BY-Klausel sollte das Passwort als literaler Passwortwert übergeben werden. Es ist – anders als bei der SET PASSWORD-Anweisung – nicht erforderlich, die Funktion PASSWORD() zu verwenden. Zum Beispiel:

GRANT ... IDENTIFIED BY 'mypass';

Wenn Sie das Passwort nicht unverschlüsselt senden wollen und den Hash-Wert kennen, den PASSWORD() für das Passwort zurückgeben würde, dann können Sie diesen Hash-Wert nach dem Schlüsselwort PASSWORD angeben:

GRANT ...
IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';

In einem C-Programm können Sie den Hash-Wert mit der C-API-Funktion make_scrambled_password() ermitteln.

Wenn Sie Berechtigungen für eine Datenbank gewähren, wird bei Bedarf ein Eintrag in der Tabelle mysql.db erstellt. Wenn alle Berechtigungen für die Datenbank mit REVOKE entfernt werden, wird dieser Eintrag gelöscht.

Die Berechtigung SHOW DATABASES ermöglicht dem Konto die Anzeige von Datenbanknamen durch Absetzen einer SHOW DATABASE-Anweisung. Konten, die diese Berechtigung nicht haben, sehen nur solche Datenbanken, für die sie Berechtigungen haben; wurde der Server mit der Option --skip-show-database gestartet, dann kann die Anweisung überhaupt nicht verwendet werden.

Wenn ein Benutzer keine Berechtigungen für eine Tabelle hat, wird, wenn er (z. B. mit SHOW TABLES) eine Liste der Tabellen anfordert, der Name der betreffenden Tabelle nicht angezeigt.

Die WITH GRANT OPTION-Klausel gibt dem Benutzer die Möglichkeit, anderen Benutzern beliebige Berechtigungen zu gewähren, die der Benutzer selbst auf einer bestimmten Berechtigungsebene hat. Sie sollten bei der Vergabe der Berechtigung GRANT OPTION mit Umsicht vorgehen, weil zwei Benutzer mit unterschiedlichen Berechtigungen sich diese unter Umständen gegenseitig gewähren können!

Sie können einem anderen Benutzer keine Berechtigung gewähren, die Sie selbst nicht haben – mit GRANT OPTION können Sie nur solche Berechtigungen vergeben, über die Sie selbst auch verfügen.

Beachten Sie, dass, wenn Sie einem Benutzer die Berechtigung GRANT OPTION für eine bestimmte Berechtigungsebene gewähren, dieser Benutzer alle Berechtigungen, die er für diese Ebene hat (oder in Zukunft erhält), beliebig anderen Benutzern zuweisen kann. Angenommen, Sie gewähren einem Benutzer die Berechtigung INSERT für eine Datenbank. Wenn Sie nachfolgend die Berechtigung SELECT für die Datenbank gewähren und WITH GRANT OPTION angeben, dann kann dieser Benutzer anderen Benutzern nicht nur die Berechtigung SELECT gewähren, sondern auch die Berechtigung INSERT. Wenn Sie dann dem Benutzer die Berechtigung UPDATE für die Datenbank gewähren, kann der Benutzer die Berechtigungen INSERT, SELECT und UPDATE gewähren.

Einem nichtadministrativen Benutzer sollten Sie die Berechtigung ALTER weder global noch für die Datenbank mysql gewähren. Andernfalls kann der Benutzer das Berechtigungssystem unterlaufen, indem er Tabellen umbenennt!

Die Optionen MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR count und MAX_CONNECTIONS_PER_HOUR count begrenzen die Anzahl der Abfrage-, Update- und Anmeldevorgänge, die ein Benutzer im Verlauf einer Stunde ausführen kann. Wenn count 0 ist (Standardeinstellung), dann heißt das, dass für den Benutzer keine Beschränkung gilt.

Die Option MAX_USER_CONNECTIONS count schränkt die maximale Anzahl gleichzeitiger Verbindungen ein, die das Konto herstellen kann. Wenn count 0 ist (Standardeinstellung), dann bestimmt die Systemvariable max_user_connections die Anzahl gleichzeitiger Verbindungen für das Konto.

Hinweis: Um für einen vorhandenen Benutzer eine solche Option zur Ressourcenbeschränkung anzugeben, ohne vorhandene Berechtigungen einzuschränken, verwenden Sie GRANT USAGE ON *.* ... WITH MAX_....

Siehe auch Abschnitt 5.9.4, „Begrenzen von Benutzer-Ressourcen“.

MySQL kann zusätzlich zur normalen, auf Benutzernamen und Passwörtern basierenden Authentifizierung Attribute von X509-Zertifikaten überprüfen. Um SSL-spezifische Optionen für ein MySQL-Konto anzugeben, verwenden Sie die REQUIRE-Klausel der GRANT-Anweisung. (Hintergrundinformationen zur Verwendung von SSL mit MySQL finden Sie in Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“.)

Es gibt mehrere verschiedene Gründe zur Beschränkung der Verbindungstypen für ein gegebenes Konto:

  • Wenn für das Konto keine SSL- oder X509-Anforderungen vorhanden sind, sind unverschlüsselte Verbindungen zulässig, sofern Benutzername und Passwort gültig sind. Allerdings können nach Maßgabe des Clients auch verschlüsselte Verbindungen benutzt werden, sofern der Client über die entsprechenden Zertifikats- und Schlüsseldateien verfügt.

  • Die Option REQUIRE SSL weist den Server an, nur SSL-verschlüsselte Verbindungen für das Konto zuzulassen. Beachten Sie, dass diese Option weggelassen werden kann, wenn Zugriffssteuerungs-Datensätze vorhanden sind, die Nicht-SSL-Verbindungen zulassen.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      IDENTIFIED BY 'goodsecret' REQUIRE SSL;
    
  • REQUIRE X509 bedeutet, dass der Client ein gültiges Zertifikat vorweisen muss, dass aber das Zertifikat selbst, der Aussteller und der Zweck keine Rolle spielen. Erforderlich ist einzig und allein, dass die Signatur bei einem Zertifikat geprüft werden können muss.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      IDENTIFIED BY 'goodsecret' REQUIRE X509;
    
  • REQUIRE ISSUER 'issuer' schränkt Verbindungsversuche dahingehend ein, dass der Client ein gültiges X509-Zertifikat vorweisen muss, welches von der Zertifizierungsstelle 'issuer' ausgestellt wurde. Wenn der Client ein Zertifikat vorweist, das zwar gültig ist, aber von einem anderen Anbieter stammt, dann weist der Server die Verbindung ab. Die Verwendung von X509-Zertifikaten impliziert immer auch eine Verschlüsselung, d. h., die Option SSL wird in diesem Fall nicht benötigt.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      IDENTIFIED BY 'goodsecret'
      REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
        O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';
    

    Beachten Sie, dass die 'issuer'-Werte als einzelner String eingegeben werden sollten.

  • REQUIRE SUBJECT 'subject' schränkt Verbindungsversuche dahingehend ein, dass der Client ein gültiges X509-Zertifikat vorweisen muss, bei dem als Zweck subject angegeben ist. Wenn der Client ein Zertifikat vorweist, das zwar gültig ist, aber einen anderen Zweck angibt, dann weist der Server die Verbindung ab.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      IDENTIFIED BY 'goodsecret'
      REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
        O=MySQL demo client certificate/
        CN=Tonu Samuel/Email=tonu@example.com';
    

    Beachten Sie, dass die 'subject'-Werte als einzelner String eingegeben werden sollten.

  • REQUIRE CIPHER 'cipher' ist erforderlich, um sicherzustellen, dass Chiffren und Schlüssellängen ausreichender Stärke verwendet werden. SSL selbst kann schwach sein, wenn alte Algorithmen kurze Schlüssel zur Verschlüsselung einsetzen. Mit dieser Option können Sie die Verwendung einer bestimmten Chiffriermethode vorsehen, damit die Verbindung zulässig ist.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      IDENTIFIED BY 'goodsecret'
      REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
    

Die Optionen SUBJECT, ISSUER und CIPHER können in der REQUIRE-Klausel wie folgt kombiniert werden:

GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
  IDENTIFIED BY 'goodsecret'
  REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
    O=MySQL demo client certificate/
    CN=Tonu Samuel/Email=tonu@example.com'
  AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
    O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
  AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

Das Schlüsselwort AND zwischen den REQUIRE-Optionen ist optional.

Die Reihenfolge der Optionen ist unerheblich, allerdings darf keine Option zweimal angegeben werden.

Wenn mysqld startet, werden alle Berechtigungen in den Speicher eingelesen. Detaillierte Informationen finden Sie in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“.

Beachten Sie, dass, wenn Sie Tabellen-, Spalten- oder Routineberechtigungen auch für nur einen einzigen Benutzer verwenden, der Server die Tabellen-, Spalten- und Routineberechtigungen für alle Benutzer prüft. Dies kann MySQL ein wenig verlangsamen. Analog muss der Server, wenn Sie die Anzahl von Abfragen, Updates oder Verbindungen für Benutzer beschränken wollen, auch diese Werte überwachen.

Die wesentlichsten Unterschiede zwischen dem SQL-Standard und den MySQL-Versionen von GRANT sind die folgenden:

  • In MySQL werden Berechtigungen mit einer Kombination aus Host- und Benutzernamen (und nicht nur mit einem Benutzernamen) verknüpft.

  • Der SQL-Standard bietet keine Berechtigungen auf globaler oder Datenbankebene und unterstützt auch nicht alle von MySQL unterstützten Berechtigungstypen.

  • MySQL unterstützt die Berechtigungen TRIGGER und UNDER des SQL-Standards nicht.

  • Berechtigungen nach SQL-Standard sind hierarchisch strukturiert. Wenn Sie einen Benutzer entfernen, werden alle Berechtigungen widerrufen, die dieser Benutzer hatte. Dies gilt auch für MySQL, wenn Sie DROP USER verwenden. Siehe auch Abschnitt 13.5.1.2, „DROP USER.

  • Wenn Sie in Standard-SQL eine Tabelle löschen, werden alle Berechtigungen für die Tabelle widerrufen. Wenn Sie in Standard-SQL eine Berechtigung widerrufen, werden alle Berechtigungen, die basierend auf dieser Berechtigung gewährt wurden, ebenfalls widerrufen. In MySQL können Berechtigungen nur mit expliziten REVOKE-Anweisungen oder durch Manipulation der in den MySQL-Grant-Tabellen gespeicherten Werte gelöscht werden.

  • In MySQL können INSERT-Berechtigungen auch für nur einige der Spalten in einer Tabelle gewährt werden. In diesem Fall können Sie INSERT-Anweisungen für die Tabelle trotzdem ausführen, sofern Sie diejenigen Spalten weglassen, für die Sie keine INSERT-Berechtigung haben. Die übergangenen Spalten können auf ihre impliziten Vorgabewerte gesetzt werden, sofern der strikte SQL-Modus nicht aktiviert ist. Im strikten Modus wird die Anweisung abgewiesen, wenn eine der übergangenen Spalten keinen Vorgabewert hat. (Der SQL-Standard sieht vor, dass Sie die INSERT-Berechtigung für alle Spalten benötigen.) Abschnitt 5.2.5, „Der SQL-Modus des Servers“, beschreibt den strikten Modus. Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, erläutert implizite Vorgabewerte.

13.5.1.4. RENAME USER

RENAME USER old_user TO new_user
    [, old_user TO new_user] ...

Die RENAME USER-Anweisung benennt MySQL-Konten um. Um sie zu verwenden, benötigen Sie die globale Berechtigung CREATE USER oder die Berechtigung UPDATE für die Datenbank mysql. Ein Fehler tritt auf, wenn ein Konto mit dem alten oder neuen Namen bereits existiert. Jedes Konto wird im selben Format wie bei der GRANT-Anweisung benannt (z. B. 'jeffrey'@'localhost'). Die Benutzer- und Hostbestandteile des Kontonamens entsprechen den Werten der Spalten User und Host des kontenspezifischen Datensatzes in der Tabelle user.

13.5.1.5. REVOKE

REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Die REVOKE-Anweisung erlaubt Systemadministratoren das Widerrufen von Berechtigungen für MySQL-Konten. Um REVOKE verwenden zu können, benötigen Sie die Berechtigung GRANT OPTION sowie alle Berechtigungen, die Sie widerrufen.

Informationen zu den Ebenen, auf denen Berechtigungen vorhanden sind, den zulässigen Werten für priv_type und der Syntax zur Angabe von Benutzern und Passwörtern finden Sie in Abschnitt 13.5.1.3, „GRANT und REVOKE.

Wenn in den Grant-Tabellen Berechtigungsdatensätze vorhanden sind, die Datenbank- oder Tabellennamen mit gemischter Groß-/Kleinschreibung enthalten, und die Systemvariable lower_case_table_names auf einen Nicht-Null-Wert gesetzt ist, dann können diese Berechtigungen nicht mit REVOKE widerrufen werden. Es ist dann erforderlich, die Grant-Tabellen direkt zu manipulieren. (GRANT erstellt solche Datensätze zwar nicht, wenn lower_case_table_names eingestellt ist, aber unter Umständen wurden derartige Datensätze bereits vor Einstellen der Variablen erstellt.)

Um alle Berechtigungen zu widerrufen, verwenden Sie die folgende Syntax. Hiermit löschen Sie alle globalen Berechtigungen sowie alle Berechtigungen auf Datenbank-, Tabellen- und Spaltenebene für den oder die aufgeführten Benutzer:

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Um diese REVOKE-Syntax zu verwenden, benötigen Sie die globale Berechtigung CREATE USER oder die Berechtigung UPDATE für die Datenbank mysql.

13.5.1.6. SET PASSWORD

SET PASSWORD = PASSWORD('some password')
SET PASSWORD FOR user = PASSWORD('some password')

Die Anweisung SET PASSWORD weist einem vorhandenen MySQL-Benutzerkonto ein Passwort zu.

Die erste Syntax stellt das Passwort für den aktuellen Benutzer ein. Ein Client, der über ein nichtanonymes Konto eine Verbindung mit dem Server hergestellt hat, kann das Passwort für dieses Konto ändern.

Die zweite Syntax stellt das Passwort für ein bestimmtes Konto auf dem aktuellen Serverhost ein. Nur Clients mit der Berechtigung UPDATE für die Datenbank mysql können dies tun. Der Wert user sollte im Format user_name@host_name angegeben werden, wobei user_name und host_name exakt so aufgeführt werden müssen, wie sie in den Spalten User bzw. Host des entsprechenden Eintrags in der Tabelle mysql.user notiert sind. Wenn Sie beispielsweise einen Eintrag mit den Werten 'bob' und '%.loc.gov' in den Spalten User bzw. Host haben, dann würden Sie die Anweisung wie folgt schreiben:

SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');

Dies entspricht den folgenden Anweisungen:

UPDATE mysql.user SET Password=PASSWORD('newpass')
  WHERE User='bob' AND Host='%.loc.gov';
FLUSH PRIVILEGES;

Hinweis: Wenn Sie mit einem Clientprogramm vor Version 4.1 eine Verbindung zu einem Server unter MySQL 4.1 oder höher herstellen, verwenden Sie die obigen Anweisungen SET PASSWORD oder UPDATE erst, wenn Sie Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“, gelesen haben. Das Passwortformat wurde in MySQL 4.1 geändert, und unter bestimmten Bedingungen ist es möglich, dass Sie, wenn Sie Ihr Passwort ändern, nachfolgend keine Serververbindung mehr herstellen können.

Sie können anzeigen, unter welchem Konto der Server Sie authentifiziert hat, indem Sie SELECT CURRENT_USER() ausführen.

13.5.2. Anweisungen für die Tabellenwartung

13.5.2.1. ANALYZE TABLE

ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

ANALYZE TABLE analysiert und speichert die Schlüsselverteilung für eine Tabelle. Während der Analyse ist die Tabelle mit einer Lesesperre versehen. Diese Anweisung funktioniert nur bei MyISAM-, BDB- und InnoDB-Tabellen. Bei MyISAM-Tabellen ist sie äquivalent zur Verwendung von myisamchk -a.

MySQL verwendet die gespeicherte Schlüsselverteilung, um die Reihenfolge zu ermitteln, in der die Tabellen verknüpft werden sollen, wenn Sie einen Join mit etwas anderem als einer Konstante durchführen.

ANALYZE TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer analyze
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

Sie können die gespeicherte Schlüsselverteilung mit der SHOW INDEX-Anweisung vergleichen. Siehe auch Abschnitt 13.5.4.12, „SHOW INDEX.

Wenn die Tabelle seit der letzten ANALYZE TABLE-Anweisung nicht geändert wurde, wird die Tabelle nicht erneut analysiert.

ANALYZE TABLE-Anweisungen werden in das Binärlog geschrieben, sofern das optionale Schlüsselwort NO_WRITE_TO_BINLOG (oder sein Alias LOCAL) nicht verwendet wird. Dies wird gemacht, damit ANALYZE TABLE-Anweisungen, die auf einem MySQL Server verwendet werden, der als Replikationsmaster agiert, standardmäßig auf den Replikationsslave repliziert werden.

13.5.2.2. BACKUP TABLE

BACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'

Hinweis: Diese Anweisung ist veraltet. Wir arbeiten derzeit an einem besseren Ersatz, der auch die Online-Sicherung unterstützt. In der Zwischenzeit kann stattdessen das Skript mysqlhotcopy verwendet werden.

BACKUP TABLE kopiert die minimale Anzahl an Tabellendateien, die zur Wiederherstellung der Tabelle benötigt werden, in das Sicherungsverzeichnis, nachdem ggf. gepufferte Änderungen auf Festplatte geschrieben wurden. Die Anweisung funktioniert nur bei MyISAM-Tabellen. Sie kopiert die Definitionsdatei (.frm) und die Datendatei (.MYD). Die .MYI-Indexdatei kann aus diesen beiden Dateien neu erstellt werden. Das Verzeichnis sollte als vollständiger Pfadname angegeben werden. Um die Tabelle wiederherzustellen, verwenden Sie RESTORE TABLE.

Während des Backups wird für jede Tabelle für den Verlauf des Sicherungsvorgangs eine Lesesperre gehalten (d. h. immer für eine Tabelle gleichzeitig). Wenn Sie mehrere Tabellen als Momentaufnahme sichern wollen (und dabei vermeiden wollen, dass diese während der Sicherung geändert werden), setzen Sie zunächst eine LOCK TABLES-Anweisung ab, um eine Lesesperre für alle betreffenden Tabellen zu erwirken.

BACKUP TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer backup
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

13.5.2.3. CHECK TABLE

CHECK TABLE tbl_name [, tbl_name] ... [option] ...

option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

CHECK TABLE prüft eine oder mehrere Tabellen auf Fehler. CHECK TABLE funktioniert bei MyISAM- und InnoDB-Tabellen. Bei MyISAM-Tabellen werden auch die Schlüsselstatistiken aktualisiert.

CHECK TABLE kann auch Views auf Probleme prüfen, z. B. in der View-Definition referenzierte Tabellen, die nicht mehr vorhanden sind.

CHECK TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer check
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

Beachten Sie, dass die Anweisung unter Umständen viele Datensätze für die überprüfte Tabelle ausgeben kann. Der letzte Datensatz hat den Msg_type-Wert status; Msg_text sollte normalerweise den Wert OK haben. Wenn Sie nicht den Wert OK oder aber die Meldung Table is already up to date erhalten, sollten Sie eine Reparatur der Tabelle durchführen. Siehe auch Abschnitt 5.10.4, „Benutzung von myisamchk für Tabellenwartung und Absturzreparatur“. Table is already up to date bedeutet, dass die Speicher-Engine für die Tabelle angegeben hat, dass es keine Notwendigkeit zur Überprüfung gibt.

Die verschiedenen Prüfoptionen, die angegeben werden können, sind in der folgenden Tabelle aufgeführt. Die Optionen dienen nur der Überprüfung von MyISAM-Tabellen; bei InnoDB-Tabellen und Views werden sie ignoriert.

TypBedeutung
QUICKüberprüft Datensätze nicht auf falsche Verknüpfungen.
FASTÜberprüft nur Tabellen, die nicht ordnungsgemäß geschlossen wurden.
CHANGEDüberprüft nur solche Tabellen, die seit der letzten Überprüfung geändert oder aber nicht korrekt geschlossen wurden.
MEDIUMprüft Datensätze, um sicherzustellen, dass gelöschte Verknüpfungen gültig sind. Hierbei wird auch eine Schlüsselprüfsumme für die Datensätze berechnet, die dann mit einer berechneten Prüfsumme für die Schlüssel verglichen wird.
EXTENDEDführt eine vollständige Schlüsselsuche für alle Schlüssel in jedem Datensatz durch. Hierdurch wird sichergestellt, dass die Tabelle hundertprozentig konsistent ist, der Vorgang dauert aber sehr lange.

Wenn keine der Optionen QUICK, MEDIUM oder EXTENDED angegeben wird, wird standardmäßig MEDIUM als Prüftyp für dynamische MyISAM-Tabellen verwendet. Dies hat dieselben Auswirkungen wie die Ausführung von myisamchk --medium-check tbl_name für die Tabelle. Auch bei statischen MyISAM-Tabellen ist MEDIUM der Standardtyp, sofern nicht CHANGED oder FAST angegeben wurde. (In diesen Fällen ist QUICK der Vorgabewert.) Der Datensatzscan wird bei CHANGED und FAST übersprungen, weil die Datensätze sehr selten beschädigt sind.

Sie können Prüfoptionen auch kombinieren. Im folgenden Beispiel etwa erfolgt eine schnelle Prüfung der Tabelle, um zu ermitteln, ob sie korrekt geschlossen wurde:

CHECK TABLE test_table FAST QUICK;

Hinweis: In manchen Fällen verändert CHECK TABLE die Tabelle. Dies geschieht, wenn die Tabelle als „beschädigt“ oder „nicht korrekt geschlossen“ gekennzeichnet wurde, aber CHECK TABLE keine Probleme in der Tabelle findet. In diesem Fall kennzeichnet CHECK TABLE die Tabelle als fehlerfrei.

Wenn eine Tabelle beschädigt ist, liegt das Problem wahrscheinlich bei den Indizes und nicht im Datenteil vor. Alle bislang genannten Prüftypen führen eine umfassende Indexprüfung durch und sollten aufgrund dessen die meisten Fehler finden.

Wenn Sie eine Tabelle, bei der Sie davon ausgehen, dass sie in Ordnung ist, nur sicherheitshalber überprüfen wollen, dann sollten Sie entweder keine Prüfoption oder die Option QUICK angeben. Letzteres sollten Sie tun, wenn Sie sehr in Eile sind und das sehr geringe Risiko in Kauf nehmen wollen, dass QUICK einen Fehler in der Datendatei nicht findet. (In den meisten Fällen sollte MySQL bei normaler Verwendung alle ggf. in der Datendatei vorhandenen Fehler finden. Geschieht dies, so wird die Tabelle als „beschädigt“ gekennzeichnet und kann erst wieder verwendet werden, nachdem sie repariert wurde.)

FAST und CHANGED sollen in erster Linie aus Skripten (die etwa mit cron ausgeführt werden) heraus verwendet werden, wenn Sie Ihre Tabellen von Zeit zu Zeit überprüfen wollen. In den meisten Fällen ist FAST CHANGED vorzuziehen. (Der einzige Fall, wo dies nicht zutrifft, liegt vor, wenn Sie annehmen, einen Bug im MyISAM-Code gefunden zu haben.)

EXTENDED sollte erst verwendet werden, wenn Sie bereits eine normale Überprüfung durchgeführt haben, aber immer noch merkwürdige Fehler zu einer Tabelle erhalten, sobald MySQL versucht, einen Datensatz zu aktualisieren oder einen Datensatz nach seinem Schlüssel zu finden. Die Wahrscheinlichkeit, dass so etwas nach einer normalen Überprüfung passiert, ist sehr gering.

Einige Probleme, die von CHECK TABLE gemeldet werden, können nicht automatisch behoben werden:

  • Found row where the auto_increment column has the value 0.

    Das bedeutet, dass Sie einen Datensatz in der Tabelle haben, bei dem die AUTO_INCREMENT-Indexspalte den Wert 0 enthält. (Ein Datensatz, bei dem die AUTO_INCREMENT-Spalte 0 ist, kann tatsächlich erzeugt werden, indem die Spalte mit UPDATE explizit auf 0 gesetzt wird.)

    Dies ist an sich kein Fehler, kann aber Probleme verursachen, wenn Sie beschließen, die Tabelle zu speichern und sie dann wiederherzustellen, oder eine ALTER TABLE-Anweisung an die Tabelle absetzen. In diesem Fall ändert die AUTO_INCREMENT-Spalte ihren Wert entsprechend den Regeln für AUTO_INCREMENT-Spalten, was Probleme wie beispielsweise Schlüsseldubletten verursachen kann.

    Um die Warnung zu beseitigen, führen Sie einfach eine UPDATE-Anweisung aus, um die Spalte auf einen anderen Wert als 0 zu setzen.

13.5.2.4. CHECKSUM TABLE

CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]

CHECKSUM TABLE meldet eine Tabellenprüfsumme.

Bei QUICK wird – sofern möglich – die mitlaufende Prüfsumme gemeldet, andernfalls NULL. Dies ist sehr schnell. Eine mitlaufende Prüfsumme wird durch Angabe der Tabellenoption CHECKSUM = 1 bei Erstellung der Tabelle aktiviert. Zurzeit wird dies nur bei MyISAM-Tabellen unterstützt. Siehe auch Abschnitt 13.1.5, „CREATE TABLE.

Bei EXTENDED wird die gesamte Tabelle Datensatz für Datensatz gelesen und die Prüfsumme berechnet. Dies kann bei großen Tabellen sehr lange dauern.

Wenn weder QUICK noch EXTENDED angegeben sind, gibt MySQL eine mitlaufende Prüfsumme zurück, wenn die Speicher-Engine der Tabelle dies unterstützt; andernfalls wird die Tabelle gescannt.

Bei einer nichtexistenten Tabelle gibt CHECKSUM TABLE NULL zurück und erzeugt eine Warnung.

13.5.2.5. OPTIMIZE TABLE

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

OPTIMIZE TABLE sollte verwendet werden, wenn Sie einen umfangreichen Teil einer Tabelle gelöscht oder viele Änderungen an einer Tabelle mit Datensätzen variabler Länge (also Tabellen mit VARCHAR-, VARBINARY-, BLOB- oder TEXT-Spalten) vorgenommen haben. Gelöschte Datensätze werden zu einer verknüpften Liste hinzugefügt. Nachfolgende INSERT-Operationen verwenden die alten Datensatzpositionen neu. Sie können mit OPTIMIZE TABLE nichtverwendeten Speicher in der Tabelle freigeben und die Datendatei defragmentieren.

In den meisten Konfigurationen müssen Sie OPTIMIZE TABLE gar nicht ausführen. Auch wenn Sie viele Änderungen an Datensätzen variabler Länge vorgenommen haben, ist die Wahrscheinlichkeit, dass Sie dies häufiger als einmal in der Woche oder im Monat tun müssen, sehr gering – und selbst dies nur bei bestimmten Tabellen.

OPTIMIZE TABLE funktioniert nur bei MyISAM-, BDB- und InnoDB-Tabellen.

Bei MyISAM-Tabellen funktioniert OPTIMIZE TABLE wie folgt:

  1. Wenn die Tabelle gelöschte oder geteilte Datensätze aufweist, wird die Tabelle repariert.

  2. Wenn die Indexseiten nicht sortiert sind, werden sie sortiert.

  3. Wenn die Tabellenstatistiken nicht aktuell sind (und eine Reparatur durch Sortierung des Indexes nicht erfolgreich war), werden sie aktualisiert.

Bei BDB wird OPTIMIZE TABLE zurzeit auf ANALYZE TABLE umgesetzt. Siehe auch Abschnitt 13.5.2.1, „ANALYZE TABLE.

Bei InnoDB wird OPTIMIZE TABLE auf ALTER TABLE umgesetzt, wodurch die Tabelle neu erstellt wird, um Indexstatistiken zu aktualisieren und ungenutzten Speicher im Cluster-Index freizugeben.

Sie können OPTIMIZE TABLE auch bei anderen Speicher-Engines zum Laufen bringen, indem Sie mysqld mit den Optionen --skip-new oder --safe-mode starten. In diesem Fall wird OPTIMIZE TABLE einfach auf ALTER TABLE umgesetzt.

OPTIMIZE TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer optimize
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

Beachten Sie, dass MySQL die Tabelle während der Laufzeit von OPTIMIZE TABLE sperrt.

OPTIMIZE TABLE-Anweisungen werden in das Binärlog geschrieben, sofern das optionale Schlüsselwort NO_WRITE_TO_BINLOG (oder sein Alias LOCAL) nicht verwendet wird. Dies wird gemacht, damit OPTIMIZE TABLE-Anweisungen, die auf einem MySQL Server verwendet werden, der als Replikationsmaster agiert, standardmäßig auf den Replikationsslave repliziert werden.

13.5.2.6. REPAIR TABLE

REPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLE
    tbl_name [, tbl_name] ... [QUICK] [EXTENDED] [USE_FRM]

REPAIR TABLE repariert eine unter Umständen beschädigte Tabelle. Standardmäßig hat dies dieselbe Wirkung wie myisamchk --recover tbl_name. REPAIR TABLE funktioniert bei MyISAM- und ARCHIVE-Tabellen. Siehe auch Abschnitt 14.1, „Die MyISAM-Speicher-Engine“, und Abschnitt 14.8, „Die ARCHIVE-Speicher-Engine“.

Im Normalfall werden Sie diese Anweisung niemals ausführen. Im Katastrophenfall kann REPAIR TABLE Ihnen aber sehr wahrscheinlich alle Daten aus einer MyISAM-Tabelle wiederherstellen. Treten bei Ihren Tabellen häufig Beschädigungen auf, dann sollten Sie versuchen, den Grund dafür zu ermitteln, um REPAIR TABLE nicht mehr fortlaufend einsetzen zu müssen. Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“, und Abschnitt 14.1.4, „MyISAM-Tabellenprobleme“.

Warnung: Wenn sich der Server während eines REPAIR TABLE-Vorgangs aufhängt, ist es unabdingbar, unmittelbar nach dem Neustart eine neue REPAIR TABLE-Anweisung für die Tabelle abzusetzen, bevor Sie weitere Operationen an ihr vornehmen. (Es bietet sich ohnehin immer an, zuallererst ein Backup zu erstellen.) Im schlimmsten Fall haben Sie unter Umständen eine neue saubere Indexdatei ohne Informationen zur Datendatei – und könnten im nächsten Schritt möglicherweise Ihre Datendatei überschreiben! Dies ist ein unwahrscheinliches, aber durchaus mögliches Szenario.

REPAIR TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer repair
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

Die Anweisung REPAIR TABLE kann unter Umständen viele Datensätze für die reparierte Tabelle ausgeben. Der letzte Datensatz hat den Msg_type-Wert status; Msg_test sollte normalerweise den Wert OK haben. Wenn Sie einen anderen Status als OK erhalten, sollten Sie die Tabelle mit myisamchk --safe-recover zu reparieren versuchen. (REPAIR TABLE implementiert noch nicht alle Optionen von myisamchk. Wir beabsichtigen aber, die Anweisung in Zukunft flexibler zu gestalten.) Mit myisamchk --safe-recover können Sie auch Optionen verwenden, die REPAIR TABLE nicht unterstützt (z. B. --max-record-length).

Wenn QUICK angegeben wird, versucht REPAIR TABLE, nur den Indexbaum zu reparieren. Dieser Reparaturtyp ähnelt dem von myisamchk --recover --quick.

Wenn Sie EXTENDED verwenden, erstellt MySQL den Index Datensatz für Datensatz, statt einen Index gleichzeitig beim Sortieren zu erzeugen. Dieser Reparaturtyp ähnelt dem von myisamchk --safe-recover.

Es gibt auch einen Modus USE_FRM für REPAIR TABLE. Diesen verwenden Sie, wenn die .MYI-Indexdatei fehlt oder ihr Header beschädigt ist. In diesem Modus erstellt MySQL die .MYI-Datei auf der Basis der Daten aus der .frm-Datei neu. Diese Art der Reparatur ist mit myisamchk nicht möglich. Hinweis: Verwenden Sie diesen Modus nur, wenn Sie die regulären REPAIR-Modi nicht einsetzen können. Der .MYI-Header enthält wichtige Tabellenmetadaten (insbesondere etwa den AUTO_INCREMENT-Wert und Delete link), die bei REPAIR ... USE_FRM verloren gehen. Verwenden Sie USE_FRM nicht für eine komprimierte Tabelle, weil diese Informationen auch in der .MYI-Datei gespeichert sind.

REPAIR TABLE-Anweisungen werden in das Binärlog geschrieben, sofern das optionale Schlüsselwort NO_WRITE_TO_BINLOG (oder sein Alias LOCAL) nicht verwendet wird. Dies wird gemacht, damit REPAIR TABLE-Anweisungen, die auf einem MySQL Server verwendet werden, der als Replikationsmaster agiert, standardmäßig auf den Replikationsslave repliziert werden.

13.5.2.7. RESTORE TABLE

RESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'

RESTORE TABLE stellt eine oder mehrere Tabellen aus einer Sicherung, die mit BACKUP TABLE erstellt wurde, wieder her. Vorhandene Tabellen werden nicht überschrieben: Wenn Sie versuchen, eine vorhandene Tabelle durch Wiederherstellen zu überschreiben, dann tritt ein Fehler auf. Wie BACKUP TABLE funktioniert auch RESTORE TABLE derzeit nur für MyISAM-Tabellen. Das Verzeichnis sollte als vollständiger Pfadname angegeben werden.

Das Backup einer Tabelle besteht aus ihrer .frm-Formatdatei und der .MYD-Datendatei. Beim Wiederherstellungsvorgang werden diese Dateien zunächst wiederhergestellt; darauf basierend wird dann die .MYI-Indexdatei erstellt. Die Wiederherstellung dauert länger als die Sicherung, weil die Indizes neu erstellt werden müssen. Je mehr Indizes die Tabelle hat, desto länger dauert der Vorgang.

RESTORE TABLE gibt eine Ergebnismenge mit den folgenden Spalten zurück:

SpalteWert
Tableder Tabellenname
Opist immer restore
Msg_typestatus, error, info oder warning
Msg_textdie Nachricht

13.5.3. SET

SET variable_assignment [, variable_assignment] ...

variable_assignment:
      user_var_name = expr
    | [GLOBAL | SESSION] system_var_name = expr
    | [@@global. | @@session. | @@]system_var_name = expr

Die Anweisung SET weist verschiedenen Arten von Variablen, die sich auf den Betrieb des Servers oder Ihres Clients auswirken, Werte zu.

Dieser Abschnitt beschreibt die Verwendung von SET zur Zuweisung von Werten an System- oder Benutzervariablen. Allgemeine Informationen zu diesen Variablentypen finden Sie in Abschnitt 5.2.2, „Server-Systemvariablen“, und Abschnitt 9.3, „Benutzerdefinierte Variablen“. Eine Liste der Systemvariablen, die dynamisch zur Laufzeit geändert werden können, finden Sie in Abschnitt 5.2.3.2, „Dynamische Systemvariablen“.

Hinweis: Ältere Versionen von MySQL verwendeten SET OPTION. Diese Funktionalität ist jedoch veraltet – mittlerweile wird SET nur noch ohne OPTION benutzt.

Es gibt auch Varianten der SET-Syntax, die in anderen Kontexten verwendet werden:

Die folgende Erläuterung zeigt die verschiedenen SET-Syntaxen, die zur Einstellung von Variablen benutzt werden können. In den Beispielen wird jeweils der Zuweisungsoperator = benutzt, der Operator := ist aber ebenfalls zulässig.

Eine Benutzervariable wird als @var_name geschrieben und kann wie folgt eingestellt werden:

SET @var_name = expr;

Systemvariablen werden in SET-Anweisungen als var_name referenziert. Unter Umständen kann ihnen auch ein Modifizierer vorangestellt sein:

  • Um explizit anzugeben, dass eine Variable eine globale Variable ist, stellen Sie dem Namen GLOBAL oder @@global. voran. Zum Einstellen globaler Variablen ist die Berechtigung SUPER erforderlich.

  • Um explizit anzugeben, dass eine Variable eine Sitzungsvariable ist, stellen Sie dem Namen SESSION oder @@session. voran.

  • LOCAL und @@local. sind Synonyme von SESSION bzw. @@session..

  • Ist kein Modifizierer vorhanden, dann stellt SET die Sitzungsvariable ein.

Ein paar Beispiele:

SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;

Die Syntax @@var_name für Systemvariablen wird unterstützt, damit die MySQL-Syntax mit einigen anderen Datenbanksystemen kompatibel ist.

Wenn Sie mehrere Systemvariablen in derselben Anweisung einstellen, wird die zuletzt angegebene GLOBAL- oder SESSION-Option für Variablen verwendet, deren Modus nicht näher spezifiziert ist.

Wenn Sie eine sitzungsspezifische Systemvariable einstellen, bleibt der Wert gültig, bis die aktuelle Sitzung endet oder Sie der Variablen einen anderen Wert zuweisen. Stellen Sie eine globale Systemvariable ein, dann wird der Wert gespeichert und bis zum nächsten Neustart des Servers für alle neuen Verbindungen verwendet. Wenn Sie den Wert einer globalen Systemvariablen permanent ändern wollen, sollten Sie diesen in eine Optionsdatei eintragen. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.

Um eine falsche Verwendung zu verhindern, erzeugt MySQL einen Fehler, wenn Sie SET GLOBAL für eine Variable verwenden, für die nur SET SESSION zulässig ist, oder GLOBAL (bzw. @@global.) beim Einstellen einer globalen Variablen nicht angeben.

Um eine SESSION-Variable auf den GLOBAL-Wert oder eine GLOBAL-Variable auf den in MySQL einkompilierten Standardwert zu setzen, verwenden Sie das Schlüsselwort DEFAULT. So sind beispielsweise die beiden folgenden Anweisungen dahingehend identisch, dass sie den Sitzungswert von max_join_size auf den globalen Wert setzen:

SET max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;

Es lassen sich nicht alle Systemvariablen auf DEFAULT setzen. In solchen Fällen tritt bei Verwendung von DEFAULT ein Fehler auf.

Eine Liste der Systemvariablen und ihrer Werte zeigen Sie mit der SHOW VARIABLES-Anweisung an. (Siehe auch Abschnitt 13.5.4.24, „SHOW VARIABLES.) Um einen bestimmten Variablennamen oder eine Liste der Namen zu erhalten, die einem Muster entsprechen, verwenden Sie eine LIKE-Klausel wie folgt:

SHOW VARIABLES LIKE 'max_join_size';
SHOW GLOBAL VARIABLES LIKE 'max_join_size';

Zum Anzeigen einer Variablenliste, deren Namen einem Muster entsprechen, verwenden Sie das Jokerzeichen ‘%’:

SHOW VARIABLES LIKE '%size%';
SHOW GLOBAL VARIABLES LIKE '%size%';

Jokerzeichen können an beliebiger Position im Vergleichsmuster stehen.

Sie können den Wert einer bestimmten Systemvariablen auch mit SELECT ermitteln, indem Sie die Syntax @@[global.|session.]var_name benutzen:

SELECT @@global.max_join_size, @@session.max_join_size;

Wenn Sie eine Variable mit SELECT @@var_name (ohne Modifizierer) abrufen, gibt MySQL den SESSION-Wert, sofern dieser vorhanden ist, und andernfalls den GLOBAL-Wert zurück. (Hier liegt ein Unterschied zu SET @@var_name = value vor, wo immer der Sitzungswert referenziert wird.)

Die folgende Liste beschreibt Variablen, die keine Standardsyntax aufweisen oder nicht in der in Abschnitt 5.2.2, „Server-Systemvariablen“, aufgeführten Liste der Systemvariablen beschrieben sind. Zwar werden die hier beschriebenen Variablen nicht von SHOW VARIABLES angezeigt, Sie können die Werte aber mit SELECT abrufen (Ausnahmen sind CHARACTER SET und SET NAMES). Zum Beispiel:

mysql> SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|            1 |
+--------------+

Die Groß-/Kleinschreibung dieser Optionen ist irrelevant.

  • AUTOCOMMIT = {0 | 1}

    Stellt den Autocommit-Modus ein. Mit der Einstellung 1 werden alle Änderungen direkt übernommen. Wenn Sie 0 wählen, müssen Sie eine Transaktion mit COMMIT übergeben oder sie mit ROLLBACK abbrechen. Standardmäßig starten Clientverbindungen mit dem AUTOCOMMIT-Wert 1. Wenn Sie AUTOCOMMIT von 0 auf 1 umstellen, führt MySQL automatisch eine COMMIT-Anweisung für alle offenen Transaktionen aus. Eine andere Möglichkeit, eine Transaktion zu starten, besteht in der Verwendung der Anweisungen START TRANSACTION oder BEGIN. Siehe auch Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK.

  • BIG_TABLES = {0 | 1}

    Beim Wert 1 werden alle Temporärtabellen auf der Festplatte statt im Arbeitsspeicher abgelegt. Dies ist ein wenig langsamer, aber der Fehler The table tbl_name is full tritt nicht bei SELECT-Operationen auf, die eine große Temporärtabelle erfordern. Der Standardwert bei einer neuen Verbindung ist 0 (d. h., es werden speicherresidente Temporärtabellen verwendet). Im Normalfall sollten Sie diese Variable niemals umstellen müssen, da speicherresidente Tabellen nach Bedarf automatisch in festplattenbasierte Tabellen konvertiert werden. (Hinweis: Diese Variable hieß früher SQL_BIG_TABLES.)

  • CHARACTER SET {charset_name | DEFAULT}

    Hiermit werden alle Strings vom und an den Client den Angaben entsprechend konvertiert. Sie können neue Zuordnungen angeben, indem Sie die Datei sql/convert.cc in der MySQL-Quelldistribution bearbeiten. SET CHARACTER SET stellt drei sitzungsspezifische Systemvariablen ein: character_set_client und character_set_results werden auf den angegebenen Zeichensatz gesetzt, character_set_connection auf den Wert von character_set_database. Siehe auch Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.

    Die Standardzuordnung kann mit dem Wert DEFAULT wiederhergestellt werden.

    Beachten Sie, dass die Syntax sich bei SET CHARACTER SET von der zur Einstellung der meisten anderen Optionen unterscheidet.

  • FOREIGN_KEY_CHECKS = {0 | 1}

    Bei der Einstellung 1 (Vorgabe) werden Fremdschlüssel-Constraints für InnoDB-Tabellen überprüft. Bei der Einstellung 0 werden sie ignoriert. Die Deaktivierung der Fremdschlüsselüberprüfung kann nützlich sein, um InnoDB-Tabellen in einer anderen als der Reihenfolge neu zu laden, die von den Parent/Child-Beziehungen erfordert wird. Siehe auch Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.

  • IDENTITY = value

    Diese Variable ist synonym zur Variablen LAST_INSERT_ID. Sie ist aus Gründen der Kompatibilität mit anderen Datenbanksystemen vorhanden. Sie können ihren Wert mit SELECT @@IDENTITY auslesen und mit SET IDENTITY einstellen.

  • INSERT_ID = value

    Stellt den von der folgenden INSERT- oder ALTER TABLE-Anweisung zu verwendenden Wert ein, wenn ein AUTO_INCREMENT-Wert eingefügt wird. Wird in erster Linie beim Binärlog benutzt.

  • LAST_INSERT_ID = value

    Stellt den von LAST_INSERT_ID() zurückzugebenden Wert ein. Dieser wird im Binärlog gespeichert, wenn Sie LAST_INSERT_ID() in einer Anweisung verwenden, die eine Tabelle aktualisiert. Durch Einstellen dieser Variablen wird der von der C-API-Funktion mysql_insert_id() zurückgegebene Wert nicht geändert.

  • NAMES {'charset_name' | DEFAULT}

    SET NAMES setzt die drei Systemvariablen character_set_client, character_set_connection und character_set_results auf den angegebenen Zeichensatz. Das Einstellen von character_set_connection auf charset_name setzt collation_connection auf die Standardsortierfolge für charset_name. Siehe auch Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.

    Die Standardzuordnung kann mit dem Wert DEFAULT wiederhergestellt werden.

    Beachten Sie, dass die Syntax sich bei SET NAMES von der zur Einstellung der meisten anderen Optionen unterscheidet.

  • ONE_SHOT

    Diese Option ist ein Modifizierer und keine Variable. Sie kann verwendet werden, um die Wirkung von Variablen zu beeinflussen, die den Zeichensatz, die Sortierfolge und die Zeitzone einstellen. ONE_SHOT wird in erster Linie zu Replikationszwecken eingesetzt. mysqlbinlog verwendet SET ONE_SHOT zur vorübergehenden Änderung der Werte von Zeichensatz-, Sortierfolgen- und Zeitzonenvariablen, um die ursprünglichen Werte für einen Rollforward zu speichern.

    Sie können ONE_SHOT nur mit den zulässigen Variablen verwenden, andernfalls erhalten Sie einen Fehler wie den folgenden:

    mysql> SET ONE_SHOT max_allowed_packet = 1;
    ERROR 1382 (HY000): The 'SET ONE_SHOT' syntax is reserved for purposes
    internal to the MySQL server
    

    Wenn ONE_SHOT mit zulässigen Variablen benutzt wird, ändert es die Variablen nach Bedarf – jedoch nur für die nächste Anweisung, die nicht SET ist. Nachfolgend setzt der Server alle zeichensatz-, sortierfolgen- und zeitzonenspezifischen Systemvariablen auf ihre vorherigen Werte. Beispiel:

    mysql> SET ONE_SHOT character_set_connection = latin5;
    
    mysql> SET ONE_SHOT collation_connection = latin5_turkish_ci;
    
    mysql> SHOW VARIABLES LIKE '%_connection';
    +--------------------------+-------------------+
    | Variable_name            | Value             |
    +--------------------------+-------------------+
    | character_set_connection | latin5            |
    | collation_connection     | latin5_turkish_ci |
    +--------------------------+-------------------+
    
    mysql> SHOW VARIABLES LIKE '%_connection';
    +--------------------------+-------------------+
    | Variable_name            | Value             |
    +--------------------------+-------------------+
    | character_set_connection | latin1            |
    | collation_connection     | latin1_swedish_ci |
    +--------------------------+-------------------+
    
  • SQL_AUTO_IS_NULL = {0 | 1}

    Bei der Einstellung 1 (Vorgabe) ermitteln Sie den zuletzt eingefügten Datensatz für eine Tabelle, die eine AUTO_INCREMENT-Spalte umfasst, mithilfe des folgenden Konstrukts:

    WHERE auto_increment_column IS NULL
    

    Dieses Verhalten wird von einigen ODBC-Programmen wie etwa Access verwendet.

  • SQL_BIG_SELECTS = {0 | 1}

    Bei der Einstellung 0 bricht MySQL SELECT-Anweisungen ab, deren Ausführung voraussichtlich sehr lange dauern wird (d. h., Anweisungen, bei denen der Optimierer eine Anzahl von untersuchten Datensätzen annimmt, deren Wert max_join_size überschreitet. Dies ist praktisch, wenn eine nicht empfehlenswerte WHERE-Anweisung abgesetzt wurde. Der Standardwert für eine neue Verbindung ist 1, d. h., alle SELECT-Anweisungen sind zulässig.

    Wenn Sie die Systemvariable max_join_size auf einen anderen Wert als DEFAULT setzen, wird SQL_BIG_SELECTS auf 0 gesetzt.

  • SQL_BUFFER_RESULT = {0 | 1}

    SQL_BUFFER_RESULT bewirkt, dass Ergebnisse aus SELECT-Anweisungen in Temporärtabellen abgelegt werden. Auf diese Weise kann MySQL die Tabellensperren schnell wieder aufheben. Die Option ist zudem in Fällen hilfreich, in denen die Übermittlung der Ergebnisse an den Client sehr lange dauert.

  • SQL_LOG_BIN = {0 | 1}

    Bei der Einstellung 0 erfolgt für den Client keine Aufzeichnung in das Binärlog. Der Client benötigt die Berechtigung SUPER, um diese Option einzustellen.

  • SQL_LOG_OFF = {0 | 1}

    Bei der Einstellung 1 erfolgt für den Client keine Aufzeichnung in das Log für allgemeine Abfragen. Der Client benötigt die Berechtigung SUPER, um diese Option einzustellen.

  • SQL_LOG_UPDATE = {0 | 1}

    Diese Variable ist veraltet und wird auf SQL_LOG_BIN umgesetzt.

  • SQL_NOTES = {0 | 1}

    Bei der Einstellung 1 (Standard) werden Warnungen auf Note-Ebene aufgezeichnet. Wird hingegen 0 gewählt, dann werden Note-Warnungen unterdrückt. mysqldump enthält eine Ausgabe, die diese Variable auf 0 setzt, sodass ein Neuladen der Dumpdatei keine Warnungen für Ereignisse erzeugt, die die Integrität des Neuladevorgangs nicht beeinträchtigen.

  • SQL_QUOTE_SHOW_CREATE = {0 | 1}

    Bei der Einstellung 1 setzt der Server Bezeichner für die Anweisungen SHOW CREATE TABLE und SHOW CREATE DATABASE in Anführungszeichen. Bei 0 werden keine Anführungszeichen gesetzt. Die Option ist standardmäßig aktiviert, damit die Replikation auch bei Bezeichnern funktioniert, die Anführungszeichen erfordern. Siehe auch Abschnitt 13.5.4.6, „SHOW CREATE TABLE, und Abschnitt 13.5.4.4, „SHOW CREATE DATABASE.

  • SQL_SAFE_UPDATES = {0 | 1}

    Bei der Einstellung 1 bricht MySQL UPDATE- und DELETE-Anweisungen ab, die keinen Schlüssel in der WHERE-Klausel oder einer LIMIT-Klausel verwenden. Auf diese Weise lassen sich UPDATE- oder DELETE-Anweisungen abfangen, bei denen Schlüssel nicht korrekt eingesetzt werden und die unter Umständen eine große Zahl von Datensätzen ändern oder löschen würden.

  • SQL_SELECT_LIMIT = {value | DEFAULT}

    Die maximale Anzahl von Datensätzen, die von SELECT-Anweisungen zurückgegeben werden können. Der Standardwert bei einer neuen Verbindung lautet „unbegrenzt“. Wenn Sie den Grenzwert geändert haben, kann der Standardwert mit dem Wert DEFAULT für SQL_SELECT_LIMIT wiederhergestellt werden.

    Wenn eine SELECT-Anweisung eine LIMIT-Klausel aufweist, hat diese LIMIT-Klausel Vorrang vor dem Wert von SQL_SELECT_LIMIT.

    SQL_SELECT_LIMIT gilt nicht für SELECT-Anweisungen, die in gespeicherten Routinen ausgeführt werden. Ebenso wenig gelten sie für SELECT-Anweisungen, die keine Ergebnismenge erzeugen, die an den Client zurückgegeben wird. Hierzu gehören SELECT-Anweisungen in Unterabfragen, CREATE TABLE ... SELECT und INSERT INTO ... SELECT.

  • SQL_WARNINGS = {0 | 1}

    Diese Variable steuert, ob INSERT-Anweisungen für einen Datensatz einen Informations-String erzeugen, wenn Warnungen auftreten. Die Standardeinstellung ist 0. Setzen Sie den Wert auf 1, um einen Informations-String zu generieren.

  • TIMESTAMP = {timestamp_value | DEFAULT}

    Stellt die Zeit für diesen Client ein. Auf deren Basis wird der ursprüngliche Zeitstempel ermittelt, wenn Sie Datensätze mit dem Binärlog wiederherstellen. timestamp_value sollte ein Unix-Epochenzeitstempel und kein MySQL-Zeitstempel sein.

  • UNIQUE_CHECKS = {0 | 1}

    Bei der Einstellung 1 (Standard) werden Eindeutigkeitsprüfungen für Sekundärindizes in InnoDB-Tabellen durchgeführt. Wenn der Wert 0 eingestellt wurde, werden keine Eindeutigkeitsprüfungen für Indexeinträge durchgeführt, die in den InnoDB-Einfügepuffer eingefügt wurden. Wenn Sie ganz sicher wissen, dass Ihre Daten keine Verstöße gegen das Eindeutigkeitsgebot enthalten, können Sie hier 0 wählen, um den Import großer Tabellen in InnoDB zu beschleunigen.

13.5.4. SHOW

Es gibt viele Formen von SHOW, die Informationen zu Datenbanken, Tabellen oder Spalten sowie Statusangaben zum Server vermitteln. In diesem Abschnitt werden die folgenden SHOW-Anweisungen beschrieben:

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW CREATE DATABASE db_name
SHOW CREATE FUNCTION funcname
SHOW CREATE PROCEDURE procname
SHOW CREATE TABLE tbl_name
SHOW DATABASES [LIKE 'pattern']
SHOW ENGINE engine_name {LOGS | STATUS }
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW FUNCTION STATUS [LIKE 'pattern']
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INNODB STATUS
SHOW PROCEDURE STATUS [LIKE 'pattern']
SHOW [BDB] LOGS
SHOW PLUGIN
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TRIGGERS
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW WARNINGS [LIMIT [offset,] row_count]

Es gibt zusätzliche Formen der SHOW-Anweisung, die Informationen zu Replikationsmaster- und -slave-Servern vermitteln (diese werden in Abschnitt 13.6, „SQL-Befehle in Bezug auf Replikation“, beschrieben):

SHOW BINLOG EVENTS
SHOW MASTER LOGS
SHOW MASTER STATUS
SHOW SLAVE HOSTS
SHOW SLAVE STATUS

Wenn die Syntax für eine gegebene SHOW-Anweisung einen LIKE 'pattern'-Teil enthält, ist 'pattern' ein String, der die SQL-Jokerzeichen ‘%’ und ‘_’ enthalten kann. Dieses Muster ist praktisch, um die Ausgabe der Anweisung auf passende Werte zu beschränken.

Mehrere SHOW-Anweisungen akzeptieren zudem eine WHERE-Klausel, die mehr Flexibilität bei der Angabe der anzuzeigenden Datensätze bietet. Siehe auch Abschnitt 22.22, „Erweiterungen der SHOW-Anweisungen“.

13.5.4.1. SHOW CHARACTER SET

SHOW CHARACTER SET [LIKE 'pattern']

Die Anweisung SHOW CHARACTER SET zeigt alle verfügbaren Zeichensätze an. Sie nimmt eine optionale LIKE-Klausel entgegen, die angibt, auf welche Zeichensatznamen zu prüfen ist. Zum Beispiel:

mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | cp1252 West European        | latin1_swedish_ci |      1 |
| latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
+---------+-----------------------------+-------------------+--------+

Die Spalte Maxlen zeigt die maximale Anzahl von Bytes an, die zur Speicherung eines Zeichens erforderlich sind.

13.5.4.2. SHOW COLLATION

SHOW COLLATION [LIKE 'pattern']

Die Ausgabe von SHOW COLLATION enthält alle verfügbaren Zeichensätze. Sie nimmt eine optionale LIKE-Klausel entgegen, bei der pattern angibt, auf welche Sortierfolgennamen zu prüfen ist. Zum Beispiel:

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          |       0 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
| latin1_danish_ci  | latin1  | 15 |         |          |       0 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       0 |
| latin1_general_ci | latin1  | 48 |         |          |       0 |
| latin1_general_cs | latin1  | 49 |         |          |       0 |
| latin1_spanish_ci | latin1  | 94 |         |          |       0 |
+-------------------+---------+----+---------+----------+---------+

Die Spalte Default gibt ab, ob eine Sortierfolge standardmäßig für den Zeichensatz verwendet wird. Compiled zeigt an, ob der Zeichensatz in den Server einkompiliert ist. Sortlen schließlich bezieht sich auf die Menge des Speichers, die zum Sortieren der im Zeichensatz ausgedrückten Strings erforderlich ist.

13.5.4.3. SHOW COLUMNS

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']

SHOW COLUMNS vermittelt Informationen zu Spalten in einer Tabelle. Die Anweisung funktioniert auch bei Views.

Das Schlüsselwort FULL bewirkt, dass die Ausgabe ihre Berechtigungen sowie alle spaltenspezifischen Kommentare für jede Spalte enthält.

Sie können db_name.tbl_name als Alternative zur Syntax tbl_name FROM db_name verwenden. Die beiden folgenden Anweisungen sind mithin äquivalent:

mysql> SHOW COLUMNS FROM mytable FROM mydb;
mysql> SHOW COLUMNS FROM mydb.mytable;

SHOW FIELDS ist ein Synonym für SHOW COLUMNS. Sie können die Spalten einer Tabelle auch mit dem Befehl mysqlshow db_name tbl_name auflisten.

Die Anweisung DESCRIBE ermittelt ähnliche Informationen wie SHOW COLUMNS. Siehe auch Abschnitt 13.3.1, „DESCRIBE (Informationen über Spalten abrufen)“.

13.5.4.4. SHOW CREATE DATABASE

SHOW CREATE {DATABASE | SCHEMA} db_name

Zeigt die CREATE DATABASE-Anweisung an, mit der die übergebene Datenbank erstellt wurde. SHOW CREATE SCHEMA ist ein Synonym zu SHOW CREATE DATABASE.

mysql> SHOW CREATE DATABASE test\G
*************************** 1. row ***************************
       Database: test
Create Database: CREATE DATABASE `test`
                 /*!40100 DEFAULT CHARACTER SET latin1 */

mysql> SHOW CREATE SCHEMA test\G
*************************** 1. row ***************************
       Database: test
Create Database: CREATE DATABASE `test`
                 /*!40100 DEFAULT CHARACTER SET latin1 */

SHOW CREATE DATABASE setzt Tabellen- und Spaltennamen entsprechend dem Wert von SQL_QUOTE_SHOW_CREATE in Anführungszeichen. Siehe auch Abschnitt 13.5.3, „SET.

13.5.4.5. SHOW CREATE PROCEDURE und SHOW CREATE FUNCTION

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

Diese Anweisung ist eine MySQL-Erweiterung. Analog zu SHOW CREATE TABLE gibt sie den exakten String zurück, mit dem die genannte Routine neu erstellt werden kann.

mysql> SHOW CREATE FUNCTION test.hello\G
*************************** 1. row ***************************
       Function: hello
       sql_mode:
Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hello, ',s,'!')

13.5.4.6. SHOW CREATE TABLE

SHOW CREATE TABLE tbl_name

Zeigt die CREATE TABLE-Anweisung an, mit der die übergebene Tabelle erstellt wurde. Diese Anweisung funktioniert auch bei Views.

mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE t (
  id INT(11) default NULL auto_increment,
  s char(60) default NULL,
  PRIMARY KEY (id)
) ENGINE=MyISAM

SHOW CREATE TABLE setzt Tabellen- und Spaltennamen entsprechend dem Wert von SQL_QUOTE_SHOW_CREATE in Anführungszeichen. Siehe auch Abschnitt 13.5.3, „SET.

13.5.4.7. SHOW DATABASES

SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']

SHOW DATABASES listet die Datenbanken auf dem MySQL Server-Host auf. Sofern Sie nicht über die Berechtigung SHOW DATABASES verfügen, werden Ihnen nur diejenigen Datenbanken angezeigt, für die Sie Berechtigungen haben. Sie können diese Liste auch mit mysqlshow anzeigen.

Wurde der Server mit der Option --skip-show-database gestartet, dann können Sie diese Anweisung ohne die Berechtigung SHOW DATABASES überhaupt nicht verwenden.

SHOW SCHEMAS kann ebenfalls verwendet werden.

13.5.4.8. SHOW ENGINE

SHOW ENGINE engine_name {LOGS | STATUS }

SHOW ENGINE zeigt Log- und Statusinformationen zu Speicher-Engines an. Die folgenden Anweisungen werden derzeit unterstützt:

SHOW ENGINE BDB LOGS
SHOW ENGINE INNODB STATUS

SHOW ENGINE BDB LOGS zeigt Statusinformationen zu vorhandenen BDB-Logdateien an. Zurückgegeben werden die folgenden Felder:

  • File

    Der vollständige Pfad zur Logdatei.

  • Type

    Der Logdateityp (BDB bei Berkeley DB-Logdateien).

  • Status

    Der Status der Logdatei (FREE, wenn die Datei entfernt werden kann, oder IN USE, wenn die Datei vom Transaktionssubsystem benötigt wird).

SHOW ENGINE INNODB STATUS zeigt umfassende Informationen zum Zustand der InnoDB-Speicher-Engine an.

Ältere (und mittlerweile nicht mehr verwendete) Synonyme für diese Anweisungen sind SHOW [BDB] LOGS und SHOW INNODB STATUS.

13.5.4.9. SHOW ENGINES

SHOW [STORAGE] ENGINES

SHOW ENGINES zeigt Statusinformationen zu den Speicher-Engines des Servers an. Dies ist besonders nützlich, um zu überprüfen, ob eine Speicher-Engine unterstützt wird, oder um festzustellen, welche Engine standardmäßig benutzt wird. SHOW TABLE TYPES ist ein veraltetes Synonym.

mysql> SHOW ENGINES\G
*************************** 1. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 2. row ***************************
      Engine: MyISAM
     Support: DEFAULT
     Comment: Default engine as of MySQL 3.23 with great performance
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: InnoDB
     Support: YES
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 4. row ***************************
      Engine: BerkeleyDB
     Support: YES
     Comment: Supports transactions and page-level locking
Transactions: YES
          XA: NO
  Savepoints: NO
*************************** 5. row ***************************
      Engine: EXAMPLE
     Support: YES
     Comment: Example storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: Archive storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: CSV
     Support: YES
     Comment: CSV storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 8. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: FEDERATED
     Support: YES
     Comment: Federated MySQL storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 10. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO

Der Wert Support gibt an, ob die betreffende Speicher-Engine unterstützt wird und welches die standardmäßig verwendete Engine ist. Wird der Server beispielsweise mit der Option --default-table-type=InnoDB gestartet, dann hat der Wert Support für den Datensatz InnoDB den Wert DEFAULT. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.

Die Spalten Transactions, XA und Savepoints wurden in MySQL 5.1.2 hinzugefügt. Sie geben jeweils an, ob die Speicher-Engine Transaktionen, XA-Transaktionen und/oder Speicherpunkte unterstützt.

13.5.4.10. SHOW ERRORS

SHOW ERRORS [LIMIT [offset,] row_count]
SHOW COUNT(*) ERRORS

Diese Anweisung ähnelt SHOW WARNINGS; der Unterschied besteht darin, dass statt Fehlern, Warnungen und Hinweisen lediglich Fehler angezeigt werden.

Die LIMIT-Klausel hat dieselbe Syntax wie bei der SELECT-Anweisung. Siehe auch Abschnitt 13.2.7, „SELECT.

Die SHOW COUNT(*) ERRORS-Anweisung zeigt die Anzahl der Fehler an. Sie können diese Anzahl auch der Variablen error_count entnehmen:

SHOW COUNT(*) ERRORS;
SELECT @@error_count;

Weitere Informationen finden Sie unter Abschnitt 13.5.4.25, „SHOW WARNINGS.

13.5.4.11. SHOW GRANTS

SHOW GRANTS FOR user

Diese Anweisung listet die GRANT-Anweisung(en) auf, die abgesetzt werden muss bzw. müssen, um die Berechtigungen zu kopieren, die einem MySQL-Benutzerkonto zugewiesen sind. Das Konto wird im selben Format wie bei der GRANT-Anweisung angegeben (z. B. 'jeffrey'@'localhost'). Die Benutzer- und Hostbestandteile des Kontonamens entsprechen den Werten der Spalten User und Host des kontenspezifischen Datensatzes in der Tabelle user.

mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+

Um die Berechtigungen des Kontos aufzulisten, über das Sie mit dem Server verbunden sind, können Sie eine der folgenden Anweisungen verwenden:

SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();

SHOW GRANTS zeigt nur die Berechtigungen an, die dem genannten Konto explizit zugewiesen sind. Das Konto kann also über weitere Berechtigungen verfügen, die nicht aufgelistet sind. Ist beispielsweise ein anonymes Konto vorhanden, dann kann das genannte Konto dessen Berechtigungen unter Umständen nutzen; dies wird aber von SHOW GRANTS nicht angezeigt.

13.5.4.12. SHOW INDEX

SHOW INDEX FROM tbl_name [FROM db_name]

SHOW INDEX gibt Informationen zum Tabellenindex zurück. Das Format erinnert an das des Aufrufs SQLStatistics in ODBC.

SHOW INDEX gibt die folgenden Felder zurück:

  • Table

    Der Name der Tabelle.

  • Non_unique

    0, wenn der Index keine Dubletten enthalten darf, andernfalls 1.

  • Key_name

    Der Name des Indexes.

  • Seq_in_index

    Die Sequenznummer der Spalte im Index, beginnend bei 1.

  • Column_name

    Der Spaltenname.

  • Collation

    Gibt an, wie die Spalte im Index sortiert ist. In MySQL können die Werte ‘A’ (aufsteigend) oder NULL (nicht sortiert) auftreten.

  • Cardinality

    Schätzung der Anzahl eindeutiger Werte im Index. Aktualisiert wird der Wert durch Ausführung von ANALYZE TABLE oder myisamchk -a. Cardinality wird basierend auf Statistiken gezählt, die als Integers gespeichert werden, d. h., der Wert ist auch bei kleinen Tabellen unter Umständen nicht exakt. Je höher die Kardinalität, desto größer ist die Chance, dass MySQL den Index bei der Durchführung von Joins verwendet.

  • Sub_part

    Die Anzahl der indizierten Zeichen, wenn die Spalte nur teilweise indiziert ist, oder NULL, wenn die gesamte Spalte indiziert ist.

  • Packed

    Gibt an, wie der Schlüssel gepackt ist. NULL zeigt an, dass der Schlüssel nicht gepackt ist.

  • Null

    Enthält YES, wenn die Spalte NULL sein kann. Andernfalls enthält die Spalte NO.

  • Index_type

    Der verwendete Indextyp (BTREE, FULLTEXT, HASH, RTREE).

  • Comment

    Verschiedene Anmerkungen.

Sie können db_name.tbl_name als Alternative zur Syntax tbl_name FROM db_name verwenden. Die folgenden beiden Anweisungen sind äquivalent:

SHOW INDEX FROM mytable FROM mydb;
SHOW INDEX FROM mydb.mytable;

SHOW KEYS ist ein Synonym für SHOW INDEX. Sie können die Indizes einer Tabelle auch mit dem Befehl mysqlshow -k db_name tbl_name auflisten.

13.5.4.13. SHOW INNODB STATUS

SHOW INNODB STATUS

In MySQL 5.1 ist dies ein veraltetes Synonym für SHOW ENGINE INNODB STATUS. Siehe auch Abschnitt 13.5.4.8, „SHOW ENGINE.

13.5.4.14. SHOW LOGS

SHOW [BDB] LOGS

In MySQL 5.1 ist dies ein veraltetes Synonym für SHOW ENGINE BDB LOGS. Siehe auch Abschnitt 13.5.4.8, „SHOW ENGINE.

13.5.4.15. SHOW OPEN TABLES

SHOW OPEN TABLES [FROM db_name] [LIKE 'pattern']

SHOW OPEN TABLES listet die nichttemporären Tabellen auf, die derzeit im Tabellen-Cache geöffnet sind. Siehe auch Abschnitt 7.4.8, „Nachteile der Erzeugung großer Mengen von Tabellen in derselben Datenbank“.

SHOW OPEN TABLES gibt die folgenden Felder zurück:

  • Database

    Die Datenbank, die die Tabelle enthält.

  • Table

    Der Tabellenname.

  • In_use

    Häufigkeit, mit der die Tabelle zurzeit von Abfragen verwendet wird. Wenn der Wert null ist, dann ist die Tabelle geöffnet, wird aber derzeit nicht verwendet.

  • Name_locked

    Gibt an, ob der Tabellenname gesperrt ist. Die Namenssperrung wird bei Operationen wie dem Löschen oder Umbenennen von Tabellen verwendet.

13.5.4.16. SHOW PLUGIN

SHOW PLUGIN

SHOW PLUGIN zeigt Informationen zu bekannten Plug-Ins an.

mysql> SHOW PLUGIN;
+------------+--------+----------------+---------+
| Name       | Status | Type           | Library |
+------------+--------+----------------+---------+
| MEMORY     | ACTIVE | STORAGE ENGINE | NULL    |
| MyISAM     | ACTIVE | STORAGE ENGINE | NULL    |
| InnoDB     | ACTIVE | STORAGE ENGINE | NULL    |
| ARCHIVE    | ACTIVE | STORAGE ENGINE | NULL    |
| CSV        | ACTIVE | STORAGE ENGINE | NULL    |
| BLACKHOLE  | ACTIVE | STORAGE ENGINE | NULL    |
| FEDERATED  | ACTIVE | STORAGE ENGINE | NULL    |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL    |
+------------+--------+----------------+---------+

SHOW PLUGIN wurde in MySQL 5.1.5 hinzugefügt.

13.5.4.17. SHOW PRIVILEGES

SHOW PRIVILEGES

SHOW PRIVILEGES zeigt eine Liste mit Systemberechtigungen an, die der MySQL Server unterstützt. Wie diese Liste genau aussieht, hängt von der Version Ihres Servers ab.

mysql> SHOW PRIVILEGES\G
*************************** 1. row ***************************
Privilege: Alter
Context: Tables
Comment: To alter the table
*************************** 2. row ***************************
Privilege: Alter routine
Context: Functions,Procedures
Comment: To alter or drop stored functions/procedures
*************************** 3. row ***************************
Privilege: Create
Context: Databases,Tables,Indexes
Comment: To create new databases and tables
*************************** 4. row ***************************
Privilege: Create routine
Context: Functions,Procedures
Comment: To use CREATE FUNCTION/PROCEDURE
*************************** 5. row ***************************
Privilege: Create temporary tables
Context: Databases
Comment: To use CREATE TEMPORARY TABLE
...

13.5.4.18. SHOW PROCEDURE STATUS und SHOW FUNCTION STATUS

SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']

Diese Anweisung ist eine MySQL-Erweiterung. Sie gibt Eigenschaften von Routinen zurück, z. B. Datenbank, Name, Typ und Ersteller sowie Erstellungs- und Änderungsdatum. Wird kein Muster angegeben, dann werden abhängig von der verwendeten Anweisung Informationen zu allen gespeicherten Prozeduren oder allen gespeicherten Funktionen aufgelistet.

mysql> SHOW FUNCTION STATUS LIKE 'hello'\G
*************************** 1. row ***************************
           Db: test
         Name: hello
         Type: FUNCTION
      Definer: testuser@localhost
     Modified: 2004-08-03 15:29:37
      Created: 2004-08-03 15:29:37
Security_type: DEFINER
      Comment:

Sie können Informationen zu gespeicherten Routinen auch der Tabelle ROUTINES in INFORMATION_SCHEMA entnehmen. Siehe auch Abschnitt 22.14, „Die Tabelle INFORMATION_SCHEMA ROUTINES.

13.5.4.19. SHOW PROCESSLIST

SHOW [FULL] PROCESSLIST

SHOW PROCESSLIST zeigt Ihnen, welche Threads gerade ausgeführt werden. Sie können diese Information auch mit mysqladmin processlist anzeigen. Wenn Sie die Berechtigung SUPER haben, werden alle Threads angezeigt. Andernfalls werden nur Ihre eigenen Threads (d. h. Threads, die mit dem MySQL-Benutzerkonto verknüpft sind, das Sie verwenden) angezeigt. Siehe auch Abschnitt 13.5.5.3, „KILL. Wenn Sie das Schlüsselwort FULL nicht angeben, werden nur die ersten hundert Zeichen jeder Anweisung im Feld Info angezeigt.

Diese Anweisung ist recht praktisch, wenn Sie die Fehlermeldung „Too many connections“ erhalten und herausfinden wollen, was gerade passiert. MySQL reserviert eine zusätzliche Verbindung für Konten, die die Berechtigung SUPER haben, damit gewährleistet ist, dass Administratoren jederzeit Verbindungen herstellen können, um das System zu überprüfen. (Dies setzt natürlich voraus, dass Sie diese Berechtigung nicht allen Benutzern gewähren.)

Die Ausgabe von SHOW PROCESSLIST kann etwa so aussehen:

mysql> SHOW FULL PROCESSLIST\G
*************************** 1. row ***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 1030455
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 2
User: system user
Host:
db: NULL
Command: Connect
Time: 1004
State: Has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
*************************** 3. row ***************************
Id: 3112
User: replikator
Host: artemis:2204
db: NULL
Command: Binlog Dump
Time: 2144
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
*************************** 4. row ***************************
Id: 3113
User: replikator
Host: iconnect2:45781
db: NULL
Command: Binlog Dump
Time: 2086
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
*************************** 5. row ***************************
Id: 3123
User: stefan
Host: localhost
db: apollon
Command: Query
Time: 0
State: NULL
Info: SHOW FULL PROCESSLIST
5 rows in set (0.00 sec)

Die Spalten haben die nachfolgend beschriebenen Bedeutungen:

  • Id

    Der Verbindungsbezeichner.

  • User

    Der MySQL-Benutzer, der die Anweisung abgesetzt hat. Die Anzeige system user bezeichnet einen clientlosen Thread, den der Server erzeugt hat, um Tasks intern zu verwalten. Es kann sich dabei um den I/O- oder den SQL-Thread, der auf dem Replikationsserver verwendet wird, oder einen Handler für verzögerte Datensätze handeln. Für den system user ist in der Spalte Host kein Host angegeben.

  • Host

    Der Hostname des Clients, der die Anweisung absetzt (außer bei system user, wo kein Host angegeben wird).

    SHOW PROCESSLIST meldet den Hostnamen für TCP/IP-Verbindungen im Format host_name:client_port, damit Sie schneller feststellen können, welcher Client was tut.

  • db

    Die Standarddatenbank, sofern eine solche ausgewählt wurde; andernfalls NULL.

  • Command

    Der Wert dieser Spalte entspricht den COM_xxx-Befehlen des Client/Server-Protokolls. Siehe auch Abschnitt 5.2.4, „Server-Statusvariablen“.

    Der Wert Command kann einen der folgenden Werte haben: Binlog Dump, Change user, Close stmt, Connect, Connect Out, Create DB, Debug, Delayed insert, Drop DB, Error, Execute, Fetch, Field List, Init DB, Kill, Long Data, Ping, Prepare, Processlist, Query, Quit, Refresh, Register Slave, Reset stmt, Set option, Shutdown, Sleep, Statistics, Table Dump, Time

  • Time

    Die Zeit (in Sekunden), die seit dem Start der Anweisung oder des Befehls bis jetzt vergangen ist.

  • State

    Eine Aktion, ein Ereignis oder ein Zustand. Folgende Werte sind möglich: After create, Analyzing, Changing master, Checking master version, Checking table, Connecting to master, Copying to group table, Copying to tmp table, Creating delayed handler, Creating index, Creating sort index, Creating table from master dump, Creating tmp table, Execution of init_command, FULLTEXT initialization, Finished reading one binlog; switching to next binlog, Flushing tables, Killed, Killing slave, Locked, Making temp file , Opening master dump table, Opening table, Opening tables, Processing request, Purging old relay logs, Queueing master event to the relay log, Reading event from the relay log, Reading from net, Reading master dump table data, Rebuilding the index on master dump table, Reconnecting after a failed binlog dump request, Reconnecting after a failed master event read, Registering slave on master, Removing duplicates, Reopen tables, Repair by sorting, Repair done, Repair with keycache, Requesting binlog dump, Rolling back, Saving state, Searching rows for update, Sending binlog event to slave, Sending data, Sorting for group, Sorting for order, Sorting index, Sorting result, System lock, Table lock, Thread initialized, Updating, User lock, Waiting for INSERT, Waiting for master to send event, Waiting for master update, Waiting for slave mutex on exit, Waiting for table, Waiting for tables, Waiting for the next event in relay log, Waiting on cond, Waiting to finalize termination, Waiting to reconnect after a failed binlog dump request, Waiting to reconnect after a failed master event read, Writing to net, allocating local table, cleaning up, closing tables, converting HEAP to MyISAM, copy to tmp table, creating table, deleting from main table, deleting from reference tables, discard_or_import_tablespace, end, freeing items, got handler lock, got old table, info, init, insert, logging slow query, login, preparing, purging old relay logs, query end, removing tmp table, rename, rename result table, reschedule, setup, starting slave, statistics, storing row into queue, update, updating, updating main table, updating reference tables, upgrading lock, waiting for delay_list, waiting for handler insert, waiting for handler lock, waiting for handler open

    Die gängigsten State-Werte werden im Folgenden beschrieben. Die Mehrzahl der anderen State-Werte sind in erster Linie praktisch, um Bugs im Server zu finden. Weitere Informationen zu Prozesszuständen bei Replikationsservern finden Sie in Abschnitt 6.4, „Replikation: Implementationsdetails“.

    Für die SHOW PROCESSLIST-Anweisung ist der State-Wert NULL.

  • Info

    Die Anweisung, die der Thread ausführt, oder NULL, sofern er keine Anweisung ausführt.

Einige State-Werte finden Sie in der Ausgabe von SHOW PROCESSLIST recht häufig:

  • Checking table

    Der Thread führt eine Tabellenprüfung durch.

  • Closing tables

    Der Thread synchronisiert die geänderten Tabellendaten auf die Festplatte und schließt die verwendeten Tabellen. Dies sollte ein sehr schneller Vorgang sein. Andernfalls sollten Sie überprüfen, ob Ihre Festplatte nicht voll ist oder stark frequentiert wird.

  • Connect Out

    Ein Replikationsslave stellt eine Verbindung zum Master her.

  • Copying to tmp table

    Der Server kopiert Daten in eine Temporärtabelle im Speicher.

  • Copying to tmp table on disk

    Der Server kopiert Daten in eine Temporärtabelle auf die Festplatte. Die temporäre Ergebnismenge war größer als tmp_table_size, und der Thread stellt die Temporärtabelle deswegen vom speicherresidenten in das festplattenbasierte Format um, um Speicher zu sparen.

  • Creating tmp table

    Der Thread erstellt eine Temporärtabelle, die einen Teil des Abfrageergebnisses aufnehmen soll.

  • deleting from main table

    Der Server führt den ersten Teil eines Löschvorgangs über mehrere Tabellen aus. Der Löschvorgang erfolgt nur in der ersten Tabelle und speichert Felder und Offsets, die zum Löschen aus anderen (Referenz-)Tabellen benutzt werden.

  • deleting from reference tables

    Der Server führt den zweiten Teil eines Löschvorgangs über mehrere Tabellen aus und löscht die entsprechenden Datensätze aus anderen Tabellen.

  • Flushing tables

    Der Thread führt FLUSH TABLES aus und wartet, bis alle Threads ihre Tabellen geschlossen haben.

  • FULLTEXT initialization

    Der Server bereitet die Ausführung einer natursprachlichen Volltextsuche vor.

  • Killed

    Jemand hat eine KILL-Anweisung an den Thread abgesetzt. Der Thread wird abgebrochen, wenn beim nächsten Mal das Terminierungs-Flag gesetzt wird. Dieses Flag wird in jeder größeren Schleife in MySQL gesetzt. Trotzdem kann es unter Umständen einen Moment dauern, bis der Thread terminiert ist. Ist der Thread durch einen anderen Thread gesperrt, dann erfolgt die Terminierung erst, wenn der andere Thread die Sperre aufgehoben hat.

  • Locked

    Die Abfrage wird durch eine andere Abfrage gesperrt.

  • Sending data

    Der Thread verarbeitet Datensätze für eine SELECT-Anweisung und sendet zudem Daten an den Client.

  • Sorting for group

    Der Thread führt eine Sortierung infolge einer GROUP BY-Klausel durch.

  • Sorting for order

    Der Thread führt eine Sortierung infolge einer ORDER BY-Klausel durch.

  • Opening tables

    Der Thread versucht, eine Tabelle zu öffnen. Dies sollte ein sehr schneller Vorgang sein, sofern das Öffnen nicht durch irgendeinen Umstand verhindert wird. So kann beispielsweise eine ALTER TABLE- oder eine LOCK TABLE-Anweisung das Öffnen einer Tabelle bis zum Abschluss der Anweisung unterbinden.

  • Reading from net

    Der Server liest ein Paket aus dem Netzwerk.

  • Removing duplicates

    Die Abfrage verwendete SELECT DISTINCT so, dass MySQL die DISTINCT-Operation nicht zu einem frühen Zeitpunkt wegoptimieren konnte. Aus diesem Grund erfordert MySQL eine zusätzliche Phase, um alle duplizierten Datensätze zu entfernen, bevor das Ergebnis an den Client gesendet wird.

  • Reopen table

    Der Thread hat eine Sperre für die Tabelle erwirkt, danach aber festgestellt, dass die zugrunde liegende Tabellenstruktur sich geändert hat. Der Thread hat die Sperre dann aufgehoben und die Tabelle geschlossen und versucht nun, sie wieder zu öffnen.

  • Repair by sorting

    Der Reparaturcode verwendet einen Sortiervorgang zur Erstellung der Indizes.

  • Repair with keycache

    Der Reparaturcode erstellt einen Schlüssel nach dem anderen über den Schlüssel-Cache. Dies ist wesentlich langsamer als Repair by sorting.

  • Searching rows for update

    Der Thread durchläuft die erste Phase zur Suche nach passenden Datensätzen, bevor er sie aktualisiert. Dies muss getan werden, wenn UPDATE den Index ändert, der für die Suche nach den betreffenden Datensätzen verwendet wird.

  • Sleeping

    Der Thread wartet darauf, dass der Client eine neue Anweisung an ihn sendet.

  • statistics

    Der Server berechnet Statistiken zur Entwicklung eines Abfrageausführungsplans.

  • System lock

    Der Thread wartet darauf, eine externe Systemsperre für die Tabelle zu erhalten. Wenn Sie nicht mehrere mysqld-Server verwenden, die auf die gleichen Tabellen zugreifen, können Sie Systemsperren mit der Option --skip-external-locking deaktivieren.

  • Upgrading lock

    Der Handler INSERT DELAYED versucht, eine Sperre für die Tabelle zu erwirken, um Datensätze einzufügen.

  • Updating

    Der Thread sucht nach zu aktualisierenden Datensätzen und aktualisiert diese dann.

  • updating main table

    Der Server führt den ersten Teil eines Änderungsvorgangs über mehrere Tabellen aus. Er führt Änderungen nur in der ersten Tabelle aus und speichert Felder und Offsets, die zur Aktualisierung anderer (Referenz-)Tabellen benutzt werden.

  • updating reference tables

    Der Server führt den zweiten Teil eines Änderungsvorgangs über mehrere Tabellen aus und aktualisiert die entsprechenden Datensätze in den anderen Tabellen.

  • User Lock

    Der Thread wartet auf ein GET_LOCK().

  • Waiting for tables

    Der Thread hat eine Mitteilung erhalten, dass die einer Tabelle zugrunde liegende Struktur sich geändert hat und er die Tabelle neu öffnen muss, um die neue Struktur zu erhalten. Um die Tabelle allerdings neu öffnen zu können, muss er warten, bis alle anderen Threads die fragliche Tabelle geschlossen haben.

    Diese Benachrichtigung erfolgt, wenn ein anderer Thread FLUSH TABLES oder eine der folgenden Anweisungen für die betreffende Tabelle verwendet hat: FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE oder OPTIMIZE TABLE.

  • waiting for handler insert

    Der INSERT DELAYED-Handler hat alle anhängigen Einfügeoperationen verarbeitet und wartet auf neue.

  • Writing to net

    Der Server schreibt ein Paket in das Netzwerk.

Die meisten Zustände entsprechen sehr schnellen Operationen. Wenn ein Thread für mehrere Sekunden in einem dieser Zustände verbleibt, dann weist dies auf ein Problem hin, das untersucht werden muss.

13.5.4.20. SHOW STATUS

SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']

SHOW STATUS zeigt Serverstatusinformationen an. Diese Informationen können auch mit dem Befehl mysqladmin extended-status ermittelt werden.

Nachfolgend ist auszugsweise eine Ausgabe aufgelistet. Die Liste der Variablen und ihrer Werte kann auf Ihrem Server anders aussehen. Die Bedeutung der Variablen ist in Abschnitt 5.2.4, „Server-Statusvariablen“, beschrieben.

mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_tables       | 8340       |
| Created_tmp_files        | 60         |
...
| Open_tables              | 1          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Opened_tables            | 44600      |
| Questions                | 2026873    |
...
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_created          | 30022      |
| Threads_connected        | 1          |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

Mit einer LIKE-Klausel zeigt die Anweisung nur die Variablen an, die dem Muster entsprechen:

mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| Key_blocks_used    | 14955    |
| Key_read_requests  | 96854827 |
| Key_reads          | 162040   |
| Key_write_requests | 7589728  |
| Key_writes         | 3813196  |
+--------------------+----------+

Wenn die Option GLOBAL angegeben wird, erhalten Sie die Statuswerte für alle Verbindungen zu MySQL. Bei SESSION erhalten Sie hingegen die Statuswerte der aktuellen Verbindung. Geben Sie überhaupt keine Option an, dann wird SESSION als Vorgabe verwendet. LOCAL ist ein Synonym für SESSION.

Einige Statusvariablen haben nur einen globalen Wert. Bei diesen erhalten Sie denselben Wert sowohl für GLOBAL als auch für SESSION.

13.5.4.21. SHOW TABLE STATUS

SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']

SHOW TABLE STATUS funktioniert wie SHOW TABLE, vermittelt aber zahlreiche Informationen zu den einzelnen Tabellen. Sie können diese Liste auch mit mysqlshow --status db_name anzeigen.

Diese Anweisung erlaubt auch die Anzeige von Informationen zu Views.

SHOW TABLE STATUS gibt die folgenden Felder zurück:

  • Name

    Den Namen der Tabelle.

  • Engine

    Die Speicher-Engine der Tabelle. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen. Vor MySQL 4.1.2 hieß dieser Wert Type.

  • Version

    Die Versionsnummer der .frm-Datei der Tabelle.

  • Row_format

    Das Format für die Datensatzspeicherung (Fixed, Dynamic, Compressed, Redundant, Compact). Das Format von InnoDB-Tabellen wird als Redundant oder Compact gemeldet.

  • Rows

    Anzahl der Datensätze. Einige Speicher-Engines wie etwa MyISAM speichern die exakte Anzahl.

    Bei anderen Engines wie InnoDB hingegen ist dies ein Schätzwert, der vom tatsächlichen Wert um bis zu 40 oder 50 Prozent abweichen kann. In solchen Fällen sollten Sie mit SELECT COUNT(*) eine exakte Anzahl ermitteln.

    Der Rows-Wert ist NULL bei Tabellen in der Datenbank INFORMATION_SCHEMA.

  • Avg_row_length

    Durchschnittliche Länge eines Datensatzes.

  • Data_length

    Die Länge der Datendatei.

  • Max_data_length

    Die maximale Länge der Datendatei. Dies ist die Gesamtzahl der Bytes, die in der Tabelle gespeichert werden können. Sie wird auf der Basis der verwendeten Zeigergröße berechnet.

  • Index_length

    Die Länge der Indexdatei.

  • Data_free

    Anzahl der reservierten, aber nicht verwendeten Bytes.

  • Auto_increment

    Der nächste AUTO_INCREMENT-Wert.

  • Create_time

    Zeitpunkt der Tabellenerstellung.

  • Update_time

    Zeitpunkt der letzten Aktualisierung der Datendatei.

  • Check_time

    Zeitpunkt der letzten Tabellenüberprüfung. Nicht alle Speicher-Engines aktualisieren diese Zeitangabe (in solchen Fällen ist der Wert stets NULL).

  • Collation

    Zeichensatz und Sortierung der Tabelle.

  • Checksum

    Wert der mitlaufenden Prüfsumme (sofern vorhanden).

  • Create_options

    Zusätzliche Optionen, die bei CREATE TABLE angegeben wurden.

  • Comment

    Bei der Erstellung der Tabelle angegebener Kommentar (oder Angaben dazu, warum MySQL nicht auf die Tabellendaten zugreifen konnte).

Im Tabellenkommentar meldet InnoDB den freien Speicher des Tablespaces, zu dem die Tabelle gehört. Bei einer Tabelle, die sich in einem gemeinsamen Tablespace befindet, ist dies der freie Speicher des gemeinsamen Tablespaces. Verwenden Sie mehrere Tablespaces und hat die Tabelle einen eigenen Tablespace, dann bezieht sich die Angabe des freien Speichers nur auf diese Tabelle.

Bei MEMORY-Tabellen geben die Werte Data_length, Max_data_length und Index_length näherungsweise die tatsächliche Menge des reservierten Speichers an. Der Reservierungsalgorithmus reserviert in großem Umfang Speicher, um die Anzahl der Reservierungsoperationen zu verringern.

Bei NDB Cluster-Tabellen zeigt die Ausgabe dieser Anweisung annähernde Werte für die Spalten Avg_row_length und Data_length. Ausgenommen sind lediglich BLOB-Spalten, die nicht berücksichtigt werden. Außerdem wird die Anzahl der Repliken in der Comment-Spalte (als number_of_replicas) angegeben.

Bei Views sind alle von SHOW TABLE STATUS angezeigten Felder NULL; lediglich Name zeigt den Namen des Views an, und Comment enthält view.

13.5.4.22. SHOW TABLES

SHOW [FULL] TABLES [FROM db_name] [LIKE 'pattern']

SHOW TABLES listet alle nichttemporären Tabellen in einer gegebenen Datenbank auf. Sie können diese Liste auch mit mysqlshow db_name anzeigen.

Die Anweisung listet außerdem alle Views in der Datenbank auf. Der Modifizierer FULL wird dahingehend unterstützt, dass SHOW FULL TABLES eine zweite Ausgabespalte anzeigt. Werte der zweiten Spalte sind BASE TABLE bei einer Tabelle und VIEW bei einem View.

Hinweis: Wenn Sie keine Berechtigungen für eine Tabelle haben, dann erscheint diese nicht in der Ausgabe von SHOW TABLES oder mysqlshow db_name.

13.5.4.23. SHOW TRIGGERS

SHOW TRIGGERS [FROM db_name] [LIKE expr]

SHOW TRIGGERS listet die derzeit auf dem MySQL Server definierten Trigger auf. Diese Anweisung erfordert die Berechtigung SUPER.

Für den Trigger ins_sum, wie er in Abschnitt 20.3, „Verwendung von Triggern“, definiert ist, sieht die Ausgabe der Anweisung wie folgt aus:

mysql> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1. row ***************************
  Trigger: ins_sum
    Event: INSERT
    Table: account
Statement: SET @sum = @sum + NEW.amount
   Timing: BEFORE
  Created: NULL
 sql_mode:
  Definer: myname@localhost

Hinweis: Wenn Sie eine LIKE-Klausel mit SHOW TRIGGERS verwenden, wird der zu prüfende Ausdruck expr mit dem Namen der Tabelle verglichen, für die der Trigger deklariert wurde, und nicht mit dem Namen des Triggers:

mysql> SHOW TRIGGERS LIKE 'ins%';
Empty set (0.01 sec)

Es folgt eine kurze Erläuterung der Spalten in der Ausgabe der Anweisung:

  • Trigger

    Der Name des Triggers.

  • Event

    Das Ereignis, welches die Trigger-Aktivierung ausgelöst hat: 'INSERT', 'UPDATE' oder 'DELETE'.

  • Table

    Die Tabelle, für die der Trigger definiert ist.

  • Statement

    Die bei Aktivierung des Triggers auszuführende Anweisung. Diese entspricht dem Text in der Spalte ACTION_STATEMENT von INFORMATION_SCHEMA.TRIGGERS.

  • Timing

    Einer der beiden Werte 'BEFORE' oder 'AFTER'.

  • Created

    Der Wert dieser Spalte ist zurzeit immer NULL.

  • sql_mode

    Der bei der Ausführung des Triggers gültige SQL-Modus.

  • Definer

    Das Konto, welches den Trigger erstellt hat.

Siehe auch Abschnitt 22.16, „Die Tabelle INFORMATION_SCHEMA TRIGGERS.

13.5.4.24. SHOW VARIABLES

SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']

SHOW VARIABLES zeigt den Wert einiger MySQL-Systemvariablen. Diese Informationen können auch mit dem Befehl mysqladmin variables ermittelt werden.

Mit der Option GLOBAL erhalten Sie die Werte, die für neue Verbindungen mit MySQL verwendet werden. Mit SESSION erhalten Sie hingegen die für die aktuelle Verbindung gültigen Werte. Geben Sie überhaupt keine Option an, dann wird SESSION als Vorgabe verwendet. LOCAL ist ein Synonym für SESSION.

Sind die Standardwerte ungeeignet, dann können Sie die meisten dieser Variablen beim Start von mysqld mit Befehlsoptionen oder zur Laufzeit mit der SET-Anweisung einstellen. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld, und Abschnitt 13.5.3, „SET.

Nachfolgend ist auszugsweise eine Ausgabe aufgelistet. Die Liste der Variablen und ihrer Werte kann auf Ihrem Server anders aussehen. Abschnitt 5.2.2, „Server-Systemvariablen“, beschreibt die Bedeutung der einzelnen Variablen. Informationen zu ihrer Optimierung finden Sie in Abschnitt 7.5.2, „Serverparameter feineinstellen“.

mysql> SHOW VARIABLES;
+---------------------------------+---------------------------+
| Variable_name                   | Value                     |
+---------------------------------+---------------------------+
| auto_increment_increment        | 1                         |
| auto_increment_offset           | 1                         |
| automatic_sp_privileges         | ON                        |
| back_log                        | 50                        |
| basedir                         | /home/jon/bin/mysql-5.1/  |
| binlog_cache_size               | 32768                     |
| bulk_insert_buffer_size         | 8388608                   |
| character_set_client            | latin1                    |
| character_set_connection        | latin1                    |
...
| max_user_connections            | 0                         |
| max_write_lock_count            | 4294967295                |
| multi_range_count               | 256                       |
| myisam_data_pointer_size        | 6                         |
| myisam_max_sort_file_size       | 2147483647                |
| myisam_recover_options          | OFF                       |
| myisam_repair_threads           | 1                         |
| myisam_sort_buffer_size         | 8388608                   |
| ndb_autoincrement_prefetch_sz   | 32                        |
| ndb_cache_check_time            | 0                         |
| ndb_force_send                  | ON                        |
...
| time_zone                       | SYSTEM                    |
| timed_mutexes                   | OFF                       |
| tmp_table_size                  | 33554432                  |
| tmpdir                          |                           |
| transaction_alloc_block_size    | 8192                      |
| transaction_prealloc_size       | 4096                      |
| tx_isolation                    | REPEATABLE-READ           |
| updatable_views_with_limit      | YES                       |
| version                         | 5.1.6-alpha-log           |
| version_comment                 | Source distribution       |
| version_compile_machine         | i686                      |
| version_compile_os              | suse-linux                |
| wait_timeout                    | 28800                     |
+---------------------------------+---------------------------+

Mit einer LIKE-Klausel zeigt die Anweisung nur die Variablen an, die dem Muster entsprechen:

mysql> SHOW VARIABLES LIKE 'have%';
+-----------------------+----------+
| Variable_name         | Value    |
+-----------------------+----------+
| have_archive          | YES      |
| have_bdb              | NO       |
| have_blackhole_engine | YES      |
| have_compress         | YES      |
| have_crypt            | YES      |
| have_csv              | YES      |
| have_example_engine   | NO       |
| have_federated_engine | NO       |
| have_geometry         | YES      |
| have_innodb           | YES      |
| have_isam             | NO       |
| have_ndbcluster       | DISABLED |
| have_openssl          | NO       |
| have_partitioning     | YES      |
| have_query_cache      | YES      |
| have_raid             | NO       |
| have_rtree_keys       | YES      |
| have_symlink          | YES      |
+-----------------------+----------+

13.5.4.25. SHOW WARNINGS

SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW COUNT(*) WARNINGS

SHOW WARNINGS zeigt die Fehler-, Warnungs- und Hinweismeldungen, die durch die zuletzt abgesetzte Anweisung ausgegeben wurden. Hat diese Anweisung keine Meldungen erzeugt, so ist die Ausgabe leer. Die verwandte Anweisung SHOW ERRORS zeigt nur die Fehler an. Siehe auch Abschnitt 13.5.4.10, „SHOW ERRORS.

Die Liste der Meldungen wird bei jeder neuen Anweisung, die eine Tabelle verwendet, zurückgesetzt.

Die SHOW COUNT(*) WARNINGS-Anweisung zeigt die Gesamtanzahl der Fehler, Warnungen und Hinweise an. Sie können diese Anzahl auch der Variablen warning_count entnehmen:

SHOW COUNT(*) WARNINGS;
SELECT @@warning_count;

Der Wert von warning_count kann größer sein als die Anzahl der von SHOW WARNINGS angezeigten Meldungen. Dies liegt dann daran, dass die Systemvariable max_error_count so niedrig angesetzt ist, dass nicht alle Meldungen gespeichert werden. Ein weiter unten in diesem Anschnitt gezeigtes Beispiel veranschaulicht, wie dies geschehen kann.

Die LIMIT-Klausel hat dieselbe Syntax wie bei der SELECT-Anweisung. Siehe auch Abschnitt 13.2.7, „SELECT.

Der MySQL Server sendet die Gesamtanzahl der Fehler, Warnungen und Hinweise zurück, die aufgrund der letzten Anweisung erzeugt wurden. Wenn Sie die C-API verwenden, lässt sich dieser Wert durch einen Aufruf von mysql_warning_count() ermitteln. Siehe auch Abschnitt 24.2.3.69, „mysql_warning_count().

Warnungen werden für Anweisungen wie LOAD DATA INFILE und DML-Anweisungen wie INSERT, UPDATE, CREATE TABLE und ALTER TABLE erzeugt.

Die folgende DROP TABLE-Anweisung erzeugt einen Hinweis:

mysql> DROP TABLE IF EXISTS no_such_table;
mysql> SHOW WARNINGS;
+-------+------+-------------------------------+
| Level | Code | Message                       |
+-------+------+-------------------------------+
| Note  | 1051 | Unknown table 'no_such_table' |
+-------+------+-------------------------------+

Es folgt ein einfaches Beispiel, das eine Syntaxwarnung für CREATE TABLE und Konvertierungswarnungen für INSERT enthält:

mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1287
Message: 'TYPE=storage_engine' is deprecated, use
         'ENGINE=storage_engine' instead
1 row in set (0.00 sec)

mysql> INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'),
    -> (300,'Open Source');
Query OK, 3 rows affected, 4 warnings (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 4

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1265
Message: Data truncated for column 'b' at row 1
*************************** 2. row ***************************
  Level: Warning
   Code: 1263
Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2
*************************** 3. row ***************************
  Level: Warning
   Code: 1264
Message: Data truncated, out of range for column 'a' at row 3
*************************** 4. row ***************************
  Level: Warning
   Code: 1265
Message: Data truncated for column 'b' at row 3
4 rows in set (0.00 sec)

Die maximale Anzahl zu speichernder Fehler-, Warn- und Hinweismeldungen wird von der Systemvariablen max_error_count gesteuert. Der Standardwert ist 64. Um die Anzahl der Meldungen, die Sie speichern wollen, zu ändern, modifizieren Sie den Wert von max_error_count. Im folgenden Beispiel erzeugt die ALTER TABLE-Anweisung drei Warnmeldungen, von denen aber nur eine gespeichert wird, weil max_error_count zuvor auf 1 gesetzt worden war:

mysql> SHOW VARIABLES LIKE 'max_error_count';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_error_count | 64    |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> SET max_error_count=1;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t1 MODIFY b CHAR;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 3

mysql> SELECT @@warning_count;
+-----------------+
| @@warning_count |
+-----------------+
|               3 |
+-----------------+
1 row in set (0.01 sec)

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

Um Warnungen zu deaktivieren, setzen Sie max_error_count auf 0. In diesem Fall zeigt warning_count zwar noch an, wie viele Warnungen aufgetreten sind, aber keine dieser Meldungen wird gespeichert.

Sie können die Sitzungsvariable SQL_NOTES auf 0 setzen, damit Warnungen auf der Note-Ebene nicht aufgezeichnet werden.

13.5.5. Weitere Verwaltungsanweisungen

13.5.5.1. CACHE INDEX

CACHE INDEX
  tbl_index_list [, tbl_index_list] ...
  IN key_cache_name

tbl_index_list:
  tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]

Die Anweisung CACHE INDEX weist Tabellenindizes einem bestimmten Schlüssel-Cache zu. Sie wird nur bei MyISAM-Tabellen eingesetzt.

Die folgende Anweisung weist Indizes der Tabellen t1, t2 und t3 dem Schlüssel-Cache namens hot_cache zu:

mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+

Die Syntax von CACHE INDEX gestattet Ihnen, anzugeben, dass nur bestimmte Indizes aus einer Tabelle dem Cache zuzuweisen sind. Die aktuelle Implementierung weist alle Indizes der Tabelle dem Cache zu, weswegen es keinen Grund gibt, einen anderen Parameter als den Tabellennamen zu übergeben.

Der in der CACHE INDEX-Anweisung referenzierte Schlüssel-Cache kann erstellt werden, indem seine Größe mit einer Anweisung zur Parametereinstellung oder in den Parametereinstellungen des Servers angegeben wird. Zum Beispiel:

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

Parameter eines Schlüssel-Caches lassen sich als Mitglieder einer strukturierten Systemvariablen einstellen. Siehe auch Abschnitt 5.2.3.1, „Strukturierte Systemvariablen“.

Ein Schlüssel-Cache muss bereits vorhanden sein, bevor Sie ihm Indizes zuweisen:

mysql> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'

Standardmäßig werden Tabellenindizes dem (vorgabeseitigen) Hauptschlüssel-Cache zugewiesen, der beim Serverstart erstellt wird. Wird ein Schlüssel-Cache zerstört, dann werden alle ihm zugewiesenen Indizes wieder dem Standardschlüssel-Cache zugewiesen.

Die Indexzuweisung wirkt sich global auf den Server aus: Wenn ein Client einem gegebenen Cache einen Index zuweist, wird der Cache für alle Abfragen verwendet, die diesen Index einbeziehen – unabhängig davon, welcher Client die Abfragen absetzt.

13.5.5.2. FLUSH

FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ...

Die FLUSH-Anweisung leert verschiedene interne Caches, die von MySQL verwendet werden, bzw. lädt diese neu. Für die Ausführung von FLUSH benötigen Sie die Berechtigung RELOAD.

Die Anweisung RESET ähnelt FLUSH. Siehe auch Abschnitt 13.5.5.5, „RESET.

flush_option kann die folgenden Werte annehmen:

  • HOSTS

    Leert die Cache-Tabellen auf dem Host. Sie sollten die Hosttabellen leeren, wenn einer Ihrer Hosts die IP-Nummer wechselt oder Sie die Fehlermeldung Host 'host_name' is blocked erhalten. Wenn aufeinander folgend mehr als max_connect_errors Fehler für einen gegebenen Host auftreten, während dieser eine Verbindung mit dem MySQL Server herstellt, dann geht MySQL davon aus, dass etwas nicht stimmt, und sperrt weitere Verbindungsanfragen dieses Hosts. Das Synchronisieren der Hosttabellen gestattet dem Host einen neuen Versuch der Verbindungsherstellung. Siehe auch Abschnitt A.2.5, „Host '...' is blocked-Fehler“. Sie können mysqld mit --max_connect_errors=999999999 starten, um diese Fehlermeldung zu verhindern.

  • DES_KEY_FILE

    Lädt die DES-Schlüssel aus der mit der Option --des-key-file beim Serverstart angegebenen Datei neu.

  • LOGS

    Schließt alle Logdateien und öffnet sie neu. Wenn das binäre Loggen aktiviert ist, wird die Sequenznummer der Binärlogdatei relativ zur vorherigen Datei um den Wert 1 erhöht. Unter Unix ist dies das Gleiche wie das Senden eines SIGHUP-Signals an den mysqld-Server. (Ausnahme sind einige Versionen von Mac OS X 10.3, wo mysqld SIGHUP und SIGQUIT ignoriert.)

    Wenn der Server mit der Option --log-error gestartet wurde, bewirkt FLUSH LOGS, dass das Fehlerlog mit dem Suffix -old umbenannt wird und mysqld eine neue leere Logdatei erstellt. Wenn die Option --log-error nicht angegeben wird, erfolgt keine Umbenennung.

  • PRIVILEGES

    Lädt die Berechtigungen aus der Gesamtstruktur in der mysql-Datenbank neu.

  • QUERY CACHE

    Defragmentiert den Abfrage-Cache, um seinen Speicher besser zu nutzen. FLUSH QUERY CACHE entfernt anders als RESET QUERY CACHE keine Abfragen aus dem Cache.

  • STATUS

    Setzt die meisten Statusvariablen auf null. Dies ist etwas, das Sie nur beim Debuggen einer Abfrage tun sollten. Siehe auch Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.

  • {TABLE | TABLES} [tbl_name [, tbl_name] ...]

    Wenn keine Tabellen benannt sind, werden alle Tabellen geschlossen. Das Schließen aller gerade verwendeten Tabellen wird ebenfalls erzwungen. Ferner wird der Schlüssel-Cache synchronisiert. Werden ein oder mehrere Tabellennamen angegeben, dann werden nur die angegebenen Tabellen synchronisiert. FLUSH TABLES entfernt ebenso wie RESET QUERY CACHE zudem alle Abfrageergebnisse aus dem Abfrage-Cache.

  • TABLES WITH READ LOCK

    Schließt alle offenen Tabellen und versieht alle Tabellen für alle Datenbanken mit einer Lesesperre, bis Sie UNLOCK TABLES ausführen. Dies ist eine recht praktische Möglichkeit der Datensicherung, wenn Sie ein Dateisystem wie Veritas einsetzen, das rechtzeitig Schnappschüsse erstellt.

  • USER_RESOURCES

    Setzt alle Benutzerbeschränkungen auf Stundenbasis auf null. Hierdurch können Clients, bei denen der Grenzwert für Verbindungen, Abfragen oder Änderungen pro Stunde erreicht wurde, ihre Aktivitäten direkt wiederaufnehmen. FLUSH USER_RESOURCES wirkt sich allerdings nicht auf die Begrenzung gleichzeitiger Verbindungen aus. Siehe auch Abschnitt 13.5.1.3, „GRANT und REVOKE.

FLUSH-Anweisungen werden in das Binärlog geschrieben, sofern das optionale Schlüsselwort NO_WRITE_TO_BINLOG (oder sein Alias LOCAL) nicht verwendet wird. Dies wird gemacht, damit FLUSH-Anweisungen, die auf einem MySQL Server verwendet werden, der als Replikationsmaster agiert, standardmäßig auf den Replikationsslave repliziert werden.

Hinweis: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE und FLUSH TABLES WITH READ LOCK werden keinesfalls geloggt, weil dies bei der Replikation auf einen Slave Probleme verursachen würde.

Sie können auf einige dieser Anweisungen auch mit dem Hilfsprogramm mysqladmin zugreifen, indem Sie die Befehle flush-hosts, flush-logs, flush-privileges, flush-status oder flush-tables verwenden.

Hinweis: Es ist in MySQL 5.1 nicht möglich, FLUSH-Anweisungen in gespeicherten Funktionen oder Triggern abzusetzen. Allerdings können Sie FLUSH in gespeicherten Prozeduren benutzen, solange diese nicht aus gespeicherten Funktionen heraus oder von Triggern aufgerufen werden. Siehe auch Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“.

Informationen dazu, wie die RESET-Anweisung bei der Replikation verwendet wird, finden Sie in Abschnitt 13.5.5.5, „RESET.

13.5.5.3. KILL

KILL [CONNECTION | QUERY] thread_id

Jede Verbindung mit mysqld wird in einem separaten Thread ausgeführt. Mit der Anweisung SHOW PROCESSLIST können Sie die gerade ausgeführten Threads auflisten. Die Terminierung eines Threads ist mit der Anweisung KILL thread_id möglich.

KILL unterstützt die optionalen Modifizierer CONNECTION oder QUERY:

  • KILL CONNECTION entspricht KILL ohne Modifizierer: Es terminiert die Verbindung zur angegebenen Kennung thread_id.

  • KILL QUERY terminiert die über die Verbindung aktuell ausgeführte Anweisung, lässt die Verbindung selbst aber bestehen.

Wenn Sie die Berechtigung PROCESS haben, werden alle Threads angezeigt. Wenn Sie die Berechtigung SUPER haben, können Sie alle Threads und Anweisungen terminieren. Andernfalls werden nur Ihre eigenen Threads und Anweisungen angezeigt und zur Terminierung freigegeben.

Zur Überprüfung und Terminierung von Threads können Sie auch die Befehle mysqladmin processlist und mysqladmin kill verwenden.

Hinweis: Sie können KILL nicht mit der Embedded MySQL Server-Bibliothek verwenden, da der eingebettete Server nur in den Threads der Hostanwendung ausgeführt wird – er selbst erstellt also keine Verbindungs-Threads.

Wenn Sie KILL verwenden, wird ein Thread-spezifisches Terminierungs-Flag für den Thread gesetzt. In den meisten Fällen kann es etwas dauern, bis die Terminierung des Threads abgeschlossen ist, weil das Flag nur in bestimmten Abständen überprüft wird:

  • Bei SELECT-, ORDER BY- und GROUP BY-Schleifen wird das Flag nach dem Lesen eines Datensatzblocks überprüft. Ist das Terminierungs-Flag gesetzt, dann wird die Anweisung abgebrochen.

  • Bei ALTER TABLE wird das Terminierungs-Flag vor jedem Lesen eines Datensatzblocks aus der Ursprungstabelle geprüft. Wurde das Flag gesetzt, dann wird die Anweisung abgebrochen und die Temporärtabelle gelöscht.

  • Bei UPDATE- oder DELETE-Operationen wird das Flag nach jedem gelesenen Block und nach jedem geänderten oder gelöschten Datensatz überprüft. Ist das Terminierungs-Flag gesetzt, dann wird die Anweisung abgebrochen. Beachten Sie, dass, wenn Sie keine Transaktionen verwenden, bereits erfolgte Änderungen nicht rückgängig gemacht werden.

  • GET_LOCK() führt einen Abbruch aus und gibt NULL zurück.

  • Ein INSERT DELAYED-Thread synchronisiert schnell alle Datensätze in seinem Speicher (d. h., er schreibt sie) und wird dann terminiert.

  • Wenn der Thread sich im Tabellensperr-Handler befindet (Zustand Locked), dann wird die Tabellensperre umgehend aufgehoben.

  • Wartet der Thread bei einem Schreibaufruf auf freien Festplattenspeicher, dann wird die Schreiboperation mit der Fehlermeldung „Disk Full“ abgebrochen.

  • Warnung: Die Terminierung einer REPAIR TABLE- oder OPTIMIZE TABLE-Operation führt bei einer MyISAM-Tabelle zu Beschädigungen, die die Tabelle unbrauchbar machen. Lese- oder Schreiboperationen in eine solche Tabelle schlagen fehl, bis Sie sie – ohne Unterbrechung – wieder optimieren oder reparieren.

13.5.5.4. LOAD INDEX INTO CACHE

LOAD INDEX INTO CACHE
  tbl_index_list [, tbl_index_list] ...

tbl_index_list:
  tbl_name
    [[INDEX|KEY] (index_name[, index_name] ...)]
    [IGNORE LEAVES]

Die Anweisung LOAD INDEX INTO CACHE lädt einen Tabellenindex vorab in den Schlüssel-Cache, dem er durch eine explizite CACHE INDEX-Anweisung zugewiesen wurde, oder aber in den vorgabeseitigen Schlüssel-Cache. LOAD INDEX INTO CACHE wird nur bei MyISAM-Tabellen verwendet.

Der Modifizierer IGNORE LEAVES bewirkt, dass nur Blöcke für Indexknoten, die nicht Endknoten (Blätter) sind, geladen werden.

Die folgende Anweisung lädt Knoten (Indexblöcke) mit Indizes der Tabellen t1 und t2:

mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table   | Op           | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status   | OK       |
| test.t2 | preload_keys | status   | OK       |
+---------+--------------+----------+----------+

Die Anweisung lädt alle Indexblöcke aus t1. Bei t2 werden nur Blöcke für Nichtendknoten geladen.

Die Syntax von LOAD INDEX INTO CACHE gestattet Ihnen, anzugeben, dass nur bestimmte Indizes aus einer Tabelle geladen werden sollen. Die aktuelle Implementierung lädt alle Indizes der Tabelle in den Cache, weswegen es keinen Grund gibt, einen anderen Parameter als den Tabellennamen zu übergeben.

13.5.5.5. RESET

RESET reset_option [, reset_option] ...

Die RESET-Anweisung wird benutzt, um den Status verschiedener Serveroperationen zu löschen. Sie benötigen die Berechtigung RELOAD, um RESET ausführen zu können.

RESET agiert als stärkere Version der FLUSH-Anweisung. Siehe auch Abschnitt 13.5.5.2, „FLUSH.

reset_option kann die folgenden Werte annehmen:

  • MASTER

    Löscht alle in der Indexdatei aufgeführten Binärlogs, leert den Binärlogindex und setzt ihn zurück und erstellt eine neue Binärlogdatei. (Ist als FLUSH MASTER in MySQL-Versionen vor 3.23.26 bekannt.) Siehe auch Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“.

  • QUERY CACHE

    Entfernt alle Abfrageergebnisse aus dem Abfrage-Cache.

  • SLAVE

    Löscht auf dem Slave die Angabe zur Replikationsposition in den Binärlogs des Masters (d. h., der Slave „vergisst“ die Position). Setzt außerdem das Relay-Log zurück, indem alle vorhandenen Relay-Logdateien gelöscht werden und eine neue Logdatei begonnen wird. (Ist als FLUSH SLAVE in MySQL-Versionen vor 3.23.26 bekannt.) Siehe auch Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“.

13.6. SQL-Befehle in Bezug auf Replikation

Dieser Abschnitt beschreibt SQL-Anweisungen, die im Zusammenhang mit der Replikation von Bedeutung sind. Eine Gruppe von Anweisungen wird zur Steuerung der Master-Server verwendet, die andere zur Steuerung der Slave-Server.

13.6.1. SQL-Anweisungen für die Steuerung von Master-Servern

Die Replikation kann über die SQL-Schnittstelle gesteuert werden. Dieser Bereich beschreibt die Anweisungen zur Verwaltung der Replikationsmaster-Server. Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“, beschreibt Anweisungen zur Verwaltung der Slave-Server.

13.6.1.1. PURGE MASTER LOGS

PURGE {MASTER | BINARY} LOGS TO 'log_name'
PURGE {MASTER | BINARY} LOGS BEFORE 'date'

Löscht alle Binärlogs, die im Logindex vor dem angegebenen Log oder Datum aufgelistet sind. Die Logs werden auch von der Liste entfernt, die in der Logindexdatei aufgezeichnet ist, d. h., das übergebene Log wird zum ersten Log auf der Liste.

Beispiel:

PURGE MASTER LOGS TO 'mysql-bin.010';
PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';

Das Argument date der Variante BEFORE kann im Format 'YYYY-MM-DD hh:mm:ss' angegeben werden. MASTER und BINARY sind Synonyme.

Diese Anweisung kann auch bei laufender Slave-Replikation sicher ausgeführt werden. Sie müssen die Replikation also nicht anhalten. Wenn ein aktiver Slave gerade eines der Logs ausliest, das Sie löschen wollen, dann hat die Anweisung keine Auswirkungen, sondern schlägt mit einem Fehler fehl. Wenn allerdings ein Slave schläft und Sie eines der Logs löschen, die dieser Slave noch lesen muss, dann wird er nach dem Erwachen nicht mehr zur Replikation in der Lage sein.

Um Logs sicher zu löschen, gehen Sie wie folgt vor:

  1. Sie setzen auf allen Slave-Servern SHOW SLAVE STATUS ab, um zu prüfen, welches Log gerade gelesen wird.

  2. Sie zeigen mit SHOW MASTER LOGS eine Liste der Logdateien auf dem Master-Server an.

  3. Ermitteln Sie das zeitlich früheste Log unter allen Slaves. Dies ist das Ziellog. Wenn alle Slaves aktuell sind, muss es das letzte Log auf der Liste sein.

  4. Erstellen Sie eine Kopie aller Logs, die Sie zu löschen beabsichtigen. (Dieser Schritt ist optional, aber stets empfehlenswert.)

  5. Löschen Sie alle Logs bis zum Ziellog (aber nicht das Ziellog selbst).

13.6.1.2. RESET MASTER

RESET MASTER

Löscht alle in der Indexdatei aufgeführten Binärlogs, leert den Binärlogindex und setzt ihn zurück und erstellt eine neue Binärlogdatei.

13.6.1.3. SET SQL_LOG_BIN

SET SQL_LOG_BIN = {0|1}

Aktiviert oder deaktiviert das binäre Loggen für die aktuelle Verbindung (SQL_LOG_BIN ist eine Sitzungsvariable), sofern der Client die Berechtigung SUPER hat. Die Anweisung wird mit einem Fehler abgewiesen, wenn der Client die Berechtigung nicht hat.

13.6.1.4. SHOW BINLOG EVENTS

SHOW BINLOG EVENTS
   [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]

Zeigt die Ereignisse im Binärlog an. Wenn Sie 'log_name' nicht angeben, wird das erste Binärlog angezeigt.

Die LIMIT-Klausel hat dieselbe Syntax wie bei der SELECT-Anweisung. Siehe auch Abschnitt 13.2.7, „SELECT.

Hinweis: Das Absetzen einer SHOW BINLOG EVENTS-Anweisung ohne LIMIT-Klausel kann einen sehr zeit- und ressourcenaufwändigen Prozess starten, weil der Server den vollständigen Inhalt des Binärlogs an den Client zurückgibt (dieses Log enthält alle datenändernden Anweisungen, die vom Server ausgeführt wurden). Als Alternative zu SHOW BINLOG EVENTS können Sie das Hilfsprogramm mysqlbinlog verwenden. Sie können damit das Binärlog in eine Textdatei speichern und später untersuchen. Siehe auch Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.

13.6.1.5. SHOW MASTER LOGS

SHOW MASTER LOGS
SHOW BINARY LOGS

Listet die Binärlogdateien auf dem Server auf. Diese Anweisung wird im Zuge eines Vorgangs benutzt, der in Abschnitt 13.6.1.1, „PURGE MASTER LOGS, beschrieben ist. Dort wird gezeigt, wie man ermittelt, welche Logdateien gelöscht werden können.

mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name      | File_size |
+---------------+-----------+
| binlog.000015 |    724935 |
| binlog.000016 |    733481 |
+---------------+-----------+

SHOW BINARY LOGS ist äquivalent mit SHOW MASTER LOGS.

13.6.1.6. SHOW MASTER STATUS

SHOW MASTER STATUS

Vermittelt Statusinformationen zu den Binärlogdateien des Masters. Beispiel:

mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73       | test         | manual,mysql     |
+---------------+----------+--------------+------------------+

13.6.1.7. SHOW SLAVE HOSTS

SHOW SLAVE HOSTS

Zeigt eine Liste der Replikationsslaves an, die derzeit beim Master registriert wird. Slaves, die nicht mit der Option --report-host=slave_name gestartet wurden, werden in der Liste nicht angezeigt.

13.6.2. SQL-Anweisungen für die Steuerung von Slave-Servern

Die Replikation kann über die SQL-Schnittstelle gesteuert werden. Dieser Abschnitt beschreibt die Anweisungen zur Verwaltung der Replikationsslave-Server. Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“, beschreibt Anweisungen zur Verwaltung der Master-Server.

13.6.2.1. CHANGE MASTER TO

CHANGE MASTER TO master_def [, master_def] ...

master_def:
    MASTER_HOST = 'host_name'
  | MASTER_USER = 'user_name'
  | MASTER_PASSWORD = 'password'
  | MASTER_PORT = port_num
  | MASTER_CONNECT_RETRY = count
  | MASTER_LOG_FILE = 'master_log_name'
  | MASTER_LOG_POS = master_log_pos
  | RELAY_LOG_FILE = 'relay_log_name'
  | RELAY_LOG_POS = relay_log_pos
  | MASTER_SSL = {0|1}
  | MASTER_SSL_CA = 'ca_file_name'
  | MASTER_SSL_CAPATH = 'ca_directory_name'
  | MASTER_SSL_CERT = 'cert_file_name'
  | MASTER_SSL_KEY = 'key_file_name'
  | MASTER_SSL_CIPHER = 'cipher_list'

CHANGE MASTER TO ändert die Parameter, die der Slave-Server zur Verbindungsherstellung und Kommunikation mit dem Master-Server verwendet. Die Anweisung aktualisiert auch den Inhalt der Dateien master.info und relay-log.info.

MASTER_USER, MASTER_PASSWORD, MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEY und MASTER_SSL_CIPHER vermitteln dem Slave Informationen dazu, wie er Verbindungen mit dem Master herstellen kann.

Die SSL-Optionen (MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEY und MASTER_SSL_CIPHER) können auch auf Slaves geändert werden, die ohne SSL-Unterstützung kompiliert wurden. Sie werden in der Datei master.info gespeichert, aber ignoriert, bis Sie einen Server verwenden, auf dem die SSL-Unterstützung aktiviert ist.

Wenn Sie einen der Parameter nicht angeben, dann behält er in der Regel seinen alten Wert (Ausnahmen entnehmen Sie der nachfolgenden Erläuterung). Wenn sich beispielsweise das Passwort, mit dem die Verbindung zu Ihrem MySQL-Master hergestellt wird, geändert hat, müssen Sie nur die folgenden Anweisungen absetzen, um dem Slave das neue Passwort mitzuteilen:

STOP SLAVE; -- if replication was running
CHANGE MASTER TO MASTER_PASSWORD='new3cret';
START SLAVE; -- if you want to restart replication

Es ist nicht notwendig, Parameter anzugeben, die sich nicht ändern (Host, Port, Benutzer usw.).

MASTER_HOST und MASTER_PORT sind der Hostname (oder die IP-Adresse) des Master-Hosts bzw. sein TCP/IP-Port. Beachten Sie, dass, wenn MASTER_HOST gleich localhost ist, die Portnummer – wie unter MySQL bei anderen Gelegenheiten auch – unter Umständen ignoriert werden kann (dies ist etwa der Fall, wenn Unix-Socketdateien benutzt werden).

Geben Sie MASTER_HOST oder MASTER_PORT an, dann setzt der Slave voraus, dass der Master-Server sich vom vorherigen unterscheidet (und zwar auch dann, wenn Sie einen Host- oder Portwert angeben, der mit dem aktuellen Wert identisch ist). In diesem Fall werden die alten Namens- und Positionswerte der Binärlogdatei auf dem Master-Server als nun ungültig betrachtet, d. h., wenn Sie MASTER_LOG_FILE und MASTER_LOG_POS in der Anweisung nicht angeben, werden stillschweigend MASTER_LOG_FILE='' und MASTER_LOG_POS=4 angehängt.

MASTER_LOG_FILE und MASTER_LOG_POS sind die Koordinaten, bei denen der Slave-I/O-Thread mit dem Lesen vom Master beginnen soll, wenn der Thread beim nächsten Mal startet. Wenn Sie einen dieser Werte angeben, dürfen Sie RELAY_LOG_FILE oder RELAY_LOG_POS nicht angeben. Wenn weder MASTER_LOG_FILE noch MASTER_LOG_POS angegeben werden, verwendet der Slave die letzten Koordinaten des Slave-SQL-Threads, bevor CHANGE MASTER abgesetzt wurde. Hierdurch ist gewährleistet, dass es bei der Replikation auch dann nicht zu Unstetigkeiten kommt, wenn der Slave-SQL-Thread sehr spät mit dem Slave-I/O-Thread verglichen wurde – etwa dann, wenn Sie beispielsweise nur das zu verwendende Passwort ändern wollen.

CHANGE MASTER löscht alle Relay-Logdateien und beginnt eine neue Relay-Logdatei, sofern Sie nicht RELAY_LOG_FILE oder RELAY_LOG_POS angeben. In diesem Fall werden die Relay-Logs behalten, und die globale Variable relay_log_purge wird stillschweigend auf 0 gesetzt.

CHANGE MASTER ist praktisch, wenn es darum geht, einen Slave zu konfigurieren, und Sie hierfür die Momentaufnahme des Masters benötigen und Logdatei und Offset entsprechend aufgezeichnet haben. Nachdem Sie die Momentaufnahme in den Slave geladen haben, können Sie CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master', MASTER_LOG_POS=log_offset_on_master auf dem Slave ausführen.

Das folgende Beispiel ändert die Koordinaten des Masters und dessen Binärlogdatei. Dies tut man, wenn man den Slave so konfiguriert, dass er den Master repliziert:

CHANGE MASTER TO
  MASTER_HOST='master2.mycompany.com',
  MASTER_USER='replication',
  MASTER_PASSWORD='bigs3cret',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='master2-bin.001',
  MASTER_LOG_POS=4,
  MASTER_CONNECT_RETRY=10;

Das nächste Beispiel zeigt eine Operation, die weniger häufig benötigt wird. Sie wird verwendet, wenn auf dem Slave Relay-Logs vorhanden sind, die Sie aus irgendeinem Grund erneut ausführen wollen. Zu diesem Zweck muss der Master nicht erreichbar sein. Sie müssen lediglich CHANGE MASTER TO benutzen und den SQL-Thread mit START SLAVE SQL_THREAD starten:

CHANGE MASTER TO
  RELAY_LOG_FILE='slave-relay-bin.006',
  RELAY_LOG_POS=4025;

Sie können die zweite Operation sogar in einer Nicht-Replikations-Konfiguration mit einem eigenständigen Nicht-Slave-Server benutzen, um nach einem Absturz eine Wiederherstellung durchzuführen. Angenommen, Ihr Server ist abgestürzt, und Sie haben eine Sicherung wiederhergestellt. Nun wollen Sie die eigenen Binärlogs des Servers – nicht die Relay-Logs, sondern die regulären Binärlogs – namens (beispielsweise) myhost-bin.* wieder auf den Server aufspielen. Zunächst erstellen Sie ein Backup dieser Binärlogs an einer sicheren Position für den Fall, dass Sie der nachfolgenden Anleitung nicht exakt folgen und der Server deswegen die Binärlogs unbeabsichtigt löscht. Verwenden Sie SET GLOBAL relay_log_purge=0, um die Sicherheit zu erhöhen. Danach starten Sie den Server ohne die Option --log-bin. Stattdessen geben Sie die Optionen --replicate-same-server-id, --relay-log=myhost-bin (damit der Server glaubt, dass es sich bei diesen regulären Logs um Relay-Logs handelt) und --skip-slave-start an. Nach dem Serverstart setzen Sie die folgenden Anweisungen ab:

CHANGE MASTER TO
  RELAY_LOG_FILE='myhost-bin.153',
  RELAY_LOG_POS=410,
  MASTER_HOST='some_dummy_string';
START SLAVE SQL_THREAD;

Der Server liest nun seine eigenen Binärlogs und führt diese aus. Auf diese Weise erfolgt eine Wiederherstellung der Daten. Nach deren Abschluss führen Sie STOP SLAVE aus, fahren den Server herunter, löschen die Dateien master.info und relay-log.info und starten den Server mit den ursprünglichen Optionen neu.

Die Angabe der Option MASTER_HOST (auch mit einem Pseudowert) ist erforderlich, damit der Server annimmt, er sei ein Slave.

13.6.2.2. LOAD DATA FROM MASTER

LOAD DATA FROM MASTER

Diese Anweisung erstellt eine Momentaufnahme des Masters und kopiert diese auf den Slave. Sie aktualisiert die Werte von MASTER_LOG_FILE und MASTER_LOG_POS, sodass der Slave die Replikation an der korrekten Position startet. Ausschlussregeln für Tabellen und Datenbanken, die mit den Optionen --replicate-*-do-* und --replicate-*-ignore-* angegeben werden, werden beachtet. --replicate-rewrite-db wird hingegen nicht berücksichtigt, weil ein Benutzer mit dieser Option eine nichteindeutige Zuordnung wie --replicate-rewrite-db="db1->db3" oder --replicate-rewrite-db="db2->db3" vornehmen könnte, was den Slave beim Laden der Tabellen vom Master verwirren würde.

Die Verwendung dieser Anweisung hängt von den folgenden Bedingungen ab:

  • Sie funktioniert nur bei MyISAM-Tabellen. Der Versuch, eine Tabelle anderen Typs zu laden, führt zu folgendem Fehler:

    ERROR 1189 (08S01): Net error reading from master
    
  • Sie erwirkt während der Aufzeichnung der Momentaufnahme eine globale Lesesperre auf dem Master, wodurch während des Ladevorgangs Updates auf dem Master unterbunden werden.

Wenn Sie große Tabellen laden, müssen Sie die Werte von net_read_timeout und net_write_timeout unter Umständen sowohl auf dem Master- als auch auf den Slave-Servern erhöhen. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“.

Beachten Sie, dass LOAD DATA FROM MASTER keine Tabellen aus der mysql-Datenbank kopiert. Dies erleichtert die Einrichtung verschiedener Benutzer und Berechtigungen auf dem Master und dem Slave.

Um LOAD DATA FROM MASTER verwenden zu können, benötigt das Replikationskonto, welches zur Verbindung mit dem Master-Server verwendet wird, die Berechtigungen RELOAD und SUPER auf dem Master und die Berechtigung SELECT für alle Master-Tabellen, die Sie laden wollen. Alle Master-Tabellen, für die der Benutzer die Berechtigung SELECT nicht hat, werden von LOAD DATA FROM MASTER ignoriert. Dies liegt daran, dass der Master sie vor dem Benutzer verbirgt: LOAD DATA FROM MASTER ruft SHOW DATABASES auf, um die zu ladenden Master-Datenbanken in Erfahrung zu bringen; SHOW DATABASES aber gibt nur Datenbanken zurück, für die der Benutzer Berechtigungen hat. Siehe auch Abschnitt 13.5.4.7, „SHOW DATABASES. Auf der Slave-Seite benötigt der Benutzer, der LOAD DATA FROM MASTER absetzt, Berechtigungen zum Löschen und Erstellen der Datenbanken und Tabellen, die kopiert werden.

13.6.2.3. LOAD TABLE tbl_name FROM MASTER

LOAD TABLE tbl_name FROM MASTER

Überträgt eine Kopie der Tabelle vom Master auf den Slave. Diese Anweisung wurde in erster Linie zum Debuggen von LOAD DATA FROM MASTER-Operationen implementiert. Um LOAD TABLE verwenden zu können, benötigt das Konto, welches zur Verbindung mit dem Master-Server verwendet wird, die Berechtigungen RELOAD und SUPER auf dem Master und die Berechtigung SELECT für die zu ladende Master-Tabelle. Auf der Slave-Seite benötigt der Benutzer, der LOAD TABLE FROM MASTER absetzt, Berechtigungen zum Löschen und Erstellen der Tabelle.

Die Bedingungen für LOAD DATA FROM MASTER gelten auch hier. So funktioniert LOAD TABLE FROM MASTER beispielsweise nur bei MyISAM-Tabellen. Auch die Hinweise zu Zeitüberschreitungen für LOAD DATA FROM MASTER sind anzuwenden.

13.6.2.4. MASTER_POS_WAIT()

SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)

Dies ist eigentlich eine Funktion und keine Anweisung. Mit ihr kann gewährleistet werden, dass der Slave Ereignisse bis zu einer gegebenen Position im Binärlog des Masters gelesen und ausgeführt hat. Eine vollständige Beschreibung finden Sie in Abschnitt 12.10.4, „Verschiedene Funktionen“.

13.6.2.5. RESET SLAVE

RESET SLAVE

RESET SLAVE löscht auf dem Slave die Angabe zur Replikationsposition in den Binärlogs des Masters (d. h., der Slave „vergisst“ die Position). Diese Anweisung ist zur Verwendung für einen sauberen Start vorgesehen: Sie löscht die Dateien master.info und relay-log.info und alle Relay-Logs und beginnt ein neues Relay-Log.

Hinweis: Alle Relay-Logs werden gelöscht – auch dann, wenn sie nicht vollständig vom Slave-SQL-Thread ausgeführt wurden. (Dieser Umstand ist wahrscheinlich auf einem Replikationsslave gegeben, wenn Sie eine STOP SLAVE-Anweisung abgesetzt haben oder der Slave stark belastet ist.)

Verbindungsdaten, die in der Datei master.info gespeichert sind, werden direkt unter Berücksichtigung von Werten zurückgesetzt, die ggf. mit den entsprechenden Startoptionen angegeben werden. Zu diesen Daten gehören Werte wie Master-Host, Master-Port, Master-Benutzer und Master-Passwort. Wenn der Slave-SQL-Thread gerade mit der Replikation von Temporärtabellen beschäftigt war, als er angehalten wurde, und RESET SLAVE abgesetzt wird, dann werden diese replizierten Temporärtabellen auf dem Slave gelöscht.

13.6.2.6. SET GLOBAL SQL_SLAVE_SKIP_COUNTER

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = N

Diese Anweisung überspringt die nächsten N Ereignisse auf dem Master. Dies ist nützlich, wenn Replikationen wiederhergestellt werden sollen, die durch eine Anweisung angehalten wurden.

Die Anweisung ist nur gültig, wenn der Slave-Thread nicht ausgeführt wird. Andernfalls erzeugt er einen Fehler.

13.6.2.7. SHOW SLAVE STATUS

SHOW SLAVE STATUS

Diese Anweisung vermittelt Statusinformationen zu wesentlichen Parametern der Slave-Threads. Wenn Sie diese Anweisung mit dem mysql-Client absetzen, können Sie \G statt des Semikolons als Abschlusszeichen für die Anweisung verwenden, um eine vertikale Ausgabe zu erhalten, die besser zu lesen ist:

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
       Slave_IO_State: Waiting for master to send event
          Master_Host: localhost
          Master_User: root
          Master_Port: 3306
        Connect_Retry: 3
      Master_Log_File: gbichot-bin.005
  Read_Master_Log_Pos: 79
       Relay_Log_File: gbichot-relay-bin.005
        Relay_Log_Pos: 548
Relay_Master_Log_File: gbichot-bin.005
     Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
      Replicate_Do_DB:
  Replicate_Ignore_DB:
           Last_Errno: 0
           Last_Error:
         Skip_Counter: 0
  Exec_Master_Log_Pos: 79
      Relay_Log_Space: 552
      Until_Condition: None
       Until_Log_File:
        Until_Log_Pos: 0
   Master_SSL_Allowed: No
   Master_SSL_CA_File:
   Master_SSL_CA_Path:
      Master_SSL_Cert:
    Master_SSL_Cipher:
       Master_SSL_Key:
Seconds_Behind_Master: 8

SHOW SLAVE STATUS gibt die folgenden Felder zurück:

  • Slave_IO_State

    Eine Kopie des State-Felds in der Ausgabe von SHOW PROCESSLIST für den Slave-I/O-Thread. Sie zeigt an, was der Thread gerade tut: Verbindungsherstellung zum Master, Warten auf vom Master kommende Ereignisse, Wiederverbindung mit dem Master usw. Mögliche Zustände sind in Abschnitt 6.4, „Replikation: Implementationsdetails“, beschrieben. Bei älteren MySQL-Versionen ist eine Überprüfung dieses Felds notwendig, denn diese erlaubten eine fortlaufende Ausführung des Threads auch für den Fall, dass eine Verbindungsherstellung mit dem Master nicht möglich war. Wird er ausgeführt, so liegt kein Problem vor; andernfalls finden Sie den Fehler im Feld Last_Error (siehe unten).

  • Master_Host

    Der aktuelle Master-Host.

  • Master_User

    Der aktuelle Benutzer, der mit dem Master verbunden ist.

  • Master_Port

    Der aktuelle Master-Port.

  • Connect_Retry

    Der aktuelle Wert der Option --master-connect-retry.

  • Master_Log_File

    Der Name der Master-Binärlogdatei, aus der der I/O-Thread derzeit liest.

  • Read_Master_Log_Pos

    Die Position, bis zu der der I/O-Thread im aktuellen Master-Binärlog gelesen hat.

  • Relay_Log_File

    Der Name der Relay-Logdatei, deren Angaben der SQL-Thread derzeit liest und ausführt.

  • Relay_Log_Pos

    Die Position, bis zu der der SQL-Thread Angaben in der aktuellen Relay-Logdatei gelesen und ausgeführt hat.

  • Relay_Master_Log_File

    Der Name der Master-Binärlogdatei, die das aktuelle Ereignis enthält, welches gerade vom SQL-Thread ausgeführt wird.

  • Slave_IO_Running

    Gibt an, ob der I/O-Thread gestartet wurde und erfolgreich eine Verbindung mit dem Master herstellen konnte. Bei älteren MySQL-Versionen (vor 4.1.14 und 5.0.12) hat Slave_IO_Running den Wert YES, wenn der I/O-Thread gestartet wurde (und zwar auch dann, wenn noch keine Verbindung zum Master hergestellt wurde).

  • Slave_SQL_Running

    Gibt an, ob der SQL-Thread gestartet wurde.

  • Replicate_Do_DB, Replicate_Ignore_DB

    Liste der Datenbanken, die ggf. mit den Optionen --replicate-do-db und --replicate-ignore-db angegeben wurden.

  • Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table

    Liste der Tabellen, die ggf. mit den Optionen --replicate-do-table, --replicate-ignore-table, --replicate-wild-do-table und --replicate-wild-ignore_table angegeben wurden.

  • Last_Errno, Last_Error

    Nummer und Meldung des Fehlers, der von der zuletzt ausgeführten Abfrage zurückgegeben wurde. Die Fehlernummer 0 und der Leer-String als Meldung haben die Bedeutung „kein Fehler“. Wenn der Wert Last_Error nicht leer ist, erscheint er auch als Meldung im Fehlerlog des Slaves. Zum Beispiel:

    Last_Errno: 1051
    Last_Error: error 'Unknown table 'z'' on query 'drop table z'
    

    Die Meldung zeigt an, dass die Tabelle z auf dem Master vorhanden war und dort gelöscht wurde, dass sie aber auf dem Slave nicht existierte, weswegen die Anweisung DROP TABLE dort fehlschlug. (Dies kann beispielsweise passieren, wenn Sie vergessen, die Tabelle beim Einrichten der Replikation auf den Slave zu kopieren.)

  • Skip_Counter

    Der zuletzt verwendete Wert von SQL_SLAVE_SKIP_COUNTER.

  • Exec_Master_Log_Pos

    Die Position des letzten vom SQL-Thread ausgeführten Ereignisses aus dem Binärlog des Masters (Relay_Master_Log_File). (Relay_Master_Log_File, Exec_Master_Log_Pos) im Binärlog des Masters entspricht (Relay_Log_File, Relay_Log_Pos) im Relay-Log.

  • Relay_Log_Space

    Die Gesamtgröße aller vorhandenen Relay-Logs.

  • Until_Condition, Until_Log_File, Until_Log_Pos

    Der in der UNTIL-Klausel der START SLAVE-Anweisung angegebene Wert.

    Until_Condition kann folgende Werte haben:

    • None, sofern keine UNTIL-Klausel angegeben wurde.

    • Master, wenn der Slave bis zu einer angegebenen Position in den Binärlogs des Masters liest.

    • Relay, wenn der Slave bis zu einer angegebenen Position in seinen Binärlogs liest.

    Until_Log_File und Until_Log_Pos geben den Namen der Logdatei und die Position an. Diese Werte definieren den Punkt, an dem die Ausführung des SQL-Threads endet.

  • Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key

    Diese Felder geben (sofern vorhanden) die SSL-Parameter an, die vom Slave zur Verbindung mit dem Master verwendet werden.

    Master_SSL_Allowed kann folgende Werte haben:

    • Yes, wenn eine SSL-Verbindung zum Master zulässig ist.

    • No, wenn keine SSL-Verbindung zum Master zulässig ist.

    • Ignored, wenn eine SSL-Verbindung zwar zulässig ist, aber am Slave-Server die SSL-Unterstützung nicht aktiviert ist.

    Die Werte der übrigen SSL-spezifischen Felder entsprechen den Werten der Optionen --master-ca, --master-capath, --master-cert, --master-cipher und --master-key.

  • Seconds_Behind_Master

    Dieses Feld gibt an, wie „verspätet“ der Slave ist:

    • Wenn der Slave-SQL-Thread aktiv läuft (d. h. Änderungen verarbeitet), dann gibt dieses Feld die Anzahl der Sekunden an, die seit dem Zeitstempel des Ereignisses vergangen sind, das von diesem Thread zuletzt auf dem Master ausgeführt wurde.

    • Wenn der SQL-Thread den Slave-I/O-Thread eingeholt hat und untätig auf weitere Ereignisse vom I/O-Thread wartet, ist das Feld null.

    Im Endeffekt misst das Feld also den zeitlichen Unterschied zwischen dem Slave-SQL-Thread und dem Slave-I/O-Thread.

    Ist die Netzwerkverbindung zwischen Master und Slave sehr schnell, dann liegt der Slave-I/O-Thread recht nah am Master, d. h., das Feld erlaubt eine recht genaue Schätzung des zeitlichen Verarbeitungsabstandes zwischen Slave-SQL-Thread und dem Master. Ist das Netzwerk hingegen langsam, dann ist der Wert nicht sehr aussagekräftig: Der Slave-SQL-Thread kann recht häufig zum langsam lesenden Slave-I/O-Thread aufschließen, weswegen Seconds_Behind_Master oft den Wert 0 anzeigt – und zwar auch dann, wenn der I/O-Thread im Vergleich zum Master relativ stark verspätet ist. Anders gesagt, diese Spalte ist nur bei schnellen Netzwerken aussagekräftig.

    Diese Berechnung des zeitlichen Unterschieds funktioniert, obwohl Master und Slave keine identisch laufenden Uhren haben (der Unterschied wird ermittelt, wenn der Slave-I/O-Thread startet; danach wird davon ausgegangen, dass der Abstand konstant bleibt). Seconds_Behind_Master ist NULL (d. h. „unbekannt“), wenn der Slave-SQL-Thread nicht ausgeführt wird oder wenn der Slave-I/O-Thread nicht läuft oder nicht mit dem Master verbunden ist. Schläft beispielsweise der Slave-I/O-Thread für die mit der Option --master-connect-retry angegebene Anzahl von Sekunden, bevor er eine Wiederverbindung versucht, dann wird NULL angezeigt, weil der Slave nicht wissen kann, was der Master tut, und deswegen auch nicht zuverlässig weiß, wie spät es ist.

    Dieses Feld hat eine Einschränkung: Der Zeitstempel wird bei der Replikation beibehalten, d. h., wenn ein Master M1 seinerseits ein Slave von M0 ist, dann hat jedes Ereignis im Binärlog von M1, das der Replikation eines Ereignisses aus dem Binärlog von M0 entstammt, auch den Zeitstempel dieses Ereignisses. Dies erlaubt MySQL die erfolgreiche Replikation von TIMESTAMP. Der Nachteil für Seconds_Behind_Master besteht allerdings darin, dass, wenn M1 auch direkte Updates von Clients erhält, der Wert wahllos abweicht, weil das letzte Ereignis auf M1 mal von M0 stammt, mal aber auch der letzte Zeitstempel eines direkten Updates ist.

13.6.2.8. START SLAVE

START SLAVE [thread_type [, thread_type] ... ]
START SLAVE [SQL_THREAD] UNTIL
    MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
    RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos

thread_type: IO_THREAD | SQL_THREAD

START SLAVE startet beide Slave-Threads. Der I/O-Thread liest Abfragen vom Master-Server und speichert sie im Relay-Log. Der SQL-Thread liest das Relay-Log und führt die Abfragen aus. START SLAVE erfordert die Berechtigung SUPER.

Wenn START SLAVE die Slave-Threads erfolgreich startet, wird kein Fehler zurückgegeben. Allerdings kann es auch in diesem Fall vorkommen, dass die Slave-Threads starten und kurz darauf wieder beendet werden (etwa weil sie keine Verbindung zum Master herstellen oder die Binärlogs nicht lesen konnten oder aus einem anderen Grund). START SLAVE warnt Sie davor nicht. Sie müssen das Fehlerlog des Slaves auf Fehlermeldungen prüfen, die von den Slave-Threads erzeugt wurden, oder sich mit SHOW SLAVE STATUS vergewissern, dass sie einwandfrei ausgeführt werden.

Sie können die Optionen IO_THREAD oder SQL_THREAD zur Anweisung hinzufügen, wenn Sie angeben wollen, welcher der Threads gestartet werden soll.

Eine UNTIL-Klausel kann hinzugefügt werden, um anzugeben, dass der Slave starten und laufen soll, bis der SQL-Thread einen gegebenen Punkt im Master-Binärlog oder den Slave-Relay-Logs erreicht. Wenn der SQL-Thread diesen Punkt erreicht, wird er beendet. Wird die Option SQL_THREAD in der Anweisung angegeben, dann startet nur der SQL-Thread. Andernfalls werden beide Slave-Threads gestartet. Läuft der SQL-Thread bereits, dann wird die Klausel UNTIL ignoriert, und eine Warnung wird ausgegeben.

Für eine UNTIL-Klausel müssen Sie sowohl einen Logdateinamen als auch eine Position angeben. Vermischen Sie die Optionen für Master- und Relay-Logs nicht.

Eine UNTIL-Bedingung wird von einer nachfolgenden STOP SLAVE-Anweisung, einer START SLAVE-Anweisung ohne UNTIL-Klausel oder einem Serverneustart zurückgesetzt.

Die UNTIL-Klausel kann nützlich sein, um die Replikation zu debuggen oder festzulegen, dass die Replikation bis genau zu dem Punkt fortfahren soll, an dem ein Slave eine Anweisung nicht mehr replizieren soll. Wurde beispielsweise versehentlich eine DROP TABLE-Anweisung auf dem Master ausgeführt, dann können Sie den Slave mit UNTIL anweisen, das Log nur bis unmittelbar vor diesem Punkt, aber nicht mehr weiter auszuführen. Um herauszufinden, was das Ereignis ist, verwenden Sie mysqlbinlog mit den Master-Logs oder den Slave-Relay-Logs oder setzen eine SHOW BINLOG EVENTS-Anweisung ab.

Wenn Sie UNTIL verwenden, damit der Slave-Prozess die Abfragen in Abschnitten repliziert, empfehlen wir den Start des Slaves mit der Option --skip-slave-start, damit der SQL-Thread nicht ausgeführt wird, wenn der Slave-Server startet. Es ist wahrscheinlich am besten, diese Option in einer Optionsdatei statt auf der Befehlszeile zu benutzen, damit die Klausel bei einem unerwarteten Serverneustart nicht vergessen wird.

Die SHOW SLAVE STATUS-Anweisung enthält Ausgabefelder, die die aktuellen Werte der UNTIL-Bedingung anzeigen.

In älteren Versionen von MySQL (vor 4.0.5) hieß diese Anweisung SLAVE START. Ihre Verwendung in dieser Form ist zwar in MySQL 5.1 aus Kompatibilitätsgründen noch akzeptabel, aber veraltet.

13.6.2.9. STOP SLAVE

STOP SLAVE [thread_type [, thread_type] ... ]

thread_type: IO_THREAD | SQL_THREAD

Beendet die Slave-Threads. STOP SLAVE erfordert die Berechtigung SUPER.

Wie START SLAVE kann diese Anweisung mit den Optionen IO_THREAD und SQL_THREAD verwendet werden, um den oder die zu beendenden Threads anzugeben.

In älteren Versionen von MySQL (vor 4.0.5) hieß diese Anweisung SLAVE STOP. Ihre Verwendung in dieser Form ist zwar in MySQL 5.1 aus Kompatibilitätsgründen noch akzeptabel, aber veraltet.

13.7. SQL-Syntax für vorbereitete Anweisungen

MySQL 5.1 unterstützt serverseitige vorbereitete Anweisungen. Diese Unterstützung nutzt das effiziente binäre Client/Server-Protokoll, welches in MySQL 4.1 implementiert wurde. Voraussetzung hierfür ist, dass Sie eine geeignete Client-Programmierschnittstelle verwenden. Geeignete Schnittstellen sind die C-API-Clientbibliothek von MySQL (für C-Programme), MySQL Connector/J (für Java-Programme) und MySQL Connector/NET. So bietet etwa die C-API eine Anzahl von Funktionsaufrufen, die eine API für vorbereitete Anweisungen darstellen. Siehe auch Abschnitt 24.2.4, „C-API: Prepared Statements“. Andere Sprachschnittstellen bieten Unterstützung für vorbereitete Anweisungen, die das binäre Protokoll verwenden, indem Sie eine Verbindung in die C-Clientbibliothek herstellen (z. B. die mysqli-Erweiterung in PHP 5.0).

Es gibt auch eine alternative SQL-Schnittstelle für vorbereitete Anweisungen. Diese ist zwar nicht so effizient wie die Verwendung eines binären Protokolls über eine API für vorbereitete Anweisungen, sie erfordert aber auch keine Programmierung, weil sie direkt auf SQL-Ebene verfügbar ist:

  • Sie können sie verwenden, wenn Ihnen keine Programmierschnittstelle zur Verfügung steht.

  • Sie können sie aus jedem Programm heraus verwenden, das Ihnen die Übermittlung von SQL-Anweisungen an den Server zur dortigen Ausführung gestattet (dies gilt beispielsweise für das mysql-Clientprogramm).

  • Sie können es auch dann verwenden, wenn der Client eine alte Version der Clientbibliothek einsetzt. Die einzige Voraussetzung besteht darin, dass Sie eine Verbindung mit einem Server herstellen können müssen, der aktuell genug ist, um die SQL-Syntax für vorbereitete Anweisungen zu unterstützen.

Die SQL-Syntax für vorbereitete Anweisungen ist zur Verwendung in Fällen wie den folgenden vorgesehen:

  • Sie wollen die Funktion vorbereiteter Anweisungen in Ihrer Anwendung testen, bevor Sie sie einkodieren.

  • Eine Anwendung hat Probleme mit der Ausführung vorbereiteter Anweisungen, und Sie wollen dem Problem interaktiv auf den Grund gehen.

  • Sie wollen einen Testfall erstellen, der ein Problem im Zusammenhang mit vorbereiteten Anweisungen beschreibt. Dieser soll als Grundlage eines Fehlerberichts dienen.

  • Sie müssen vorbereitete Anweisungen verwenden, haben aber keinen Zugang zu einer Programmierschnittstelle, die diese unterstützt.

Die SQL-Syntax für vorbereitete Anweisungen basiert auf drei SQL-Anweisungen:

  • PREPARE stmt_name FROM preparable_stmt

    Die Anweisung PREPARE bereitet eine Anweisung vor und weist ihr den Namen stmt_name zu, unter dem sie später referenziert werden kann. Die Groß-/Kleinschreibung wird bei Anweisungsnamen nicht unterschieden. preparable_stmt ist entweder ein String-Literal oder eine Benutzervariable, die den Text der Anweisung enthält. Der Text muss eine einzelne SQL-Anweisung (nicht mehrere Anweisungen) darstellen. In dieser Anweisung können Fragezeichen (‘?’) als Parameterkennzeichen verwendet werden: Sie geben an, wo bei der späteren Ausführung der Anweisung Datenwerte eingebunden werden. Fragezeichen sollten auch dann nicht in Anführungszeichen gesetzt werden, wenn Sie beabsichtigen, sie an String-Werte anzubinden. Parameterkennzeichen dürfen nur an Stellen verwendet werden, an denen Datenwerte eingefügt werden sollen, nicht jedoch für SQL-Schlüsselwörter, Bezeichner usw.

    Wenn eine vorbereitete Anweisung des angegebenen Namens bereits vorhanden ist, wird diese Namenszuweisung implizit aufgehoben, bevor die neue Anweisung vorbereitet wird. Das bedeutet, dass, wenn die neue Anweisung einen Fehler enthält und nicht vorbereitet werden kann, ein Fehler zurückgegeben wird; in diesem Fall gibt es keine Anweisung des betreffenden Namens mehr.

    Der Gültigkeitsbereich einer vorbereiteten Anweisung ist die Clientsitzung, innerhalb derer sie erstellt wird. Andere Clients sehen sie nicht.

  • EXECUTE stmt_name [USING @var_name [, @var_name] ...]

    Nach der Vorbereitung einer Anweisung können Sie sie mit einer EXECUTE-Anweisung ausführen, die den Namen der vorbereiteten Anweisung referenziert. Wenn die vorbereitete Anweisung Parameterkennzeichen enthält, müssen Sie eine USING-Klausel angeben, die die Benutzervariablen mit den Werten auflistet, welche für die Parameter eingesetzt werden sollen. Parameterwerte können nur über Benutzervariablen übergeben werden. Die USING-Klausel muss so viele Variablen übergeben, wie Parameterkennzeichen in der Anweisung vorhanden sind, und alle Variablennamen müssen korrekt sein.

    Sie können eine vorbereitete Anweisung mehrfach ausführen und dabei unterschiedliche Variablen übergeben oder die Variablen vor jeder Ausführung auf andere Werte setzen.

  • {DEALLOCATE | DROP} PREPARE stmt_name

    Um eine vorbereitete Anweisung aufzuheben, verwenden Sie die Anweisung DEALLOCATE PREPARE. Wenn Sie eine vorbereitete Anweisung auszuführen versuchen, nachdem Sie sie aufgehoben haben, wird ein Fehler erzeugt.

    Wenn Sie eine Clientsitzung beenden, ohne eine zuvor vorbereitete Anweisung aufzuheben, dann hebt der Server sie automatisch auf.

In vorbereiteten Anweisungen können die folgenden SQL-Anweisungen verwendet werden: CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE und die meisten SHOW-Anweisungen. Andere Anweisungen werden noch nicht unterstützt.

Die folgenden Beispiele zeigen zwei gleichwertige Arten der Vorbereitung einer Anweisung, die die Hypotenuse eines Dreiecks berechnet, bei dem zwei Seitenlängen gegeben sind.

Das erste Beispiel zeigt, wie man eine vorbereitete Anweisung unter Verwendung eines String-Literals erstellt, um den Text der Anweisung zu übergeben:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

Das zweite Beispiel ist ähnlich, übergibt den Text der Anweisung aber als Benutzervariable:

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|         10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;

Die SQL-Syntax für vorbereitete Anweisungen erlaubt keine Verschachtelungen: Eine an PREPARE übergebene Anweisung darf selbst keine PREPARE-, EXECUTE- oder DEALLOCATE PREPARE-Anweisung sein.

Die SQL-Syntax für vorbereitete Anweisungen unterscheidet sich von der Verwendung von API-Aufrufen für vorbereitete Anweisungen. So können Sie beispielsweise mit der C-API-Funktion mysql_stmt_prepare() keine PREPARE-, EXECUTE- oder DEALLOCATE PREPARE-Anweisung vorbereiten.

Die SQL-Syntax für vorbereitete Anweisungen kann in gespeicherten Prozeduren, nicht aber in gespeicherten Funktionen oder Triggern verwendet werden.

Bei der Verwendung vorbereiteter Anweisungen können für die Argumente der LIMIT-Klausel Platzhalter eingesetzt werden. Siehe auch Abschnitt 13.2.7, „SELECT.


Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.