MySQL-Variablen für Spaltennamen (und andere Identifier) verwenden

By

in

Variablen lassen sich in MySQL hervorragend für Strings, Zahlenwerte oder auch binäre Daten verwenden. Möchte man diese Variablen jedoch zum Adressieren von Spalten, Tabellen oder Datenbanken verwenden, dann erfordert dies ein etwas anderes Vorgehen. Dieser Artikel gibt eine kurze Zusammenfassung, wie man MySQL-Variablen in Abfragen einsetzt.

Variablen für Daten (Grundsyntax)

Zunächst einmal die allgemeine VerwendungFolgendes Beispiel zeigt eine einfachste Verwendung von Variablen:

SQL
SET @t1=1, @t2=2, @t3:=4;
-- Query OK, 0 rows affected (0.00 sec)
SQL
SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;
-- +------+------+------+--------------------+
-- | @t1  | @t2  | @t3  | @t4 := @t1+@t2+@t3 |
-- +------+------+------+--------------------+
-- |    1 |    2 |    4 |                  7 | 
-- +------+------+------+--------------------+
-- 1 row in set (0.00 sec)

Nutzt man Variablen, um Spaltennamen dynamisch anzusprechen, dann ist dies mit der einfachen Variablen-Syntax jedoch nicht möglich, wie folgendes Beispiel zeigt:

SQL
SET @col = "c1";
-- Query OK, 0 rows affected (0.00 sec)
SQL
SELECT @col FROM t;
-- +------+
-- | @col |
-- +------+
-- | c1   |
-- +------+
-- 1 row in set (0.00 sec)
SQL
SELECT `@col` FROM t;
-- ERROR 1054 (42S22): Unknown column '@col' in 'field list'

Hierbei wird c1 ebenfalls als String interpretiert und dabei nicht auf die Daten der eigentlichen Spalte zugegriffen. Die Ausgabe liefert nur den Inhalt ‘c1’ der Variablen zurück.

Variablen für Spaltennamen (Identifier) verwenden

Um Variablen auch für Spaltennamen bzw. Identifier verwenden zu können, muss man etwas weiter ausholen. Das Prinzip ist folgendes: man erstellt sich einen String, welcher der Abfrage entspricht und führt diese anschließend aus. Diese Methode erlaubt das Adressieren jeglicher Identifier (Spalten, Tabellen, Datenbanken, …) in MySQL. Nachfolgendes Beispiel soll dieses Vorgehen genauer erläutern.

Zunächst setzt man wie gewohnt die Inhalte der Variablen:

SQL
SET @c = "c1";
-- Query OK, 0 rows affected (0.00 sec)

Anschließend erstellt man einen String (ebenfalls in einer Variablen), welche die SQL-Abfrage enthält:

SQL
SET @s = CONCAT("SELECT ", @c, " FROM t");
-- Query OK, 0 rows affected (0.00 sec)

… bereitet die Abfrage vor:

SQL
PREPARE stmt FROM @s;
-- Query OK, 0 rows affected (0.04 sec)
-- Statement prepared

… und führt sie aus:

SQL
EXECUTE stmt;
-- +----+
-- | c1 |
-- +----+
-- |  0 |
-- +----+
-- |  1 |
-- +----+
-- 2 rows in set (0.00 sec)

Über DEALLOCATE PREPARE wird die erstellte Abfrage wieder freigegeben:

SQL
DEALLOCATE PREPARE stmt;
-- Query OK, 0 rows affected (0.00 sec)

Die Syntax von PREPARE, EXECUTE und DEALLOCATE PREPARE wird unter SQL Syntax for Prepared Statements des MySQL-Manuals genauer erläutert.



Comments

5 responses to “MySQL-Variablen für Spaltennamen (und andere Identifier) verwenden”

  1. Danke schön,

    lange gesucht, funktioniet auch wunderbar mit Tabellennamen !

  2. Wirklich sehr schön erklärt, danke! Genau was ich gesucht habe und was natürlich in der MySQL Doku nicht sauber dokumentiert wurde.

    Hätte ich auch selbst drauf kommen können (im Nachhinein) 😉

    Viele Grüße!

  3. Michael Saxer Avatar
    Michael Saxer

    hallo;
    was habe ich denn hier falsch gemacht ? Ich bekomme für $anz nichts angezeigt.
    Vielen Dank;
    Michael Saxer

    $db->query("SET @a1 = 'test'");
    $db->query("SET @a2 = CONCAT('SELECT * FROM ', @a1)"); 
    $db->query("PREPARE a3 FROM @a2");
    $erg = $db->query("EXECUTE a3");
    $anz = $erg->num_rows;
    echo $anz;
    1. Mathias Lipowski Avatar
      Mathias Lipowski

      Hallo Michael,

      die 4 Abfragen habe ich lokal getestet und nacheinander ausgeführt. Diese sind so korrekt und bringen das gewünschte Ergebnis.

      Lass dir mal die letzten MySQL-Fehler anzeigen. Existiert die Datenbank ‘test’ auch? Welches PHP-System/Framework oder welche Klasse nutzt du im Hintergrund für die Verbindung zu MySQL?

      Grüße,
      Mathias

Leave a Reply

Your email address will not be published. Required fields are marked *