Drupal 7のdb_affected_rows(db_query)


8

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

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

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 ...");
}

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

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

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

回答:



8

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

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

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

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

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

ああ、はい、これが更新された質問の正解です:)マージクエリは、D7開発サイクルの後半に再設計されて、実際にはSQL 2003標準の一部であるMERGE sqlクエリのように機能するようになりましたが、dbmsはまだそれを実装していません、したがって、すべてのdbmsには2つのクエリが必要です(トランザクションを使用することで、アトミックになります)。MySQLに使用された単一クエリアプローチの問題は、key()定義を完全に無視し、特定のテーブルの一意/主キーを単純に処理することでした。
Berdir

@Berdir:私を正しい方向に向けてくれてありがとう。私はSQLを書くのが好きで、新しいdb APIに慣れるのに苦労している開発者の一人です:)
googletorp

このポインタをありがとう。ただし、Drupal db apiではCURRENT_TIMESTAMP(drupal.org/node/215821を参照)などの定数を使用できないため、とにかくdb_queryに頼らなければなりませんでした
Whisky
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.