db_affected_rows in Drupal 7 für db_query

8

Mir ist gerade aufgefallen, dass es so schön wardb_affected_rows , @Berdir aus Drupal 7 zu entfernen . Ich frage mich jetzt, wie Sie jetzt am besten feststellen können, ob die von Ihnen ausgeführte Abfrage etwas in der Datenbank geändert hat.

Ein typischer Anwendungsfall wäre zu.

db_query(...);
if (!db_affected_rows()) {
  db_query(...);
}

Ich habe mir das von db_query zurückgegebene Abfrageobjekt angesehen, aber es schien nicht viel Hilfe zu sein.

Update:
Ich sehe, ich war ein bisschen unklar, unter welchen Umständen ich die Informationen brauchte.

Mein aktueller Anwendungsfall ist recht einfach. Ich habe eine Tabelle für einen Knotentyp mit einer NID-Spalte und einigen Datenspalten. Ich habe ein Formular und möchte nach dem Absenden des Formulars die Zeile in der Datenbank entweder einfügen oder aktualisieren.

Das Problem mit db_update/ db_insertist, dass ich, wenn ich zuerst update verwende und einfüge, wenn update 0 zurückgibt, die Bedingung nicht abfange, bei der das Formular mit dem Wert in der Datenbank gesendet wurde. Wenn ich zuerst db_insert verwende, wird dies einen Fehler auslösen, wenn bereits eine Zeile in der Datenbank vorhanden ist.

Ich nehme an, ich könnte in diesem speziellen Zustand beim Erstellen des Knotens einen leeren Wert einfügen und dann nur update verwenden. In einigen Fällen ist dies jedoch möglicherweise nicht möglich, wenn ich Informationen speichern muss, die für eine externe Datenbank verschlüsselt wurden. Ich möchte auch vermeiden, dass ich mich auf Datenbankwerte verlassen muss, damit mein Code funktioniert.

Meine übliche Strategie für solche Fälle war es, a

db_query("INSERT IGNORE INTO ...")
if (!db_affected_rows()) {
  db_query("UPDATE ...");
}

Dies ist sowohl einfach als auch fehlerfrei, egal in welchem ​​Zustand sich die Datenbank befindet. Die beste Option, die ich derzeit sehen kann, wäre, sie mit SQL zu handhaben und dies zu tun:

db_query("INSERT ... ON DUPLICATE KEY UPDATE");

Ich hatte jedoch gehofft, dass die Datenbank-API damit umgehen kann.

googletorp
quelle

Antworten:

9

Diese Informationen werden direkt von der execute () -Methode von Delete / UpdateQuery zurückgegeben, siehe zum Beispiel: UpdateQuery :: execute () .

<?php
$affected = db_update('some_table')
  ->fields(array(
    'some_field' => $value,
  ))
  ->condition('another_field', $id)
  ->execute();
?>

Und InsertQuery :: execute () gibt die letzte Einfüge-ID zurück.

Berdir
quelle
8

Nachdem ich mich umgesehen hatte, stellte ich fest, dass Drupal ein fertiges benanntes Tool für meinen genauen Anwendungsfall bereitstellt:

Fügen Sie eine Zeile in die Datenbank ein oder aktualisieren Sie die vorhandene, wenn sie bereits vorhanden ist.

Dies wird als Zusammenführungsabfragen bezeichnet , die für einige DB-Engines atomar ausgeführt werden können.

Der Syntext ist ziemlich einfach:

db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
    'field1' => $value1,
    'field2' => $value2,
))
->execute();
googletorp
quelle
Ah ja, das ist die richtige Antwort auf Ihre aktualisierte Frage :) Beachten Sie, dass Zusammenführungsabfragen spät im D7-Entwicklungszyklus neu gestaltet wurden, um tatsächlich wie MERGE-SQL-Abfragen zu funktionieren, die Teil des SQL 2003-Standards sind, aber noch nicht von DBMS implementiert wurden Daher erfordern alle DBMS zwei Abfragen (sie werden mithilfe von Transaktionen atomarisiert). Das Problem bei dem für MySQL verwendeten Einzelabfrageansatz bestand darin, dass die key () - Definition vollständig ignoriert und einfach mit den eindeutigen / Primärschlüsseln einer bestimmten Tabelle gearbeitet wurde.
Berdir
@Berdir: Danke, dass du mich in die richtige Richtung gelenkt hast. Ich bin einer der Entwickler, die gerne SQL schreiben und sich nur schwer an die neue
Datenbank-
Danke für diesen Hinweis. Ich musste jedoch trotzdem auf db_query zurückgreifen, da die Drupal db api die Verwendung von Konstanten wie CURRENT_TIMESTAMP nicht zulässt (siehe drupal.org/node/215821 )
Whiskey