Tabelle wird mit WordPress dbdelta nicht aktualisiert

Lesezeit: 6 Minuten

Ich habe folgenden Code zum Erstellen einer Tabelle:

$sql = "CREATE TABLE " . $table_name . "("
         . "id mediumint(9) NOT NULL AUTO_INCREMENT, "
         . "product_id mediumint(9) DEFAULT 0 NOT NULL,"
         . "name_type mediumint(9) NOT NULL, "
         . "name_key varchar(48) NOT NULL, "
         . "valid_until datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "UNIQUE KEY id (id)"
         . ")" . $charset_collate. ";";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );

Es funktioniert und die Tabelle wurde erstellt.

Jetzt muss ich die Tabelle aktualisieren und eine neue Spalte hinzufügen (sites_list):

$sql = "CREATE TABLE " . $table_name . "("
         . "id mediumint(9) NOT NULL AUTO_INCREMENT, "
         . "product_id mediumint(9) DEFAULT 0 NOT NULL,"
         . "name_type mediumint(9) NOT NULL, "
         . "name_key varchar(48) NOT NULL, "
         . "sites_list longtext, "
         . "valid_until datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "UNIQUE KEY id (id)"
         . ")" . $charset_collate. ";";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );

Aber das funktioniert nicht.

Und ich habe einen Fehler:

WordPress database error: [Table 'table_name' already exists]

Was ist falsch?

Danke.

  • Der Fehler ist ziemlich klar. Sie können die Tabelle nicht erstellen, da sie bereits vorhanden ist. Du willst wahrscheinlich ALTER TABLE oder CREATE TABLE IF NOT EXISTS

    – naththedeveloper

    22. März 2016 um 16:08

  • Ja, das wird großartig, aber aus dem Codex: Die dbDelta-Funktion untersucht die aktuelle Tabellenstruktur, vergleicht sie mit der gewünschten Tabellenstruktur und fügt die Tabelle nach Bedarf hinzu oder ändert sie, sodass sie bei Aktualisierungen sehr praktisch sein kann. https://stackoverflow.com/questions/36159055/table-not-updating-with-wordpress-dbdeltacodex.wordpress.org/… Ich denke, die Verwendung dbdelta korrekter ist es, das Plugin zu aktualisieren

    – Eugen

    22. März 2016 um 16:28


  • Dieses Problem liegt wahrscheinlich daran, dass sich Ihre Felder nicht tatsächlich in separaten Zeilen befinden (dies ist eine der „Bedingungen“, die von der Funktion festgelegt werden). Der Grund dafür ist, dass Sie die Zeichenfolge verketten und dies tatsächlich zu einer einzelnen Zeile führt. I Ich werde eine Antwort hinzufügen und versuchen, dies etwas besser zu erklären.

    – naththedeveloper

    23. März 2016 um 7:48

  • Ich versuche, die Verkettung zu entfernen, aber es hat sich nichts geändert. Fehler ist derselbe.

    – Eugen

    25. März 2016 um 5:34

Sie haben die dbDelta-Funktion falsch verwendet.

  • Sie müssen jedes Feld in Ihrer SQL-Anweisung in eine eigene Zeile einfügen.

  • Zwischen den Wörtern PRIMARY KEY und der Definition Ihres Primärschlüssels müssen zwei Leerzeichen stehen.

  • Sie müssen das Schlüsselwort KEY anstelle seines Synonyms INDEX verwenden und mindestens einen KEY angeben.

http://hungred.com/how-to/wordpress-dbdelta-function/

Der Code selbst der dbDelta-Funktion ist sehr komplex. Aber durch Versuch und Irrtum sind mir einige Verhaltensweisen der dbDelta-Funktion aufgefallen aktualisieren Verhalten:

  • Die Primärschlüsselspalte wird nicht umbenannt
  • Es wird keine Spalte entfernt
  • Wenn Sie versuchen, eine alte Spalte umzubenennen, wird lediglich eine neue Spalte erstellt und die alte beibehalten.

Lange Erklärung

