在 Drupal 7 中操作数据库 - 第12课 - 查询条件(WHERE、HAVING、LIKE)
查询条件允许我们选择仅符合特定限制的记录,例如两周内创建的节点、名称中包含“Drupal”一词的术语等。在 SQL 中,我们使用 WHERE 和 HAVING 来为 SELECT、UPDATE、DELETE 查询设置限制。在 Drupal 的动态查询中,也提供了用于处理查询条件的机制。这个机制在三种类型的查询(选择、更新、删除)中工作方式相同。
条件表达式的概念
条件包含在一个专门定义限制的表达式中。
合并(相加、并集、逻辑与)
每个条件可以由多个条件表达式组成,这些表达式可以组合在一起。条件通过运算符 AND(与) 和 OR(或) 来连接。
条件对象
Drupal 将每个条件片段表示为 QueryConditional 类的实例。条件对象是该类的一个实例。
我们来看一个 SQL 查询示例:
查询语句:
SELECT FROM {mytable} WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
条件表达式:
WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
条件表达式的部分:
(a = 1 AND b = 'foo' OR (c = 'bar'))
(c = 'bar')
条件连接运算符:
AND, OR
SELECT、UPDATE、DELETE 查询对象通过 QueryConditionalInterface 类实现,该接口为这三种查询类型提供了统一的接口。然后该对象被包装在 QueryConditional 对象中。可以直接调用 QueryConditional 类。
每个条件片段默认使用 AND 运算符连接。一个或多个条件片段也可以通过其他连接运算符(如 OR)组合。
API
有两个主要方法用于定义条件对象:
$query->condition($field, $value = NULL, $operator = '=')
condition() 方法用于定义字段、值和比较运算符。该方法可用于设置二元比较(即返回 TRUE 或 FALSE 的比较),如 =、<、>=、LIKE 等。如果未定义运算符,默认使用 =(精确匹配)。例如:condition('myfield', $value)
将被转换为 myfield = :value
,其中 :value
是由变量 $value
替换的占位符。
$query->where($snippet, $args = array())
where() 是一个附加方法,因为可以使用 condition() 代替它。但由于 where() 使用频繁,因此被单独实现。参数 $snippet 中写入标准 SQL 片段,而 $args 包含替换查询中的变量。
一般推荐使用 condition() 而不是 where()。
数组条件
有时我们需要为查询设置包含多个值的条件。这时可以将数组作为值传递。最常见的 SQL 运算符是 IN 和 BETWEEN。IN 运算符仅匹配数组中任意一个精确值。
<?php $query->condition('myfield', array(1, 2, 3), 'IN'); // 转换为: myfield IN (:db_placeholder_1, :db_placeholder_2, :db_placeholder_3) ?>
这样,我们会选择字段 myfield 值为 1、2 或 3 的所有记录。
若要设置值范围,可以使用 BETWEEN:
<?php $query->condition('myfield', array(5, 10), 'BETWEEN'); // 转换为: myfield BETWEEN :db_placeholder_1 AND :db_placeholder_2 ?>
这将选择字段 myfield 值在 5 到 10 之间的所有记录。
嵌套条件
condition() 的第一个参数也可以接受另一个条件对象。嵌套查询可以包含在更复杂的查询中。最终,我们可以得到带有 AND 和 OR 运算符组合的复杂条件表达式。
辅助函数 db_condition() 返回一个新的条件对象。该函数的参数定义条件连接类型。你还可以使用 db_or()、db_xor()(异或)、db_and() 等内置助手函数,通常这些已足够使用。示例:
<?php $query ->condition('field1', array(1, 2), 'IN') ->condition(db_or()->condition('field2', 5)->condition('field3', 6)); // 结果: // (field1 IN (:db_placeholder_1, :db_placeholder_2) AND (field2 = :db_placeholder_3 OR field3 = :db_placeholder_4)) ?>
NULL 值
用于检查 NULL 值的方法如下:
<?php $query->isNull('myfield'); // 结果: (myfield IS NULL) $query->isNotNull('myfield'); // 结果: (myfield IS NOT NULL) ?>
这些 isNull() 和 isNotNull() 方法可以与 where()、condition() 结合使用。
注意: 已弃用 condition('myfield', NULL)
的写法,应改用 isNull() 或 isNotNull()。
子查询
condition() 方法支持在 $value 中使用子查询。要实现子查询,可使用 db_select() 方法创建 SelectQuery 对象。然后将此对象传递给 condition() 方法的参数,而不是直接执行 select()。
子查询适合用于简短、单字段的条件查询。如果你的查询逻辑过于复杂,建议放弃 db_select() 方式,直接使用 condition()。
以下是子查询的示例:
db_delete()
<?php db_delete('sessions') ->condition('timestamp', REQUEST_TIME - $lifetime, '<') ->execute(); // DELETE FROM {sessions} WHERE (timestamp < 1228713473) ?>
db_update()
<?php db_update('sessions') ->fields(array( 'sid' => session_id() )) ->condition('sid', $old_session_id) ->execute(); // UPDATE {sessions} SET sid = 'abcde' WHERE (sid = 'fghij'); ?>
db_delete()
<?php // 来自 taxonomy_term_save() 示例: $or = db_or()->condition('tid1', 5)->condition('tid2', 6); db_delete('term_relation')->condition($or)->execute(); // DELETE FROM {term_relation} WHERE ((tid1 = 5 OR tid2 = 6)) ?>