web-dev-qa-db-ja.com

db_affected_rows in Drupal 7 for db_query

@ BerdirがDrupal 7 からdb_affected_rowsを削除してよかったことに気づきました。ここで、実行したクエリがデータベース内の何かを変更したかどうかを検出するためのベストプラクティスは何なのかと思っています。

典型的なユースケースは次のとおりです。

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

Db_queryから返されたクエリオブジェクトを確認しましたが、あまり役に立ちませんでした。

更新:
どのような状況で情報が必要かについて、私は少し不明瞭でした。

私の現在の使用例は、非常に単純なものです。 nid列といくつかのデータ列を持つノードタイプのテーブルがあります。フォームの送信時にフォームがあり、データベースに行を挿入または更新します。

db_update/db_insertの問題は、最初にupdateを使用し、updateが0を返した場合に挿入すると、フォームがdbの値で送信された状態をキャッチできないことです。最初にdb_insertを使用した場合、すでにdbに行があるとエラーが発生します。

この特定の状況では、ノードの作成時に空白の値を挿入してから更新のみを使用できると思いますが、外部データベースにキー入力された情報を格納する必要がある場合は、それができない場合があります。また、コードが機能するためにデータベースの値に依存する必要がないようにしたいと思います。

そのような場合の私の通常の戦略は、

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

これを行うことは、dbがどのような状態であっても、シンプルでエラーのない状態です。現在私が見ることができる最良のオプションは、SQLで処理してこれを行うことです。

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

しかし、私はdb APIがこれを処理できることを望んでいました。

8
googletorp

調べてみたところ、Drupalは、私の正確なユースケースに対応した、すぐに使える名前の付いたツールを提供しています。

dbに行を挿入するか、既存の行がある場合は既存の行を更新します。

これは マージクエリ と呼ばれ、一部のdbエンジンではアトミックに実行できます。

シンテキストはかなりシンプルです:

db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
    'field1' => $value1,
    'field2' => $value2,
))
->execute();
8
googletorp

その情報は、Delete/UpdateQueryのexecute()メソッドによって直接返されます。例: pdateQuery :: execute() を参照してください。

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

そして InsertQuery :: execute() は最後の挿入IDを返します。

9
Berdir