logo

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

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

演示 EBT 模块 下载 EBT 模块

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

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

演示 EPT 模块 滚动

滚动

在 Drupal 7 中操作数据库 - 第8课 - 插入查询(INSERT INTO)

14/10/2025, by Ivan

插入查询应始终使用查询构造器(Query Builder)。某些数据库需要对 LOB(Large Object,例如 MySQL 中的 TEXT)和 BLOB(Binary Large Object)字段进行特殊处理,因此需要通过数据库抽象层为不同的数据库驱动实现相应的处理逻辑。

插入查询以函数 db_insert() 开始:

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

该插入查询会创建一个查询对象,用于向表 node 中插入一条或多条记录。请注意,不需要使用花括号包裹表名,查询构造器会自动处理。

插入查询使用 Fluent API(链式调用),这意味着所有方法(包括 execute())都会返回查询对象自身,从而可以连续调用多个方法。

插入查询支持多种模式以适应不同用途。通常,我们先定义要插入的字段,然后指定要插入的值。以下列出了常见的几种使用模式。

简洁模式(Compact form)

这是最常用、最推荐的插入方式:

<?php
$nid = db_insert('node')
  ->fields(array(
    'title' => 'Example',
    'uid' => 1,
    'created' => REQUEST_TIME,
  ))
  ->execute();
?>

该查询等价于以下 SQL 语句:

INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405);

上面的示例将字段键与对应的插入数据进行映射。

fields() 方法接受一个关联数组,键为数据库表字段名,值为对应要插入的数据。执行后,系统会自动生成 INSERT 语句。

<?php
  ->execute();
?>

与其他查询不同,execute() 在插入操作中会返回自增字段(auto-increment)的值。例如,对于 node 表,这将返回字段 nid 的值。如果表中没有自增字段,则返回值为 undefined(未定义),此时不应依赖该值。

基础模式(Degenerate form)

<?php
$nid = db_insert('node')
  ->fields(array('title', 'uid', 'created'))
  ->values(array(
    'title' => 'Example',
    'uid' => 1,
    'created' => REQUEST_TIME,
  ))
  ->execute();
?>

该示例与前一个功能相同,执行结果一致。

fields() 使用索引数组而非关联数组时,它仅定义要插入的字段(列名),不定义具体的值。随后通过 values() 方法提供插入数据。这种形式常用于多行插入(multi-insert)。

values() 方法可接受关联数组或索引数组。若为索引数组,值的顺序必须与 fields() 中字段顺序一致;若为关联数组,则顺序无关。由于关联数组更具可读性,因此通常推荐使用关联数组。

多行插入(Multi-insert form)

插入查询对象可以多次调用 values() 方法,以在单个事务中插入多条记录。多数数据库会自动优化该操作,在单一事务中执行以提高性能。在 MySQL 中,此操作相当于多值插入语法。

<?php
$values = array(
  array(
    'title' => 'Example',
    'uid' => 1,
    'created' => REQUEST_TIME,
  ),
  array(
    'title' => 'Example 2',
    'uid' => 1,
    'created' => REQUEST_TIME,
  ),
  array(
    'title' => 'Example 3',
    'uid' => 2,
    'created' => REQUEST_TIME,
  ),
);

$query = db_insert('node')->fields(array('title', 'uid', 'created'));
foreach ($values as $record) {
  $query->values($record);
}
$query->execute();
?>

上面的代码展示了如何一次性插入三条记录。通过将查询对象存入变量,我们可以在循环中多次调用 values() 方法。

该示例等价于执行以下三个 SQL 查询:

INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405);
INSERT INTO {node} (title, uid, created) VALUES ('Example 2', 1, 1221717405);
INSERT INTO {node} (title, uid, created) VALUES ('Example 3', 2, 1221717405);

请注意,在多行插入模式下,execute() 的返回值为 undefined,因为不同数据库驱动的返回行为不一致。

基于查询结果的插入(INSERT INTO ... SELECT)

如果你希望用其他表的数据填充新表(如生成汇总表),可以使用 INSERT INTO ... SELECT FROM 查询,而无需先在 PHP 中处理。

以下示例演示如何创建一个 “mytable” 表,其中包含所有节点的 nid 和用户名:

Drupal 6 版本:

<?php
db_query('INSERT INTO {mytable} (nid, name) SELECT n.nid, u.name FROM {node} n LEFT JOIN {users} u ON n.uid = u.uid WHERE n.type = "%s"', array('page'));
?>

Drupal 7 版本:

<?php
// 构建 SELECT 查询。
$query = db_select('node', 'n');
// 连接 users 表。
$query->join('users', 'u', 'n.uid = u.uid');
// 添加需要的字段。
$query->addField('n', 'nid');
$query->addField('u', 'name');
// 添加条件,只选择类型为 page 的节点。
$query->condition('type', 'page');

// 执行插入。
db_insert('mytable')
  ->from($query)
  ->execute();
?>

默认值(Default values)

通常情况下,如果未为某个字段定义值,而该字段在表结构中有默认值,则数据库会自动插入默认值。但在某些情况下,我们需要显式地告诉数据库使用默认值。例如,当你希望所有字段都使用其默认值时,可以调用 useDefaults() 方法:

<?php
$query->useDefaults(array('field1', 'field2'));
?>

此代码将强制查询为字段 field1field2 使用默认值。请注意,如果同一字段同时出现在 useDefaults()fields()values() 中,会导致错误。