dbDelta ist eine Funktion, die man normalerweise nutzen soll register_activation_hook, aber dies wird nicht bei Plugin-Updates ausgelöst, sodass keine Tabellen für Ihre Benutzer erstellt werden, die eine bestehende Installation aktualisieren. Um dbDelta-Updates zum Laufen zu bringen, müssen Sie es also zunächst einbinden admin_init.

Allerdings handelt es sich hierbei um eine ziemlich umfangreiche Funktion, sodass sie nur bei Bedarf ausgeführt werden darf. Dafür können Sie eine behalten my_plugin_db_version Option in der Datenbank und prüfen Sie damit, ob Sie dbDelta ausführen sollten oder nicht.

Wenn bereits eine automatisch geladene Option geladen wird, ist es sogar noch besser, diese zu verwenden, da die Prüfung keine Auswirkungen auf die Leistung hat, da automatisch geladene Optionen zu Beginn des WordPress-Lebenszyklus in den Speicher geladen werden.

Dies kann im Code ausgedrückt werden als:

add_action('admin_init', 'my_plugin_maybe_run_delta');

function my_plugin_maybe_run_delta() {
  // Here we are not using an existing autoloaded option to keep the example short
  $dbVersion = get_option('my_plugin_db_version');

  // Early bail: No need to run dbDelta
  if ($dbVersion === '1.0.0') {
    return;
  }

  // dbDelta here...

  // Now set the db version so it can early bail next time...
  update_option('my_plugin_db_version', '1.0.0', false);
}

Nehmen wir nun an, dass ich dieses dbDelta in Version 1.0 meines Plugins habe:

global $wpdb;
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

$tableName = $wpdb->prefix . 'foo';
$charset_collate = $wpdb->get_charset_collate();

$sql = "CREATE TABLE $tableName (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  event longtext NOT NULL,
  PRIMARY KEY  (id)
) $charset_collate;";

dbDelta($sql);

// Some error happened during dbDelta.
if (!empty($lastErrorBefore) && $lastErrorBefore !== $wpdb->last_error) {
    // handle error
}

Dies erzeugt die folgende DDL in der Datenbank:

CREATE TABLE `wp_foo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Jetzt entscheide ich mich für eine Umbenennung id Zu event_idalso ändere ich das dbDelta und veröffentliche die Version 1.1 des Plugins:

$sql = "CREATE TABLE $tableName (
  event_id bigint(20) NOT NULL AUTO_INCREMENT,
  event longtext NOT NULL,
  PRIMARY KEY  (event_id)
) $charset_collate;";

Dieses Delta ändert die Datenbankstruktur für Benutzer, die das Plugin aktualisieren, nicht, sie haben den Primärschlüssel als idwährend Neuinstallationen den Primärschlüssel als haben event_id:

CREATE TABLE `wp_foo` (
  `event_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Regel Nr. 1 von dbDelta: Die Primärschlüsselspalte wird nicht umbenannt.

Jetzt, in Version 1.2, möchte ich umbenennen event Zu eventsalso ändere ich das dbDelta wie folgt:

$sql = "CREATE TABLE $tableName (
  event_id bigint(20) NOT NULL AUTO_INCREMENT,
  events longtext NOT NULL,
  PRIMARY KEY  (event_id)
) $charset_collate;";

Dies führt für Benutzer, die ein Upgrade von 1.1 auf 1.2 durchführen, zu folgendem Ergebnis:

CREATE TABLE `wp_foo` (
  `event_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Bei Neuinstallationen wird das folgende Ergebnis angezeigt:

CREATE TABLE `wp_wpstg_analytics` (
  `event_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Dabei wird für Benutzer, die das Plugin seit 1.0 verwenden, das folgende Ergebnis erzielt:

CREATE TABLE `wp_wpstg_analytics` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Das ist ein ziemlich vernünftiges Verhalten, wenn man darüber nachdenkt. Wenn Sie die Spalte umbenennen event Zu eventskönnen Sie die Daten für frühere Installationen weiterhin von der alten Spalte in die neue migrieren. Denken Sie daran, die Spalte, die als Primärschlüssel zugewiesen ist, niemals umzubenennen.

1451250cookie-checkTabelle wird mit WordPress dbdelta nicht aktualisiert

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy