logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

在 Drupal 7 中操作数据库 - 第12课 - 查询条件(WHERE、HAVING、LIKE)

14/10/2025, by Ivan

查询条件允许我们选择仅符合特定限制的记录,例如两周内创建的节点、名称中包含“Drupal”一词的术语等。在 SQL 中,我们使用 WHEREHAVING 来为 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 运算符是 INBETWEENIN 运算符仅匹配数组中任意一个精确值。

<?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))
?>