logo

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

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

演示 EBT 模块 下载 EBT 模块

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

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

演示 EPT 模块 滚动

滚动

在 Drupal 7 中操作数据库 - 第4课 - 动态查询(SELECT)

14/10/2025, by Ivan

我们终于来到了 Drupal Database API 中最有趣的部分:动态查询(Dynamic Queries)。之所以称为动态查询,是因为 Drupal 会动态地构建 SQL 查询语句。所有的插入(INSERT)、更新(UPDATE)、删除(DELETE)和合并(MERGE)查询都可以是动态的。SELECT 查询既可以是静态的,也可以是动态的,但在大多数情况下,推荐使用动态查询。

所有 动态查询 都是通过创建查询对象的方式生成的,我们可以在需要时对该对象进行操作。与静态查询类似,大多数动态查询也通过过程式封装函数(procedural wrapper)来执行。查询对象可以根据需要添加参数或条件。

db_select() 查询

动态 SELECT 查询从 db_select() 函数开始,例如:

<?php
$query = db_select('node', 'n', $options);
?>

在这个例子中,"node" 是表名(对应 SQL 中的 FROM 子句)。请注意,这里不需要使用花括号包裹表名,查询构造器会自动处理。第二个参数是表的别名(alias)。如果未提供,系统会使用表名作为别名。可选的 $options 数组与静态查询中的选项相同。

简单示例

<?php
$query = db_select('users', 'u');

$query
  ->condition('u.uid', 0, '<>')
  ->fields('u', array('uid', 'name', 'status', 'created', 'access'))
  ->range(0, 50);

$result = $query->execute();
?>

该示例等价于以下 SQL 语句:

SELECT uid, name, status, created, access FROM {users} u WHERE uid <> 0 LIMIT 50 OFFSET 0;

这是一个典型的用户管理页面查询示例。

表连接(JOIN)

可以通过以下方法实现表连接:join()innerJoin()leftJoin()rightJoin(),例如:

<?php
$table_alias = $query->join('user', 'u', 'n.uid = u.uid AND u.uid = :uid', array(':uid' => 5));
?>

上面的示例添加了一个 INNER JOIN(默认类型),连接了 “user” 表并将其命名为 "u"。JOIN 条件是 “n.uid = u.uid AND u.uid = :uid”,其中 :uid 的值为 5。使用占位符(placeholders)可以防止 SQL 注入攻击。innerJoin()、leftJoin() 和 rightJoin() 的语法和作用类似。

选择字段(addField / fields)

要向查询中添加字段,请使用 addField() 方法:

<?php
$title_field = $query->addField('n', 'title', 'my_title');
?>

上例中,我们从表别名 "n" 中选择字段 "title",并将其命名为 "my_title"。如果未提供别名,系统会自动生成一个。

若要一次添加多个字段,可使用 fields()

<?php
$query->fields('n', array('nid', 'title', 'created', 'uid'));
?>

该方法等价于多次调用 addField()。

DISTINCT 去重

若查询结果包含重复记录,可使用 distinct() 方法:

<?php
$query->distinct();
?>

请注意,DISTINCT 可能会增加查询负担,应谨慎使用。

表达式(addExpression)

可通过 addExpression() 添加 SQL 表达式(如 COUNT、SUM、SUBSTRING 等)。

<?php
$count_alias = $query->addExpression('COUNT(uid)', 'uid_count');
$count_alias = $query->addExpression('created - :offset', 'uid_count', array(':offset' => 3600));
?>

排序(ORDER BY)

<?php
$query->orderBy('title', 'DESC');
?>

默认排序为升序(ASC)。可多次调用以设置多字段排序。

随机排序(orderRandom)

<?php
$query->orderRandom();
?>

不同数据库的随机排序语法不同,因此应使用此方法动态生成。

分组(GROUP BY)

可使用 groupBy() 实现分组:

<?php
$query->groupBy('uid');
?>

限制输出(range)

可通过 range($start, $count) 限制结果数量:

<?php
$query->range(5, 10);
?>

此查询将从第6条记录开始,返回10条结果。

表格排序(extend('TableSort'))

<?php
$query = $query->extend('TableSort')->orderByHeader($header);
?>

条件(condition)

条件是一个复杂主题。SELECT 查询可以使用 WHERE 或 HAVING 条件:

  • condition() / where() — 对应 WHERE 子句。
  • havingCondition() / having() — 对应 HAVING 子句。

执行查询(execute)

调用 execute() 方法来执行查询:

<?php
$result = $query->execute();
foreach ($result as $record) {
  // 处理每一条记录
}
?>

结果统计(countQuery)

若需要统计结果数量,可使用 countQuery()

<?php
$num_rows = $query->countQuery()->execute()->fetchField();
?>

调试(Debug)

可使用 __toString() 输出最终生成的 SQL 语句:

<?php
print_r($query->__toString());
?>