在 Drupal 7 中操作数据库 - 第4课 - 动态查询(SELECT)
我们终于来到了 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()); ?>