Drupal 7 でのデータベース操作 - レッスン 11 - MERGE クエリ
マージクエリは、データベースクエリの特殊なハイブリッド型です。これらのクエリの構文は SQL 2003 で定義されましたが、実際にサポートしているデータベースはわずかです。しかし、ほとんどのデータベースは特定の構文を使った代替実装を提供しています。Drupal のマージクエリビルダーは、マージクエリの概念をオブジェクト構造に抽象化するため、各データベースの独自の構文に基づいて適切にコンパイルできます。
一般に、マージクエリは insert クエリと update クエリの組み合わせです。条件が満たされる場合――つまり特定のキーを持つ行がすでに存在する場合――一方のクエリ(通常は UPDATE)が実行されます。そうでない場合は、もう一方(通常は INSERT)が実行されます。これは次に似ています:
$id)))->fetchField()) {
// Run an update using WHERE id = $id
}
else {
// Run an insert, inserting $id for id
}
?>
実際には、実装はデータベースによって異なります。マージクエリは概念的にはアトミックですが、特定のデータベース実装によっては実際にアトミックである場合もそうでない場合もあることに注意してください。たとえば MySQL の実装はアトミックですが、上記の PHP コードスニペットはそうではありません。
基本的な例
key(array('name' => $name))
->fields(array(
'field1' => $value1,
'field2' => $value2,
))
->execute();
?>
この例では、「example」テーブルを操作します。値が $name の一意のキーフィールド name を定義し、設定するフィールド値の配列を提供します。
name = $name の行がすでに存在する場合、field1 と field2 が $value1 と $value2 で更新されます。そのような行が存在しない場合は、同じ値で新しい行が挿入されます。
条件の設定
場合によっては、レコードがすでに存在するかどうかに応じて異なる値を設定したいことがあります。これには 2 つの方法があります。
key(array('name' => $name))
->fields(array(
'field1' => $value1,
'field2' => $value2,
))
->updateFields(array(
'field1' => $alternate1,
))
->execute();
?>
この例は前の例と同じように動作しますが、レコードがすでに存在する場合は field1 のみが $alternate1 で更新される点が異なります。レコードが存在しない場合は、field1 = $value1 と field2 = $value2 で作成されます。updateFields() メソッドは連想配列(またはキーと値の 2 つの順序付き数値配列)を受け取ります。
key(array('name' => $name))
->fields(array(
'field1' => $value1,
'field2' => $value2,
))
->expression('field1', 'field1 + :inc', array(':inc' => 1))
->execute();
?>
この場合、行がすでに存在すれば、field1 は 1 増加します。これは、イベントが発生するたびにフィールドを増やしたいカウンターのような動作に役立ちます。行が存在しない場合は、field1 と field2 が指定された値に設定されます。expression() メソッドは、既存の行に対する SQL 式を定義するために、フィールドごとに 1 回ずつ、複数回使えます。3 つのパラメーターを取ります:フィールド名、使用する SQL フラグメント、そして任意のプレースホルダー値の配列です。
注意:expression() で使うフィールドは、fields() に含まれている必要はありません。
選択的なフィールド更新
key(array('name' => $name))
->fields(array(
'field1' => $value1,
'field2' => $value2,
))
->updateExcept('field1')
->execute();
?>
updateExcept() メソッドは、フィールド名の配列、またはカンマ区切りのフィールド名リストのいずれかを受け取ります。指定されたフィールドは、行がすでに存在する場合には更新されません。たとえば、name = $name の行が存在する場合、field2 のみが更新され、field1 は無視されます。行が存在しない場合は、field1 と field2 の両方が挿入されます。
優先順位のルール
API では、論理的に意味をなさない組み合わせも可能です。たとえば、同じフィールドに expression() と updateExcept() を使うなどです。曖昧さを避けるため、Drupal は次のルールを適用します:
- フィールドが
expression()を使って設定されている場合、それはupdate()とupdateExcept()より優先されます。 - 値が
update()とupdateExcept()の両方で指定されている場合、そのフィールドは無視されます。 update()が使われている場合、既存の行ではupdate()に列挙されたフィールドのみが更新されます。それ以外のすべてのフィールドは無視されます。
意味をなさないクエリを定義できてしまうので、この API は慎重に使ってください。