# 查询构建器类

CodeIgniter 提供了查询构建器类。这种模式允许使用最少的脚本从数据库中检索、插入和更新信息。在某些情况下，只需一两行代码就能执行数据库操作。 CodeIgniter 不要求每个数据库表都有自己的类文件，而是提供了一个更简化的接口。

除了简单之外，使用查询构建器功能的一个主要好处是，它允许创建数据库无关的应用程序，因为查询语法是由每个数据库适配器生成的。它还允许更安全的查询，因为值由系统自动转义。

备注

CodeIgniter 不支持表名和字段名中的点（`.`）。 从 v4.5.0 开始，支持带点的数据库名称。

## SQL 注入保护

使用查询构建器生成 SQL 语句是相当安全的。然而，它并非被设计为，无论你传递什么数据都能防止 SQL 注入。

传递给查询构建器的参数可以是：

  1. 标识符，如字段名或表名

  2. 它们的 值

  3. SQL 字符串 的一部分

查询构建器默认会转义所有 值。

它还会默认尝试正确保护 标识符 和 SQL 字符串 中的标识符。 然而，它是为了在许多用例中良好工作而实现的，并不是设计用来防止所有攻击的。 因此，绝不应该在没有适当验证的情况下将用户输入传入其中。

此外，许多方法都有 `$escape` 参数，可以设置为禁用转义。 如果 `$escape` 设置为 false，查询构建器将不会提供任何保护， 因此你必须自己确保在将其传递给查询构建器之前， 它们已经被正确转义或保护。 使用 `RawSql` 时也是如此，它指定了一个原始 SQL 语句。

## 加载查询构建器

查询构建器通过数据库连接上的 `table()` 方法加载。这会为你设置查询的 FROM 部分， 并返回查询构建器类的新实例：

    <?php

    $db      = \Config\Database::connect();
    $builder = $db->table('users');

查询构建器仅在你明确请求该类时才加载到内存中，因此默认情况下不使用任何资源。

## 选择数据

以下方法允许构建 SQL SELECT 语句。

### Get

#### $builder->get()

运行选择查询并返回结果。可以单独使用检索表中的所有记录：

    <?php

    $builder = $db->table('mytable');
    $query   = $builder->get();  // Produces: SELECT * FROM mytable

第一个和第二个参数允许设置 limit 和 offset 子句：

    <?php

    $query = $builder->get(10, 20);
    /*
     * Executes: SELECT * FROM mytable LIMIT 20, 10
     * (in MySQL. Other databases have slightly different syntax)
     */

你会注意到上述方法被赋值给一个名为 $query 的变量，该变量可以用来显示结果：

    <?php

    $query = $builder->get();

    foreach ($query->getResult() as $row) {
        echo $row->title;
    }

请访问 getResult() 方法，获取关于结果生成的完整讨论。

#### $builder->getCompiledSelect()

编译选择查询，就像 `$builder->get()` 一样，但不 运行 查询。此方法只是将 SQL 查询作为字符串返回。

示例：

    <?php

    $sql = $builder->getCompiledSelect();
    echo $sql;
    // Prints string: SELECT * FROM mytable

下面第一个查询中的参数（false）允许设置是否重置查询构建器 （因为参数的默认值是 true，`getCompiledSelect(bool $reset = true)`，默认情况下它会像使用 `$builder->get()` 时一样被重置）：

    <?php

    echo $builder->limit(10, 20)->getCompiledSelect(false);
    /*
     * Prints string: SELECT * FROM mytable LIMIT 20, 10
     * (in MySQL. Other databases have slightly different syntax)
     */

    echo $builder->select('title, content, date')->getCompiledSelect();
    // Prints string: SELECT title, content, date FROM mytable LIMIT 20, 10

上述示例的关键点是，第二个查询没有 使用 `limit(10, 20)`，但生成的 SQL 查询却有 `LIMIT 20, 10`。 出现这种结果的原因是第一个查询中的参数设置为 `false`，`limit(10, 20)` 保留在第二个查询中。

#### $builder->getWhere()

与 `get()` 方法相同，只是它允许你在第一个参数中添加 "where" 子句，而不是使用 `$builder->where()` 方法：

    <?php

    $query = $builder->getWhere(['id' => $id], $limit, $offset);

请阅读下面的 `where()` 方法获取更多信息。

### Select

#### $builder->select()

允许编写查询的 SELECT 部分：

    <?php

    $builder->select('title, content, date');
    $query = $builder->get();
    // Executes: SELECT title, content, date FROM mytable

备注

如果从表中选择所有（`*`）字段，则不需要使用此方法。当省略时，CodeIgniter 假定你希望选择所有字段，并自动添加 `SELECT *`。

`$builder->select()` 接受一个可选的第二个参数。如果将其设置为 `false`，CodeIgniter 将不会尝试保护字段或表名。这在需要复合 select 语句且自动转义字段可能破坏它们时非常有用。

    <?php

    $builder->select('(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4) AS amount_paid', false);
    $query = $builder->get();

##### RawSql

Added in version 4.2.0.

从 v4.2.0 开始，`$builder->select()` 接受一个 `CodeIgniter\Database\RawSql` 实例，它表示原始 SQL 字符串。

    <?php

    use CodeIgniter\Database\RawSql;

    $sql = 'REGEXP_SUBSTR(ral_anno,"[0-9]{1,2}([,.][0-9]{1,3})([,.][0-9]{1,3})") AS ral';
    $builder->select(new RawSql($sql));
    $query = $builder->get();

警告

使用 `RawSql` 时，必须手动转义值并保护标识符。否则可能导致 SQL 注入。

#### $builder->selectMax()

为查询编写 SELECT MAX(field) 部分。可以选择包含第二个参数来重命名结果字段。

    <?php

    $builder->selectMax('age');
    $query = $builder->get();
    // Produces: SELECT MAX(age) as age FROM mytable

    $builder->selectMax('age', 'member_age');
    $query = $builder->get();
    // Produces: SELECT MAX(age) as member_age FROM mytable

#### $builder->selectMin()

为查询编写 SELECT MIN(field) 部分。与 `selectMax()` 一样，可以选择包含第二个参数来重命名结果字段。

    <?php

    $builder->selectMin('age');
    $query = $builder->get();
    // Produces: SELECT MIN(age) as age FROM mytable

#### $builder->selectAvg()

为查询编写 SELECT AVG(field) 部分。与 `selectMax()` 一样，可以选择包含第二个参数来重命名结果字段。

    <?php

    $builder->selectAvg('age');
    $query = $builder->get();
    // Produces: SELECT AVG(age) as age FROM mytable

#### $builder->selectSum()

为查询编写 SELECT SUM(field) 部分。与 `selectMax()` 一样，可以选择包含第二个参数来重命名结果字段。

    <?php

    $builder->selectSum('age');
    $query = $builder->get();
    // Produces: SELECT SUM(age) as age FROM mytable

#### $builder->selectCount()

为查询编写 SELECT COUNT(field) 部分。与 `selectMax()` 一样，可以选择包含第二个参数来重命名结果字段。

备注

此方法在与 `groupBy()` 一起使用时特别有用。对于一般性的结果计数，请参阅 `countAll()` 或 `countAllResults()`。

    <?php

    $builder->selectCount('age');
    $query = $builder->get();
    // Produces: SELECT COUNT(age) as age FROM mytable

#### $builder->selectSubquery()

向 SELECT 部分添加子查询。

    $subquery = $db->table('countries')->select('name')->where('id', 1);
    $builder  = $db->table('users')->select('name')->selectSubquery($subquery, 'country');
    $query    = $builder->get();
    // Produces: SELECT `name`, (SELECT `name` FROM `countries` WHERE `id` = 1) `country` FROM `users`

### From

#### $builder->from()

允许编写查询的 FROM 部分：

    <?php

    $builder = $db->table('users');
    $builder->select('title, content, date');
    $builder->from('mytable');
    $query = $builder->get();
    // Produces: SELECT title, content, date FROM users, mytable

备注

如前所示，查询的 FROM 部分可以在 `$db->table()` 方法中指定。对 `from()` 的额外调用将向查询的 FROM 部分添加更多表。

### 子查询

#### $builder->fromSubquery()

允许将 FROM 查询的一部分编写为子查询。

以下示例向现有表添加子查询：

    <?php

    $subquery = $db->table('users');
    $builder  = $db->table('jobs')->fromSubquery($subquery, 'alias');
    $query    = $builder->get();
    // Produces: SELECT * FROM `jobs`, (SELECT * FROM `users`) `alias`

使用 `$db->newQuery()` 方法使子查询成为主表：

    <?php

    $subquery = $db->table('users')->select('id, name');
    $builder  = $db->newQuery()->fromSubquery($subquery, 't');
    $query    = $builder->get();
    // Produces: SELECT * FROM (SELECT `id`, `name` FROM users) `t`

### Join

#### $builder->join()

允许编写查询的 JOIN 部分：

    <?php

    $builder = $db->table('blogs');
    $builder->select('*');
    $builder->join('comments', 'comments.id = blogs.id');
    $query = $builder->get();
    /*
     * Produces:
     * SELECT * FROM blogs JOIN comments ON comments.id = blogs.id
     */

如果在一个查询中需要多个连接，可以进行多次方法调用。

如果需要特定类型的 JOIN，可以通过方法的第三个参数指定。选项有：`left`、`right`、`outer`、`inner`、`left outer` 和 `right outer`。

    <?php

    $builder->join('comments', 'comments.id = blogs.id', 'left');
    // Produces: LEFT JOIN comments ON comments.id = blogs.id

##### RawSql

Added in version 4.2.0.

从 v4.2.0 开始，`$builder->join()` 接受一个 `CodeIgniter\Database\RawSql` 实例作为 JOIN ON 条件，它表示原始 SQL 字符串。

    <?php

    use CodeIgniter\Database\RawSql;

    $sql = 'user.id = device.user_id AND ((1=1 OR 1=1) OR (1=1 OR 1=1))';
    $builder->join('user', new RawSql($sql), 'LEFT');
    // Produces: LEFT JOIN "user" ON user.id = device.user_id AND ((1=1 OR 1=1) OR (1=1 OR 1=1))

警告

使用 `RawSql` 时，必须手动转义值并保护标识符。否则可能导致 SQL 注入。

## 查找特定数据

### Where

#### $builder->where()

此方法允许使用五种方式设置 WHERE 子句：

备注

传递给此方法的所有值都会自动转义， 产生更安全的查询，除非使用自定义字符串。

备注

`$builder->where()` 接受一个可选的第三个参数。如果将其设置为 `false`，CodeIgniter 将不会尝试保护字段或表名。

##### 1. 简单键/值方式

>     <?php

>     $builder->where('name', $name);
>     // Produces: WHERE name = 'Joe'

> 注意，等号会为你自动添加。

> 如果使用多个方法调用，它们将用 AND 连接在一起：

>     <?php

>     $builder->where('name', $name);
>     $builder->where('title', $title);
>     $builder->where('status', $status);
>     // WHERE name = 'Joe' AND title = 'boss' AND status = 'active'

##### 2. 自定义键/值方式

> 可以在第一个参数中包含运算符以控制比较：

>     <?php

>     $builder->where('name !=', $name);
>     $builder->where('id <', $id);
>     // Produces: WHERE name != 'Joe' AND id < 45

##### 3. 关联数组方式

>     <?php

>     $array = ['name' => $name, 'title' => $title, 'status' => $status];
>     $builder->where($array);
>     // Produces: WHERE name = 'Joe' AND title = 'boss' AND status = 'active'

> 也可以使用此方法包含自己的运算符：

>     <?php

>     $array = ['name !=' => $name, 'id <' => $id, 'date >' => $date];
>     $builder->where($array);

##### 4. 自定义字符串

> 可以手动编写自己的子句：

>     <?php

>     $where = "name='Joe' AND status='boss' OR status='active'";
>     $builder->where($where);

> 警告

> 如果在字符串中使用用户提供的数据，必须手动转义值并保护标识符。否则可能导致 SQL 注入。

>     <?php

>     $name  = $builder->db->escape('Joe');
>     $where = "name={$name} AND status='boss' OR status='active'";
>     $builder->where($where);

##### 5. RawSql

> Added in version 4.2.0.

> 从 v4.2.0 开始，`$builder->where()` 接受一个 `CodeIgniter\Database\RawSql` 实例，它表示原始 SQL 字符串。

>     <?php

>     use CodeIgniter\Database\RawSql;

>     $sql = "id > 2 AND name != 'Accountant'";
>     $builder->where(new RawSql($sql));

> 警告

> 使用 `RawSql` 时，必须手动转义值并保护标识符。否则可能导致 SQL 注入。

##### 6. 子查询

>     <?php

>     // With closure
>     use CodeIgniter\Database\BaseBuilder;

>     $builder->where('advance_amount <', static function (BaseBuilder $builder) {
>         $builder->select('MAX(advance_amount)', false)->from('orders')->where('id >', 2);
>     });
>     // Produces: WHERE "advance_amount" < (SELECT MAX(advance_amount) FROM "orders" WHERE "id" > 2)

>     // With builder directly
>     $subQuery = $db->table('orders')->select('MAX(advance_amount)', false)->where('id >', 2);
>     $builder->where('advance_amount <', $subQuery);

#### $builder->orWhere()

此方法与上述方法相同，只是多个实例通过 OR 连接：

    <?php

    $builder->where('name !=', $name);
    $builder->orWhere('id >', $id);
    // Produces: WHERE name != 'Joe' OR id > 50

#### $builder->whereIn()

生成一个 WHERE field IN ('item', 'item') SQL 查询，在适当时用 AND 连接：

    <?php

    $names = ['Frank', 'Todd', 'James'];
    $builder->whereIn('username', $names);
    // Produces: WHERE username IN ('Frank', 'Todd', 'James')

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->whereIn('id', static function (BaseBuilder $builder) {
        $builder->select('job_id')->from('users_jobs')->where('user_id', 3);
    });
    // Produces: WHERE "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3);
    $builder->whereIn('id', $subQuery);

#### $builder->orWhereIn()

生成一个 WHERE field IN ('item', 'item') SQL 查询，在适当时用 OR 连接：

    <?php

    $names = ['Frank', 'Todd', 'James'];
    $builder->orWhereIn('username', $names);
    // Produces: OR username IN ('Frank', 'Todd', 'James')

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->orWhereIn('id', static function (BaseBuilder $builder) {
        $builder->select('job_id')->from('users_jobs')->where('user_id', 3);
    });
    // Produces: OR "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3);
    $builder->orWhereIn('id', $subQuery);

#### $builder->whereNotIn()

生成一个 WHERE field NOT IN ('item', 'item') SQL 查询，在适当时用 AND 连接：

    <?php

    $names = ['Frank', 'Todd', 'James'];
    $builder->whereNotIn('username', $names);
    // Produces: WHERE username NOT IN ('Frank', 'Todd', 'James')

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->whereNotIn('id', static function (BaseBuilder $builder) {
        $builder->select('job_id')->from('users_jobs')->where('user_id', 3);
    });
    // Produces: WHERE "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3);
    $builder->whereNotIn('id', $subQuery);

#### $builder->orWhereNotIn()

生成一个 WHERE field NOT IN ('item', 'item') SQL 查询，在适当时用 OR 连接：

    <?php

    $names = ['Frank', 'Todd', 'James'];
    $builder->orWhereNotIn('username', $names);
    // Produces: OR username NOT IN ('Frank', 'Todd', 'James')

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->orWhereNotIn('id', static function (BaseBuilder $builder) {
        $builder->select('job_id')->from('users_jobs')->where('user_id', 3);
    });
    // Produces: OR "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3);
    $builder->orWhereNotIn('id', $subQuery);

## 查找相似数据

### Like

#### $builder->like()

此方法允许生成 LIKE 子句，用于执行搜索。

备注

传递给此方法的所有值都会自动转义。

备注

所有 `like*` 方法变体可以通过向方法传递第五个参数 `true` 来强制执行不区分大小写的搜索。这将使用平台特定的功能（如果可用），否则将强制值为小写，即 `WHERE LOWER(column) LIKE '%search%'`。这可能需要为 `LOWER(column)` 而不是 `column` 创建索引才能有效。

##### 1. 简单键/值方方式

>     <?php

>     $builder->like('title', 'match');
>     // Produces: WHERE `title` LIKE '%match%' ESCAPE '!'

> 如果使用多个方法调用，它们将用 AND 连接在一起：

>     <?php

>     $builder->like('title', 'match');
>     $builder->like('body', 'match');
>     // WHERE `title` LIKE '%match%' ESCAPE '!' AND  `body` LIKE '%match%' ESCAPE '!'

> 如需控制通配符（%）的位置，可使用可选的第三个参数。选项包括 `none`、`before`、`after` 以及 `both` （默认值）。

>     <?php

>     $builder->like('title', 'match', 'none');   // Produces: WHERE `title` LIKE 'match' ESCAPE '!'
>     $builder->like('title', 'match', 'before'); // Produces: WHERE `title` LIKE '%match' ESCAPE '!'
>     $builder->like('title', 'match', 'after');  // Produces: WHERE `title` LIKE 'match%' ESCAPE '!'
>     $builder->like('title', 'match', 'both');   // Produces: WHERE `title` LIKE '%match%' ESCAPE '!'

##### 2. 关联数组方式

>     <?php

>     $array = ['title' => $match, 'page1' => $match, 'page2' => $match];
>     $builder->like($array);
>     /*
>      * WHERE `title` LIKE '%match%' ESCAPE '!'
>      *     AND  `page1` LIKE '%match%' ESCAPE '!'
>      *     AND  `page2` LIKE '%match%' ESCAPE '!'
>      */

##### 3. RawSql

> Added in version 4.2.0.

> 从 v4.2.0 开始，`$builder->like()` 接受一个 `CodeIgniter\Database\RawSql` 实例，它表示原始 SQL 字符串。

>     <?php

>     use CodeIgniter\Database\RawSql;

>     $sql    = "CONCAT(users.name, ' ', IF(users.surname IS NULL OR users.surname = '', '', users.surname))";
>     $rawSql = new RawSql($sql);
>     $builder->like($rawSql, 'value', 'both');

> 警告

> 使用 `RawSql` 时，必须手动转义值并保护标识符。否则可能导致 SQL 注入。

#### $builder->orLike()

此方法与上述方法相同，只是多个实例通过 OR 连接：

    <?php

    $builder->like('title', 'match');
    $builder->orLike('body', $match);
    // WHERE `title` LIKE '%match%' ESCAPE '!' OR  `body` LIKE '%match%' ESCAPE '!'

#### $builder->notLike()

此方法与 `like()` 相同，只是它生成 NOT LIKE 语句：

    <?php

    $builder->notLike('title', 'match'); // WHERE `title` NOT LIKE '%match% ESCAPE '!'

#### $builder->orNotLike()

此方法与 `notLike()` 相同，只是多个实例通过 OR 连接：

    <?php

    $builder->like('title', 'match');
    $builder->orNotLike('body', 'match');
    // WHERE `title` LIKE '%match% OR  `body` NOT LIKE '%match%' ESCAPE '!'

#### $builder->groupBy()

允许编写查询的 GROUP BY 部分：

    <?php

    $builder->groupBy('title');
    // Produces: GROUP BY title

也可以传递多个值的数组：

    <?php

    $builder->groupBy(['title', 'date']);
    // Produces: GROUP BY title, date

#### $builder->distinct()

向查询添加 DISTINCT 关键字：

    <?php

    $builder->distinct();
    $builder->get();
    // Produces: SELECT DISTINCT * FROM mytable

#### $builder->having()

允许编写查询的 HAVING 部分。有 2 种可能的语法，1 个参数或 2 个参数：

    <?php

    $builder->having('user_id = 45'); // Produces: HAVING user_id = 45
    $builder->having('user_id', 45); // Produces: HAVING user_id = 45

也可以传递多个值的数组：

    <?php

    $builder->having(['title =' => 'My Title', 'id <' => $id]);
    // Produces: HAVING title = 'My Title', id < 45

如果使用的数据库由 CodeIgniter 负责转义值，可以通过传递可选的第三个参数并将其设置为 `false` 来防止内容被转义。

    <?php

    $builder->having('user_id', 45); // Produces: HAVING `user_id` = 45 in some databases such as MySQL
    $builder->having('user_id', 45, false); // Produces: HAVING user_id = 45

#### $builder->orHaving()

与 `having()` 相同，只是用 OR 分隔多个子句。

#### $builder->havingIn()

生成一个 HAVING field IN ('item', 'item') SQL 查询，在适当时用 AND 连接：

    <?php

    $groups = [1, 2, 3];
    $builder->havingIn('group_id', $groups);
    // Produces: HAVING group_id IN (1, 2, 3)

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->havingIn('id', static function (BaseBuilder $builder) {
        $builder->select('user_id')->from('users_jobs')->where('group_id', 3);
    });
    // Produces: HAVING "id" IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3);
    $builder->havingIn('id', $subQuery);

#### $builder->orHavingIn()

生成一个 HAVING field IN ('item', 'item') SQL 查询，在适当时用 OR 连接：

    <?php

    $groups = [1, 2, 3];
    $builder->orHavingIn('group_id', $groups);
    // Produces: OR group_id IN (1, 2, 3)

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->orHavingIn('id', static function (BaseBuilder $builder) {
        $builder->select('user_id')->from('users_jobs')->where('group_id', 3);
    });
    // Produces: OR "id" IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3);
    $builder->orHavingIn('id', $subQuery);

#### $builder->havingNotIn()

生成一个 HAVING field NOT IN ('item', 'item') SQL 查询，在适当时用 AND 连接：

    <?php

    $groups = [1, 2, 3];
    $builder->havingNotIn('group_id', $groups);
    // Produces: HAVING group_id NOT IN (1, 2, 3)

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->havingNotIn('id', static function (BaseBuilder $builder) {
        $builder->select('user_id')->from('users_jobs')->where('group_id', 3);
    });
    // Produces: HAVING "id" NOT IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3);
    $builder->havingNotIn('id', $subQuery);

#### $builder->orHavingNotIn()

生成一个 HAVING field NOT IN ('item', 'item') SQL 查询，在适当时用 OR 连接：

    <?php

    $groups = [1, 2, 3];
    $builder->havingNotIn('group_id', $groups);
    // Produces: OR group_id NOT IN (1, 2, 3)

可以使用子查询代替值数组：

    <?php

    // With closure
    use CodeIgniter\Database\BaseBuilder;

    $builder->orHavingNotIn('id', static function (BaseBuilder $builder) {
        $builder->select('user_id')->from('users_jobs')->where('group_id', 3);
    });
    // Produces: OR "id" NOT IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3)

    // With builder directly
    $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3);
    $builder->orHavingNotIn('id', $subQuery);

#### $builder->havingLike()

此方法允许为查询的 HAVING 部分生成 LIKE 子句，用于执行搜索。

备注

传递给此方法的所有值都会自动转义。

备注

所有 `havingLike*()` 方法变体可以通过向方法传递第五个参数 `true` 来强制执行不区分大小写的搜索。这将使用平台特定的功能（如果可用），否则将强制值为小写，即 `HAVING LOWER(column) LIKE '%search%'`。这可能需要为 `LOWER(column)` 而不是 `column` 创建索引才能有效。

##### 1. 简单键/值方式

>     <?php

>     $builder->havingLike('title', 'match');
>     // Produces: HAVING `title` LIKE '%match%' ESCAPE '!'

> 如果使用多个方法调用，它们将用 AND 连接在一起：

>     <?php

>     $builder->havingLike('title', 'match');
>     $builder->havingLike('body', 'match');
>     // HAVING `title` LIKE '%match%' ESCAPE '!' AND  `body` LIKE '%match% ESCAPE '!'

> 如果想控制通配符（%）放置的位置，可以使用可选的第三个参数。选项有 `before`、`after` 和 `both` （默认）。

>     <?php

>     $builder->havingLike('title', 'match', 'before'); // Produces: HAVING `title` LIKE '%match' ESCAPE '!'
>     $builder->havingLike('title', 'match', 'after');  // Produces: HAVING `title` LIKE 'match%' ESCAPE '!'
>     $builder->havingLike('title', 'match', 'both');   // Produces: HAVING `title` LIKE '%match%' ESCAPE '!'

##### 2. 关联数组方式

>     <?php

>     $array = ['title' => $match, 'page1' => $match, 'page2' => $match];
>     $builder->havingLike($array);
>     /*
>      *  HAVING `title` LIKE '%match%' ESCAPE '!'
>      *      AND  `page1` LIKE '%match%' ESCAPE '!'
>      *      AND  `page2` LIKE '%match%' ESCAPE '!'
>      */

#### $builder->orHavingLike()

此方法与上述方法相同，只是多个实例通过 OR 连接：

    <?php

    $builder->havingLike('title', 'match');
    $builder->orHavingLike('body', $match);
    // HAVING `title` LIKE '%match%' ESCAPE '!' OR  `body` LIKE '%match%' ESCAPE '!'

#### $builder->notHavingLike()

此方法与 `havingLike()` 相同，只是它生成 NOT LIKE 语句：

    <?php

    $builder->notHavingLike('title', 'match');
    // HAVING `title` NOT LIKE '%match% ESCAPE '!'

#### $builder->orNotHavingLike()

此方法与 `notHavingLike()` 相同，只是多个实例通过 OR 连接：

    <?php

    $builder->havingLike('title', 'match');
    $builder->orNotHavingLike('body', 'match');
    // HAVING `title` LIKE '%match% OR  `body` NOT LIKE '%match%' ESCAPE '!'

## 排序结果

### OrderBy

#### $builder->orderBy()

允许设置 ORDER BY 子句。

第一个参数包含要排序的字段名。

第二个参数允许设置结果的排序方式。 选项有 `ASC`、`DESC` 和 `RANDOM`。

    <?php

    $builder->orderBy('title', 'DESC');
    // Produces: ORDER BY `title` DESC

也可以在第一个参数中传递自己的字符串：

    <?php

    $builder->orderBy('title DESC, name ASC');
    // Produces: ORDER BY `title` DESC, `name` ASC

如果需要多个字段，可以进行多次方法调用。

    <?php

    $builder->orderBy('title', 'DESC');
    $builder->orderBy('name', 'ASC');
    // Produces: ORDER BY `title` DESC, `name` ASC

如果选择 `RANDOM` 方向选项，则将忽略第一个参数，除非指定数字种子值。

    <?php

    $builder->orderBy('title', 'RANDOM');
    // Produces: ORDER BY RAND()

    $builder->orderBy(42, 'RANDOM');
    // Produces: ORDER BY RAND(42)

## 限制或计数结果

### Limit

#### $builder->limit()

允许限制查询返回的行数：

    <?php

    $builder->limit(10);
    // Produces: LIMIT 10

备注

如果在 SQL 语句中指定 `LIMIT 0`，将返回 0 条记录。 然而，查询构建器中有一个错误，如果指定 `limit(0)`， 生成的 SQL 语句将没有 `LIMIT` 子句，所有记录都将被返回。为了修复此错误行为，在 v4.5.0 中添加了一个设置。参见 limit(0) 行为 了解详细信息。此错误行为将在未来版本中修复，因此建议更改默认设置。

第二个参数允许设置结果偏移量。

    <?php

    $builder->limit(10, 20);
    // Produces: LIMIT 20, 10 (in MySQL. Other databases have slightly different syntax)

#### $builder->countAllResults()

允许确定特定查询构建器查询中的行数。支持查询构建器的限制条件，如 `where()`、`orWhere()`、`like()`、`orLike()` 等。示例：

    <?php

    echo $builder->countAllResults(); // Produces an integer, like 25
    $builder->like('title', 'match');
    $builder->from('my_table');
    echo $builder->countAllResults(); // Produces an integer, like 17

然而，此方法还会重置你可能已传递给 `select()` 的任何字段值。如果需要保留它们，可以将 `false` 作为第一个参数传递。

    <?php

    echo $builder->countAllResults(false); // Produces an integer, like 17

#### $builder->countAll()

允许确定特定表中的行数。示例：

    <?php

    echo $builder->countAll(); // Produces an integer, like 25

与 `countAllResult()` 方法一样，此方法也会重置你可能已传递给 `select()` 的字段值。如果需要保留它们，可以将 `false` 作为第一个参数传递。

## 联合查询

### Union

#### $builder->union()

用于组合两个或多个 SELECT 语句的结果集。它将只返回唯一的结果。

    <?php

    $builder = $db->table('users')->select('id, name')->limit(10);
    $union   = $db->table('groups')->select('id, name');
    $builder->union($union)->get();
    /*
     * Produces:
     * SELECT * FROM (SELECT `id`, `name` FROM `users` LIMIT 10) uwrp0
     * UNION SELECT * FROM (SELECT `id`, `name` FROM `groups`) uwrp1
     */

备注

为了与 DBMS（如 MSSQL 和 Oracle）正常工作，查询被包装在 `SELECT * FROM ( ... ) alias` 中。 主查询将始终具有别名 `uwrp0`。通过 `union()` 添加的每个后续查询将具有别名 `uwrpN+1`。

所有联合查询都将在主查询之后添加，无论 `union()` 方法的调用顺序如何。 也就是说，`limit()` 或 `orderBy()` 方法将相对于主查询，即使在 `union()` 之后调用也是如此。

在某些情况下，可能需要对查询结果进行排序或限制记录数。 解决方案是使用通过 `$db->newQuery()` 创建的包装器。 在下面的示例中，我们获取前 5 个用户 + 最后 5 个用户，并按 id 对结果进行排序：

    <?php

    $union   = $db->table('users')->select('id, name')->orderBy('id', 'DESC')->limit(5);
    $builder = $db->table('users')->select('id, name')->orderBy('id', 'ASC')->limit(5)->union($union);

    $db->newQuery()->fromSubquery($builder, 'q')->orderBy('id', 'DESC')->get();
    /*
     * Produces:
     * SELECT * FROM (
     *      SELECT * FROM (SELECT `id`, `name` FROM `users` ORDER BY `id` ASC LIMIT 5) uwrp0
     *      UNION
     *      SELECT * FROM (SELECT `id`, `name` FROM `users` ORDER BY `id` DESC LIMIT 5) uwrp1
     * ) q ORDER BY `id` DESC
     */

#### $builder->unionAll()

行为与 `union()` 方法相同。然而，将返回所有结果，而不仅仅是唯一的结果。

## 查询分组

### Group

查询分组允许通过将 WHERE 子句括在括号中来创建 WHERE 子句组。这样就可以创建具有复杂 WHERE 子句的查询。支持嵌套分组。示例：

    <?php

    $builder->select('*')->from('my_table')
        ->groupStart()
            ->where('a', 'a')
            ->orGroupStart()
                ->where('b', 'b')
                ->where('c', 'c')
            ->groupEnd()
        ->groupEnd()
        ->where('d', 'd')
        ->get();
    /*
     * Generates:
     * SELECT * FROM (`my_table`) WHERE ( `a` = 'a' OR ( `b` = 'b' AND `c` = 'c' ) ) AND `d` = 'd'
     */

备注

分组需要平衡，确保每个 `groupStart()` 都有对应的 `groupEnd()`。

#### $builder->groupStart()

通过向查询的 WHERE 子句添加左括号来开始新组。

#### $builder->orGroupStart()

通过向查询的 WHERE 子句添加左括号来开始新分组，前缀为 OR。

#### $builder->notGroupStart()

通过向查询的 WHERE 子句添加左括号来开始新分组，前缀为 NOT。

#### $builder->orNotGroupStart()

通过向查询的 WHERE 子句添加左括号来开始新分组，前缀为 OR NOT。

#### $builder->groupEnd()

通过向查询的 WHERE 子句添加右括号来结束当前组。

#### $builder->havingGroupStart()

通过向查询的 HAVING 子句添加左括号来开始新组。

#### $builder->orHavingGroupStart()

通过向查询的 HAVING 子句添加左括号来开始新分组，前缀为 OR。

#### $builder->notHavingGroupStart()

通过向查询的 HAVING 子句添加左括号来开始新分组，前缀为 NOT。

#### $builder->orNotHavingGroupStart()

通过向查询的 HAVING 子句添加左括号来开始新分组，前缀为 OR NOT。

#### $builder->havingGroupEnd()

通过向查询的 HAVING 子句添加右括号来结束当前分组。

## 插入数据

### 插入

#### $builder->insert()

根据提供的数据生成插入字符串并运行查询。可以向方法传递 数组 或 对象。以下是使用数组的示例：

    <?php

    use CodeIgniter\Database\RawSql;

    $data = [
        'id'          => new RawSql('DEFAULT'),
        'title'       => 'My title',
        'name'        => 'My Name',
        'date'        => '2022-01-01',
        'last_update' => new RawSql('CURRENT_TIMESTAMP()'),
    ];

    $builder->insert($data);
    /* Produces:
        INSERT INTO mytable (id, title, name, date, last_update)
        VALUES (DEFAULT, 'My title', 'My name', '2022-01-01', CURRENT_TIMESTAMP())
    */

第一个参数是值的关联数组。

备注

除 `RawSql` 外的所有值都会自动转义，生成更安全的查询。

警告

使用 `RawSql` 时，必须手动转义数据。否则可能导致 SQL 注入。

以下是使用对象的示例：

    <?php

    namespace App\Libraries;

    class MyClass
    {
        public $title   = 'My Title';
        public $content = 'My Content';
        public $date    = 'My Date';
    }

    <?php

    use App\Libraries\MyClass;

    $object = new MyClass();
    $builder->insert($object);
    // Produces: INSERT INTO mytable (title, content, date) VALUES ('My Title', 'My Content', 'My Date')

第一个参数是对象。

#### $builder->ignore()

根据提供的数据生成插入忽略字符串并运行查询。如果已存在具有相同主键的条目，则不会插入该查询。 可以选择向方法传递 布尔值。也可以用于 insertBatch、update 和 delete （在支持时）。 以下是使用上述示例数组的示例：

    <?php

    $data = [
        'title' => 'My title',
        'name'  => 'My Name',
        'date'  => 'My date',
    ];

    $builder->ignore(true)->insert($data);
    // Produces: INSERT OR IGNORE INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')

#### $builder->getCompiledInsert()

像 `$builder->insert()` 一样编译插入查询，但不 运行 查询。此方法只是将 SQL 查询作为字符串返回。

示例：

    <?php

    $data = [
        'title' => 'My title',
        'name'  => 'My Name',
        'date'  => 'My date',
    ];

    $sql = $builder->set($data)->getCompiledInsert();
    echo $sql;
    // Produces string: INSERT INTO mytable (`title`, `name`, `date`) VALUES ('My title', 'My name', 'My date')

第一个参数允许设置是否重置查询构建器查询 （默认情况下它会像 `$builder->insert()` 一样被重置）：

    <?php

    echo $builder->set('title', 'My Title')->getCompiledInsert(false);
    // Produces string: INSERT INTO mytable (`title`) VALUES ('My Title')

    echo $builder->set('content', 'My Content')->getCompiledInsert();
    // Produces string: INSERT INTO mytable (`title`, `content`) VALUES ('My Title', 'My Content')

第二个查询有效的原因是第一个参数设置为 `false`。

备注

此方法不适用于批量插入。

### insertBatch

#### $builder->insertBatch()

##### 从数据插入

根据提供的数据生成插入字符串并运行查询。可以向方法传递 数组 或 对象。以下是使用数组的示例：

    <?php

    $data = [
        [
            'title' => 'My title',
            'name'  => 'My Name',
            'date'  => 'My date',
        ],
        [
            'title' => 'Another title',
            'name'  => 'Another Name',
            'date'  => 'Another date',
        ],
    ];

    $builder->insertBatch($data);
    /*
     * Produces:
     * INSERT INTO mytable (title, name, date)
     *      VALUES ('My title', 'My name', 'My date'),
     *      ('Another title', 'Another name', 'Another date')
     */

第一个参数是值的关联数组。

备注

除 `RawSql` 外的所有值都会自动转义，生成更安全的查询。

警告

使用 `RawSql` 时，必须手动转义数据。否则可能导致 SQL 注入。

##### 从查询插入

也可以从查询插入：

    <?php

    use CodeIgniter\Database\RawSql;

    $query = 'SELECT user2.name, user2.email, user2.country
              FROM user2
              LEFT JOIN user ON user.email = user2.email
              WHERE user.email IS NULL';

    $sql = $builder
        ->ignore(true)
        ->setQueryAsData(new RawSql($query), null, 'name, country, email')
        ->insertBatch();
    /* MySQLi produces:
        INSERT IGNORE INTO `db_user` (`name`, `country`, `email`)
        SELECT user2.name, user2.email, user2.country
        FROM user2
        LEFT JOIN user ON user.email = user2.email
        WHERE user.email IS NULL
    */

备注

从 v4.3.0 开始可以使用 `setQueryAsData()`。

备注

需要为选择查询的字段设置别名以匹配目标表的字段。

## Upsert 数据

### Upsert

#### $builder->upsert()

Added in version 4.3.0.

根据提供的数据生成 upsert 字符串并运行查询。可以向方法传递 数组 或 对象。默认情况下，约束将按顺序定义。将首先选择主键，然后选择唯一键。MySQL 默认将使用任何约束。以下是使用数组的示例：

    <?php

    $data = [
        'email'   => 'ahmadinejad@example.com',
        'name'    => 'Ahmadinejad',
        'country' => 'Iran',
    ];

    $builder->upsert($data);
    // MySQLi  produces: INSERT INTO.. ON DUPLICATE KEY UPDATE..
    // Postgre produces: INSERT INTO.. ON CONFLICT.. DO UPDATE..
    // SQLite3 produces: INSERT INTO.. ON CONFLICT.. DO UPDATE..
    // SQLSRV  produces: MERGE INTO.. WHEN MATCHED THEN UPDATE.. WHEN NOT MATCHED THEN INSERT..
    // OCI8    produces: MERGE INTO.. WHEN MATCHED THEN UPDATE.. WHEN NOT MATCHED THEN INSERT..

备注

对于 MySQL 之外的数据库，如果表有多个键（主键或唯一键）， 在处理约束时默认将优先考虑主键。如果希望 使用不同的唯一键而不是主键，请使用 `onConstraint()` 方法。

第一个参数是值的关联数组。

以下是使用对象的示例：

    <?php

    namespace App\Libraries;

    class MyClass
    {
        public $email   = 'ahmadinejad@example.com';
        public $name    = 'Ahmadinejad';
        public $country = 'Iran';
    }

    <?php

    use App\Libraries\MyClass;

    $object = new MyClass();
    $builder->upsert($object);

第一个参数是对象。

备注

所有值都会自动转义，生成更安全的查询。

#### $builder->getCompiledUpsert()

Added in version 4.3.0.

像 `$builder->upsert()` 一样编译 upsert 查询，但不 运行 查询。此方法只是将 SQL 查询作为字符串返回。

示例：

    <?php

    $data = [
        'email'   => 'ahmadinejad@example.com',
        'name'    => 'Ahmadinejad',
        'country' => 'Iran',
    ];

    $sql = $builder->setData($data)->getCompiledUpsert();
    echo $sql;
    /* MySQLi produces:
        INSERT INTO `db_user` (`country`, `email`, `name`)
        VALUES ('Iran','ahmadinejad@example.com','Ahmadinejad')
        ON DUPLICATE KEY UPDATE
        `country` = VALUES(`country`),
        `email` = VALUES(`email`),
        `name` = VALUES(`name`)
    */

备注

此方法不适用于批量 upsert。

### upsertBatch

#### $builder->upsertBatch()

Added in version 4.3.0.

##### 从数据 Upsert

根据提供的数据生成 upsert 字符串并运行查询。可以向方法传递 数组 或 对象。默认情况下，约束将按顺序定义。将首先选择主键，然后选择唯一键。MySQL 默认将使用任何约束。

以下是使用数组的示例：

    <?php

    $data = [
        [
            'id'      => 2,
            'email'   => 'ahmadinejad@example.com',
            'name'    => 'Ahmadinejad',
            'country' => 'Iran',
        ],
        [
            'id'      => null,
            'email'   => 'pedro@example.com',
            'name'    => 'Pedro',
            'country' => 'El Salvador',
        ],
    ];

    $builder->upsertBatch($data);
    // MySQLi  produces: INSERT INTO.. ON DUPLICATE KEY UPDATE..
    // Postgre produces: INSERT INTO.. ON CONFLICT.. DO UPDATE..
    // SQLite3 produces: INSERT INTO.. ON CONFLICT.. DO UPDATE..
    // SQLSRV  produces: MERGE INTO.. WHEN MATCHED THEN UPDATE.. WHEN NOT MATCHED THEN INSERT..
    // OCI8    produces: MERGE INTO.. WHEN MATCHED THEN UPDATE.. WHEN NOT MATCHED THEN INSERT..

第一个参数是值的关联数组。

备注

所有值都会自动转义，生成更安全的查询。

##### 从查询 Upsert

也可以从查询进行 upsert：

    <?php

    use CodeIgniter\Database\RawSql;

    $query = $this->db->table('user2')
        ->select('user2.name, user2.email, user2.country')
        ->join('user', 'user.email = user2.email', 'left')
        ->where('user.email IS NULL');

    $additionalUpdateField = ['updated_at' => new RawSql('CURRENT_TIMESTAMP')];

    $sql = $builder->setQueryAsData($query)
        ->onConstraint('email')
        ->updateFields($additionalUpdateField, true)
        ->upsertBatch();
    /* MySQLi produces:
        INSERT INTO `db_user` (`country`, `email`, `name`)
        SELECT user2.name, user2.email, user2.country
        FROM user2
        LEFT JOIN user ON user.email = user2.email
        WHERE user.email IS NULL
        ON DUPLICATE KEY UPDATE
        `country` = VALUES(`country`),
        `email` = VALUES(`email`),
        `name` = VALUES(`name`),
        `updated_at` = CURRENT_TIMESTAMP
    */

备注

从 v4.3.0 开始可以使用 `setQueryAsData()`、`onConstraint()` 和 `updateFields()` 方法。

备注

需要为选择查询的字段设置别名以匹配目标表的字段。

#### $builder->onConstraint()

Added in version 4.3.0.

允许手动设置用于 upsert 的约束。这不适用于 MySQL，因为 MySQL 默认检查所有约束。

    <?php

    $data = [
        'id'      => 2,
        'email'   => 'ahmadinejad@example.com',
        'name'    => 'Ahmadinejad',
        'country' => 'Iran',
    ];

    $builder->onConstraint('email')->upsert($data);
    /* Postgre produces:
        INSERT INTO "db_user"("country", "email", "id", "name")
        VALUES ('Iran','ahmadinejad@example.com',2,'Ahmadinejad')
        ON CONFLICT("email")
        DO UPDATE SET
        "country" = "excluded"."country",
        "id" = "excluded"."id",
        "name" = "excluded"."name"
    */

此方法接受字符串或字段数组。

#### $builder->updateFields()

Added in version 4.3.0.

允许手动设置执行 upsert 时要更新的字段。

    <?php

    $data = [
        'id'      => 2,
        'email'   => 'ahmadinejad@example.com',
        'name'    => 'Ahmadinejad Zaghari',
        'country' => 'Afghanistan',
    ];

    $builder->updateFields('name, country')->setData($data, null, '_upsert')->upsert();
    /* SQLSRV produces:
        MERGE INTO "test"."dbo"."db_user"
        USING (
         VALUES ('Iran','ahmadinejad@example.com',2,'Ahmadinejad')
        ) "_upsert" ("country", "email", "id", "name")
        ON ("test"."dbo"."db_user"."id" = "_upsert"."id")
        WHEN MATCHED THEN UPDATE SET
        "country" = "_upsert"."country",
        "name" = "_upsert"."name"
        WHEN NOT MATCHED THEN INSERT ("country", "email", "id", "name")
        VALUES ("_upsert"."country", "_upsert"."email", "_upsert"."id", "_upsert"."name");
    */

此方法接受字符串、字段数组或 RawSql。还可以指定要更新的额外字段，该字段不包含在数据集中。 可以通过将第二个参数设置为 `true` 来完成此操作。

    <?php

    use CodeIgniter\Database\RawSql;

    $data = [
        [
            'id'      => 2,
            'email'   => 'ahmadinejad@example.com',
            'name'    => 'Ahmadinejad',
            'country' => 'Iran',
        ],
        [
            'id'      => null,
            'email'   => 'pedro@example.com',
            'name'    => 'Pedro',
            'country' => 'El Salvador',
        ],
    ];

    $additionalUpdateField = ['updated_at' => new RawSql('CURRENT_TIMESTAMP')];

    $sql = $builder->setData($data)->updateFields($additionalUpdateField, true)->upsertBatch();
    /* MySQLi produces:
        INSERT INTO `db_user` (`country`, `email`, `name`)
        VALUES ('Iran','ahmadinejad@example.com','Ahmadinejad'),('El Salvador','pedro@example.com','Pedro')
        ON DUPLICATE KEY UPDATE
        `country` = VALUES(`country`),
        `email` = VALUES(`email`),
        `name` = VALUES(`name`),
        `updated_at` = CURRENT_TIMESTAMP
    */

注意，`updated_at` 字段未插入，但在更新时使用。

## 更新数据

### 更新

#### $builder->replace()

此方法执行 REPLACE 语句，这基本上是 SQL 标准中的（可选） DELETE + INSERT，使用 主键 和 唯一键 作为决定条件。 在我们的情况下，它将使你无需实现复杂的 逻辑，无需使用 `select()`、`update()`、 `delete()` 和 `insert()` 调用的各种组合。

示例：

    <?php

    $data = [
        'title' => 'My title',
        'name'  => 'My Name',
        'date'  => 'My date',
    ];

    $builder->replace($data);
    // Executes: REPLACE INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')

在上述示例中，如果我们假设 `title` 字段是主键， 那么如果一行包含 `My title` 作为 `title` 值，该行将被删除， 我们的新行数据将替换它。

也允许使用 `set()` 方法，所有值都会自动转义，就像使用 `insert()` 一样。

#### $builder->set()

此方法允许为插入或更新设置值。

它可以用来代替直接向 insert() 或 update() 方法传递数据数组：

    <?php

    $builder->set('name', $name);
    $builder->insert();
    // Produces: INSERT INTO mytable (`name`) VALUES ('{$name}')

如果使用多个方法调用，它们将根据你是执行插入还是更新来正确组装：

    <?php

    $builder->set('name', $name);
    $builder->set('title', $title);
    $builder->set('status', $status);
    $builder->insert();

`set()` 还将接受可选的第三个参数（`$escape`），如果设置为 `false`，将防止值被转义。为了说明区别，以下是使用和不使用转义参数的 `set()`。

    <?php

    $builder->set('field', 'field+1', false);
    $builder->where('id', 2);
    $builder->update();
    // gives UPDATE mytable SET field = field+1 WHERE `id` = 2

    $builder->set('field', 'field+1');
    $builder->where('id', 2);
    $builder->update();
    // gives UPDATE `mytable` SET `field` = 'field+1' WHERE `id` = 2

也可以向此方法传递关联数组：

    <?php

    $array = [
        'name'   => $name,
        'title'  => $title,
        'status' => $status,
    ];

    $builder->set($array);
    $builder->insert();

或对象：

    <?php

    namespace App\Libraries;

    class MyClass
    {
        public $title   = 'My Title';
        public $content = 'My Content';
        public $date    = 'My Date';
    }

    <?php

    use App\Libraries\MyClass;

    $object = new MyClass();
    $builder->set($object);
    $builder->insert();

#### $builder->update()

生成 update 字符串并根据提供的数据运行查询。可以向方法传递 数组 或 对象。以下是使用数组的示例：

    <?php

    $data = [
        'title' => $title,
        'name'  => $name,
        'date'  => $date,
    ];

    $builder->where('id', $id);
    $builder->update($data);
    /*
     * Produces:
     * UPDATE mytable
     * SET title = '{$title}', name = '{$name}', date = '{$date}'
     * WHERE id = $id
     */

或可以提供对象：

    <?php

    namespace App\Libraries;

    class MyClass
    {
        public $title   = 'My Title';
        public $content = 'My Content';
        public $date    = 'My Date';
    }

    <?php

    use App\Libraries\MyClass;

    $object = new MyClass();
    $builder->where('id', $id);
    $builder->update($object);
    /*
     * Produces:
     * UPDATE `mytable`
     * SET `title` = '{$title}', `content` = '{$content}', `date` = '{$date}'
     * WHERE id = `$id`
     */

备注

除 `RawSql` 外的所有值都会自动转义，生成更安全的查询。

警告

使用 `RawSql` 时，必须手动转义数据。否则可能导致 SQL 注入。

你会注意到使用了 `$builder->where()` 方法，允许设置 WHERE 子句。可以选择将此信息直接作为字符串传递到 `update()` 方法中：

    <?php

    $builder->update($data, 'id = 4');

或作为数组：

    <?php

    $builder->update($data, ['id' => $id]);

执行更新时也可以使用上述的 `$builder->set()` 方法。

#### $builder->getCompiledUpdate()

这与 `$builder->getCompiledInsert()` 的工作方式完全相同，只是它生成 UPDATE SQL 字符串而不是 INSERT SQL 字符串。

有关更多信息，请查看 $builder->getCompiledInsert() 的文档。

备注

此方法不适用于批量更新。

### UpdateBatch

#### $builder->updateBatch()

备注

从 v4.3.0 开始，`updateBatch()` 的第二个参数 `$index` 已 更改为 `$constraints`。它现在接受数组、字符串或 `RawSql` 类型。

##### 从数据更新

根据提供的数据生成 update 字符串并运行查询。可以向方法传递 数组 或 对象。以下是使用数组的示例：

    <?php

    $data = [
        [
            'title'  => 'Title 1',
            'author' => 'Author 1',
            'name'   => 'Name 1',
            'date'   => 'Date 1',
        ],
        [
            'title'  => 'Title 2',
            'author' => 'Author 2',
            'name'   => 'Name 2',
            'date'   => 'Date 2',
        ],
    ];
    $builder->updateBatch($data, ['title', 'author']);
    /*
     * Produces:
     * UPDATE `mytable`
     * INNER JOIN (
     * SELECT 'Title 1' `title`, 'Author 1' `author`, 'Name 1' `name`, 'Date 1' `date` UNION ALL
     * SELECT 'Title 2' `title`, 'Author 2' `author`, 'Name 2' `name`, 'Date 2' `date`
     * ) `u`
     * ON `mytable`.`title` = `u`.`title` AND `mytable`.`author` = `u`.`author`
     * SET
     * `mytable`.`title` = `u`.`title`,
     * `mytable`.`name` = `u`.`name`,
     * `mytable`.`date` = `u`.`date`
     */

第一个参数是值的关联数组，第二个参数是 where 键。

备注

从 v4.3.0 开始，生成的 SQL 结构已得到改进。

从 v4.3.0 开始，还可以使用 `onConstraint()` 和 `updateFields()` 方法：

    <?php

    use CodeIgniter\Database\RawSql;

    $builder->setData($data)->onConstraint('title, author')->updateBatch();

    // OR
    $builder->setData($data, null, 'u')
        ->onConstraint(['`mytable`.`title`' => '`u`.`title`', 'author' => new RawSql('`u`.`author`')])
        ->updateBatch();

    // OR
    foreach ($data as $row) {
        $builder->setData($row);
    }
    $builder->onConstraint('title, author')->updateBatch();

    // OR
    $builder->setData($data, true, 'u')
        ->onConstraint(new RawSql('`mytable`.`title` = `u`.`title` AND `mytable`.`author` = `u`.`author`'))
        ->updateFields(['last_update' => new RawSql('CURRENT_TIMESTAMP()')], true)
        ->updateBatch();
    /*
     * Produces:
     * UPDATE `mytable`
     * INNER JOIN (
     * SELECT 'Title 1' `title`, 'Author 1' `author`, 'Name 1' `name`, 'Date 1' `date` UNION ALL
     * SELECT 'Title 2' `title`, 'Author 2' `author`, 'Name 2' `name`, 'Date 2' `date`
     * ) `u`
     * ON `mytable`.`title` = `u`.`title` AND `mytable`.`author` = `u`.`author`
     * SET
     * `mytable`.`title` = `u`.`title`,
     * `mytable`.`name` = `u`.`name`,
     * `mytable`.`date` = `u`.`date`,
     * `mytable`.`last_update` = CURRENT_TIMESTAMP() // this only applies to the last scenario
     */

备注

除 `RawSql` 外的所有值都会自动转义，生成更安全的查询。

警告

使用 `RawSql` 时，必须手动转义数据。否则可能导致 SQL 注入。

备注

因为工作原理的原因，若使用此方法则 `affectedRows()` 无法提供正确的结果。相反，`updateBatch()` 返回受影响的行数。

##### 从查询更新

从 v4.3.0 开始，还可以使用 `setQueryAsData()` 方法从查询更新：

    <?php

    use CodeIgniter\Database\RawSql;

    $query = $this->db->table('user2')
        ->select('user2.name, user2.email, user2.country')
        ->join('user', 'user.email = user2.email', 'inner')
        ->where('user2.country', 'US');

    $additionalUpdateField = ['updated_at' => new RawSql('CURRENT_TIMESTAMP')];

    $sql = $builder->table('user')
        ->setQueryAsData($query, null, 'u')
        ->onConstraint('email')
        ->updateFields($additionalUpdateField, true)
        ->updateBatch();
    /*
     * Produces:
     * UPDATE `user`
     * INNER JOIN (
     * SELECT user2.name, user2.email, user2.country
     * FROM user2
     * INNER JOIN user ON user.email = user2.email
     * WHERE user2.country = 'US'
     * ) `u`
     * ON `user`.`email` = `u`.`email`
     * SET
     * `mytable`.`name` = `u`.`name`,
     * `mytable`.`email` = `u`.`email`,
     * `mytable`.`country` = `u`.`country`,
     * `mytable`.`updated_at` = CURRENT_TIMESTAMP()
     */

备注

需要为 select 查询的字段设置别名以匹配目标表的字段。

## 删除数据

### 删除

#### $builder->delete()

生成 DELETE SQL 字符串并运行查询。

    <?php

    $builder->delete(['id' => $id]);
    // Produces: DELETE FROM mytable WHERE id = $id

第一个参数是 where 子句。 也可以使用 `where()` 或 `orWhere()` 方法，而不是将数据传递给方法的第一个参数：

    <?php

    $builder->where('id', $id);
    $builder->delete();
    /*
     * Produces:
     * DELETE FROM mytable
     * WHERE id = $id
     */

如果要删除表中的所有数据，可以使用 `truncate()` 方法或 `emptyTable()`。

#### $builder->getCompiledDelete()

这与 `$builder->getCompiledInsert()` 的工作方式完全相同，只是它生成 DELETE SQL 字符串而不是 INSERT SQL 字符串。

有关更多信息，请查看 $builder->getCompiledInsert() 的文档。

### DeleteBatch

#### $builder->deleteBatch()

Added in version 4.3.0.

##### 从数据删除

基于一组数据生成批量 DELETE 语句。

    <?php

    $data = [
        [
            'order'   => 48372,
            'line'    => 3,
            'product' => 'Keyboard',
            'qty'     => 1,
        ],
        [
            'order'   => 48372,
            'line'    => 4,
            'product' => 'Mouse',
            'qty'     => 1,
        ],
        [
            'order'   => 48372,
            'line'    => 5,
            'product' => 'Monitor',
            'qty'     => 2,
        ],
    ];

    $builder->setData($data, true, 'del')
        ->onConstraint('order, line')
        ->where('del.qty >', 1)
        ->deleteBatch();

    /*
     * MySQL Produces:
     * DELETE `order_line` FROM `order_line`
     * INNER JOIN (
     * SELECT 3 `line`, 48372 `order`, 'Keyboard' `product`, 1 `qty` UNION ALL
     * SELECT 4 `line`, 48372 `order`, 'Mouse'    `product`, 1 `qty` UNION ALL
     * SELECT 5 `line`, 48372 `order`, 'Monitor'  `product`, 2 `qty`
     * ) `del`
     * ON `order_line`.`order` = `del`.`order` AND `order_line`.`line` = `del`.`line`
     * WHERE `del`.`qty` > 1
     */

此方法在删除具有复合主键的表中的数据时可能特别有用。

备注

SQLite3 不支持使用 `where()`。

##### 从查询删除

也可以从查询删除：

    <?php

    use CodeIgniter\Database\RawSql;

    $query = $this->db->table('user2')->select('email, name, country')->where('country', 'Greece');

    $this->db->table('user')
        ->setQueryAsData($query, 'alias')
        ->onConstraint('email')
        ->where('alias.name = user.name')
        ->deleteBatch();

    /* MySQLi produces:
        DELETE `user` FROM `user`
        INNER JOIN (
        SELECT `email`, `name`, `country`
        FROM `user2`
        WHERE `country` = 'Greece') `alias`
        ON `user`.`email` = `alias`.`email`
        WHERE `alias`.`name` = `user`.`name`
    */

#### $builder->emptyTable()

生成 DELETE SQL 字符串并运行查询：

    <?php

    $builder->emptyTable('mytable');
    // Produces: DELETE FROM mytable

#### $builder->truncate()

生成 TRUNCATE SQL 字符串并运行查询。

    <?php

    $builder->truncate();
    /*
     * Produce:
     * TRUNCATE mytable
     */

备注

如果 TRUNCATE 命令不可用，`truncate()` 将执行为 "DELETE FROM table"。

## 条件语句

### When

#### $builder->when()

Added in version 4.3.0.

这允许基于条件修改查询，而无需中断查询构建器链。第一个参数是条件，它使用 PHP 的原生布尔逻辑进行评估——这意味着像 `false`、`null`、 `0`、`'0'`、`0.0`、空字符串 `''` 和空数组 `[]` 这样的值将被视为 false。 第二个参数是在条件为 true 时将运行的回调函数。

例如，你可能只希望根据 HTTP 请求中发送的值应用给定的 WHERE 语句：

    <?php

    $status = service('request')->getPost('status');

    $users = $this->db->table('users')
        ->when($status, static function ($query, $status) {
            $query->where('status', $status);
        })
        ->get();

由于条件被评估为 `true`，将调用回调函数。条件中设置的值将作为第二个参数传递给回调函数，以便在查询中使用。

有时你可能希望在条件评估为 false 时应用不同的语句。 这可以通过提供第二个闭包来实现：

    <?php

    $onlyInactive = service('request')->getPost('return_inactive');

    $users = $this->db->table('users')
        ->when($onlyInactive, static function ($query, $onlyInactive) {
            $query->where('status', 'inactive');
        }, static function ($query) {
            $query->where('status', 'active');
        })
        ->get();

### WhenNot

#### $builder->whenNot()

Added in version 4.3.0.

这与 `$builder->when()` 的工作方式完全相同，只是它只会在条件评估为 `false` 时运行回调函数，而不是像 `when()` 那样在 `true` 时运行。

    <?php

    $status = service('request')->getPost('status');

    $users = $this->db->table('users')
        ->whenNot($status, static function ($query, $status) {
            $query->where('active', 0);
        })
        ->get();

## 方法链

方法链允许通过连接多个方法来简化语法。考虑此示例：

    <?php

    $query = $builder->select('title')
        ->where('id', $id)
        ->limit(10, 20)
        ->get();

## 重置查询构建器

### ResetQuery

#### $builder->resetQuery()

重置查询构建器允许在不先使用 `$builder->get()` 或 `$builder->insert()` 等方法执行查询的情况下重新开始。

这在以下情况下很有用：使用查询构建器生成 SQL （例如，`$builder->getCompiledSelect()`），但之后选择运行查询：

    <?php

    // Note that the parameter of the `getCompiledSelect()` method is false
    $sql = $builder->select(['field1', 'field2'])
        ->where('field3', 5)
        ->getCompiledSelect(false);

    // ...
    // Do something crazy with the SQL code... like add it to a cron script for
    // later execution or something...
    // ...

    $data = $builder->get()->getResultArray();
    /*
     * Would execute and return an array of results of the following query:
     * SELECT field1, field2 FROM mytable WHERE field3 = 5;
     */

## 类参考

class CodeIgniter\Database\BaseBuilder
  db()
    返回:

      正在使用的数据库连接

    返回类型:

      `ConnectionInterface`

    从 `$db` 返回当前数据库连接。用于访问查询构建器无法直接使用的 `ConnectionInterface` 方法，如 `insertID()` 或 `errors()`。

  resetQuery()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    重置当前查询构建器状态。当你想构建一个在某些条件下可以取消的查询时很有用。

  countAllResults([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置 SELECT 的值

    返回:

      查询结果中的行数

    返回类型:

      `int`

    生成特定于平台的查询字符串，用于计算查询构建器查询返回的所有记录数。

  countAll([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置 SELECT 的值

    返回:

      查询结果中的行数

    返回类型:

      `int`

    生成特定于平台的查询字符串，用于计算特定表中的所有记录数。

  get([$limit = null[, $offset = null[, $reset = true]]]])
    参数:

      - $limit (`int`) -- LIMIT 子句

      - $offset (`int`) -- OFFSET 子句

      - $reset (`bool`) -- 是否要清除查询构建器的值？

    返回:

      `\CodeIgniter\Database\ResultInterface` 实例（方法链）

    返回类型:

      `\CodeIgniter\Database\ResultInterface`

    根据已调用的查询构建器方法编译并运行 `SELECT` 语句。

  getWhere([$where = null[, $limit = null[, $offset = null[, $reset = true]]]]])
    参数:

      - $where (`string`) -- WHERE 子句

      - $limit (`int`) -- LIMIT 子句

      - $offset (`int`) -- OFFSET 子句

      - $reset (`bool`) -- 是否要清除查询构建器的值？

    返回:

      `\CodeIgniter\Database\ResultInterface` 实例（方法链）

    返回类型:

      `\CodeIgniter\Database\ResultInterface`

    与 `get()` 相同，但还允许直接添加 WHERE 子句。

  select([$select = '*'[, $escape = null]])
    参数:

      - $select (`array|RawSql|string`) -- 查询的 SELECT 部分

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT` 子句。

  selectAvg([$select = ''[, $alias = '']])
    参数:

      - $select (`string`) -- 要计算平均值的字段

      - $alias (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT AVG(field)` 子句。

  selectMax([$select = ''[, $alias = '']])
    参数:

      - $select (`string`) -- 要计算最大值的字段

      - $alias (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT MAX(field)` 子句。

  selectMin([$select = ''[, $alias = '']])
    参数:

      - $select (`string`) -- 要计算最小值的字段

      - $alias (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT MIN(field)` 子句。

  selectSum([$select = ''[, $alias = '']])
    参数:

      - $select (`string`) -- 要计算总和的字段

      - $alias (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT SUM(field)` 子句。

  selectCount([$select = ''[, $alias = '']])
    参数:

      - $select (`string`) -- 要计算平均值的字段

      - $alias (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `SELECT COUNT(field)` 子句。

  selectSubquery(BaseBuilder $subquery, string $as)
    参数:

      - $subquery (`string`) -- BaseBuilder 实例

      - $as (`string`) -- 结果值名称的别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向选择中添加子查询。

  distinct([$val = true])
    参数:

      - $val (`bool`) -- "distinct" 标志的期望值

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    设置一个标志，告诉查询构建器向查询的 `SELECT` 部分添加 `DISTINCT` 子句。

  from($from[, $overwrite = false])
    参数:

      - $from (`mixed`) -- 表名；字符串或数组

      - $overwrite (`bool`) -- 是否移除现有的第一个表？

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    指定查询的 `FROM` 子句。

  fromSubquery($from, $alias)
    参数:

      - $from (`BaseBuilder`) -- BaseBuilder 类的实例

      - $alias (`string`) -- 子查询别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    使用子查询指定查询的 `FROM` 子句。

  setQueryAsData($query[, $alias[, $columns = null]])

    Added in version 4.3.0.

    参数:

      - $query (`BaseBuilder|RawSql`) -- BaseBuilder 或 RawSql 的实例

      - $alias (`string|null`) -- 查询的别名

      - $columns (`array|string|null`) -- 查询中字段的数组或逗号分隔的字符串

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    将查询设置为 `insertBatch()`、`updateBatch()`、`upsertBatch()` 的数据源。 如果 `$columns` 为 null，则将运行查询以生成字段名。

  join($table, $cond[, $type = ''[, $escape = null]])
    参数:

      - $table (`string`) -- 要连接的表名

      - $cond (`string|RawSql`) -- JOIN ON 条件

      - $type (`string`) -- JOIN 类型

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `JOIN` 子句。从 v4.2.0 开始，`RawSql` 可以用作 JOIN ON 条件。另请参见 $builder->join()。

  where($key[, $value = null[, $escape = null]])
    参数:

      - $key (`array|RawSql|string`) -- 要比较的字段名，或关联数组

      - $value (`mixed`) -- 如果是单个键，则与此值比较

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成查询的 `WHERE` 部分。用 `AND` 分隔多个调用。

  orWhere($key[, $value = null[, $escape = null]])
    参数:

      - $key (`mixed`) -- 要比较的字段名，或关联数组

      - $value (`mixed`) -- 如果是单个键，则与此值比较

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成查询的 `WHERE` 部分。用 `OR` 分隔多个调用。

  orWhereIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要搜索的字段

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `WHERE` 字段 `IN('item', 'item')` SQL 查询，在适当时用 `OR` 连接。

  orWhereNotIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要搜索的字段

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `WHERE` 字段 `NOT IN('item', 'item')` SQL 查询，在适当时用 `OR` 连接。

  whereIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要检查的字段名

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `WHERE` 字段 `IN('item', 'item')` SQL 查询，在适当时用 `AND` 连接。

  whereNotIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要检查的字段名

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `WHERE` 字段 `NOT IN('item', 'item')` SQL 查询，在适当时用 `AND` 连接。

  groupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始一个组表达式，对其内部的条件使用 `AND`。

  orGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始一个组表达式，对其内部的条件使用 `OR`。

  notGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始一个组表达式，对其内部的条件使用 `AND NOT`。

  orNotGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始一个组表达式，对其内部的条件使用 `OR NOT`。

  groupEnd()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    结束一个组表达式。

  like($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`array|RawSql|string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `LIKE` 子句，用 `AND` 分隔多个调用。

  orLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `LIKE` 子句，用 `OR` 分隔多个调用。

  notLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `NOT LIKE` 子句，用 `AND` 分隔多个调用。

  orNotLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `NOT LIKE` 子句，用 `OR` 分隔多个调用。

  having($key[, $value = null[, $escape = null]])
    参数:

      - $key (`mixed`) -- 标识符（字符串）或字段/值对的关联数组

      - $value (`string`) -- 如果 $key 是标识符，则为要查找的值

      - $escape (`string`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `HAVING` 子句，用 `AND` 分隔多个调用。

  orHaving($key[, $value = null[, $escape = null]])
    参数:

      - $key (`mixed`) -- 标识符（字符串）或字段/值对的关联数组

      - $value (`string`) -- 如果 $key 是标识符，则为要查找的值

      - $escape (`string`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `HAVING` 子句，用 `OR` 分隔多个调用。

  orHavingIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要搜索的字段

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `HAVING` 字段 IN('item', 'item') SQL 查询，在适当时用 `OR` 连接。

  orHavingNotIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要搜索的字段

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `HAVING` 字段 `NOT IN('item', 'item')` SQL 查询，在适当时用 `OR` 连接。

  havingIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要检查的字段名

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `HAVING` 字段 `IN('item', 'item')` SQL 查询，在适当时用 `AND` 连接。

  havingNotIn([$key = null[, $values = null[, $escape = null]]])
    参数:

      - $key (`string`) -- 要检查的字段名

      - $values (`array|BaseBulder|Closure`) -- 目标值数组，或用于子查询的匿名函数

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    生成 `HAVING` 字段 `NOT IN('item', 'item')` SQL 查询，在适当时用 `AND` 连接。

  havingLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询的 `HAVING` 部分添加 `LIKE` 子句，用 `AND` 分隔多个调用。

  orHavingLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询的 `HAVING` 部分添加 `LIKE` 子句，用 `OR` 分隔多个调用。

  notHavingLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

      - $insensitiveSearch (`bool`) -- 是否强制执行不区分大小写的搜索

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询的 `HAVING` 部分添加 `NOT LIKE` 子句，用 `AND` 分隔多个调用。

  orNotHavingLike($field[, $match = ''[, $side = 'both'[, $escape = null[, $insensitiveSearch = false]]]])
    参数:

      - $field (`string`) -- 字段名

      - $match (`string`) -- 要匹配的文本部分

      - $side (`string`) -- 在表达式的哪一侧放置 '%' 通配符

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询的 `HAVING` 部分添加 `NOT LIKE` 子句，用 `OR` 分隔多个调用。

  havingGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始 `HAVING` 子句的组表达式，对其内部的条件使用 `AND`。

  orHavingGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始 `HAVING` 子句的组表达式，对其内部的条件使用 `OR`。

  notHavingGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始 `HAVING` 子句的组表达式，对其内部的条件使用 `AND NOT`。

  orNotHavingGroupStart()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    开始 `HAVING` 子句的组表达式，对其内部的条件使用 `OR NOT`。

  havingGroupEnd()
    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    结束 `HAVING` 子句的组表达式。

  groupBy($by[, $escape = null])
    参数:

      - $by (`mixed`) -- 要分组的字段；字符串或数组

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `GROUP BY` 子句。

  orderBy($orderby[, $direction = ''[, $escape = null]])
    参数:

      - $orderby (`string`) -- 要排序的字段

      - $direction (`string`) -- 请求的排序顺序 - ASC、DESC 或 random

      - $escape (`bool`) -- 是否转义值和标识符

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `ORDER BY` 子句。

  limit($value[, $offset = 0])
    参数:

      - $value (`int`) -- 要限制结果的行数

      - $offset (`int`) -- 要跳过的行数

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `LIMIT` 和 `OFFSET` 子句。

  offset($offset)
    参数:

      - $offset (`int`) -- 要跳过的行数

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    向查询添加 `OFFSET` 子句。

  union($union)
    参数:

      - $union (`BaseBulder|Closure`) -- 联合查询

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    添加 `UNION` 子句。

  unionAll($union)
    参数:

      - $union (`BaseBulder|Closure`) -- 联合查询

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    添加 `UNION ALL` 子句。

  set($key[, $value = ''[, $escape = null]])
    参数:

      - $key (`mixed`) -- 字段名，或字段/值对的数组

      - $value (`mixed`) -- 字段值，如果 $key 是单个字段

      - $escape (`bool`) -- 是否转义值

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    添加字段/值对，稍后传递给 `insert()`、`update()` 或 `replace()`。

  insert([$set = null[, $escape = null]])
    参数:

      - $set (`array`) -- 字段/值对的关联数组

      - $escape (`bool`) -- 是否转义值

    返回:

      成功时返回 `true`，失败时返回 `false`

    返回类型:

      `bool`

    编译并执行 `INSERT` 语句。

  insertBatch([$set = null[, $escape = null[, $batch_size = 100]]])
    参数:

      - $set (`array`) -- 要插入的数据

      - $escape (`bool`) -- 是否转义值

      - $batch_size (`int`) -- 一次插入的行数

    返回:

      插入的行数，如果没有数据执行插入操作则返回 `false`

    返回类型:

      `int|false`

    编译并执行批量 `INSERT` 语句。

    备注

    当提供超过 `$batch_size` 行时，将执行多个 `INSERT` 查询，每个查询尝试插入 最多 `$batch_size` 行。

  setInsertBatch($key[, $value = ''[, $escape = null]])

    自 4.3.0 版本弃用: 使用 `CodeIgniter\Database\BaseBuilder::setData()` 代替。

    参数:

      - $key (`mixed`) -- 字段名或字段/值对的数组

      - $value (`string`) -- 字段值，如果 $key 是单个字段

      - $escape (`bool`) -- 是否转义值

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    添加字段/值对，稍后通过 `insertBatch()` 插入到表中。

    重要

    此方法已弃用。将在未来版本中删除。

  upsert([$set = null[, $escape = null]])
    参数:

      - $set (`array`) -- 字段/值对的关联数组

      - $escape (`bool`) -- 是否转义值

    返回:

      成功时返回 `true`，失败时返回 `false`

    返回类型:

      `bool`

    编译并执行 `UPSERT` 语句。

  upsertBatch([$set = null[, $escape = null[, $batch_size = 100]]])
    参数:

      - $set (`array`) -- 要 upsert 的数据

      - $escape (`bool`) -- 是否转义值

      - $batch_size (`int`) -- 一次 upsert 的行数

    返回:

      upsert 的行数，失败时返回 `false`

    返回类型:

      `int|false`

    编译并执行批量 `UPSERT` 语句。

    备注

    MySQL 使用 `ON DUPLICATE KEY UPDATE`，每行的受影响行数值 如果行作为新行插入则为 1，如果现有行被更新则为 2， 如果现有行被设置为其当前值则为 0。

    备注

    当提供超过 `$batch_size` 行时，将执行多个 `UPSERT` 查询，每个查询尝试 upsert 最多 `$batch_size` 行。

  update([$set = null[, $where = null[, $limit = null]]])
    参数:

      - $set (`array`) -- 字段/值对的关联数组

      - $where (`string`) -- WHERE 子句

      - $limit (`int`) -- LIMIT 子句

    返回:

      成功时返回 `true`，失败时返回 `false`

    返回类型:

      `bool`

    编译并执行 `UPDATE` 语句。

  updateBatch([$set = null[, $constraints = null[, $batchSize = 100]]])
    参数:

      - $set (`array|object|null`) -- 字段名，或字段/值对的关联数组

      - $constraints (`array|RawSql|string|null`) -- 用作更新键的字段或字段

      - $batchSize (`int`) -- 在单个查询中分组的条件数

    返回:

      更新的行数，失败时返回 `false`

    返回类型:

      `int|false`

    备注

    从 v4.3.0 开始，参数 `$set` 和 `$constraints` 的类型已更改。

    编译并执行批量 `UPDATE` 语句。 `$constraints` 参数接受逗号分隔的字段字符串、数组、关联数组或 `RawSql`。

    备注

    当提供超过 `$batchSize` 个字段/值对时， 将执行多个查询，每个查询处理最多 `$batchSize` 个字段/值对。如果我们将 `$batchSize` 设置为 0， 则所有字段/值对将在一个查询中执行。

  updateFields($set[, $addToDefault = false[, $ignore = null]])

    Added in version 4.3.0.

    参数:

      - $set (`mixed`) -- 行或行数组，行是数组或对象

      - $addToDefault (`bool`) -- 添加比数据集中更多的字段

      - $ignore (`bool`) -- 从 $set 中忽略的字段数组

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    与 `updateBatch()` 和 `upsertBatch()` 方法一起使用。这定义了将被更新的字段。

  onConstraint($set)

    Added in version 4.3.0.

    参数:

      - $set (`mixed`) -- 用作键或约束的字段或字段集

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    与 `updateBatch()` 和 `upsertBatch()` 方法一起使用。这接受逗号分隔的字段字符串、数组、关联数组或 RawSql。

  setData($set[, $escape = null[, $alias = '']])

    Added in version 4.3.0.

    参数:

      - $set (`mixed`) -- 行或行数组，行是数组或对象

      - $escape (`bool`) -- 是否转义值

      - $alias (`bool`) -- 数据集的表别名

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    用于 `*Batch()` 方法设置插入、更新、upsert 的数据。

  setUpdateBatch($key[, $value = ''[, $escape = null]])

    自 4.3.0 版本弃用: 使用 `CodeIgniter\Database\BaseBuilder::setData()` 代替。

    参数:

      - $key (`mixed`) -- 字段名或字段/值对的数组

      - $value (`string`) -- 字段值，如果 $key 是单个字段

      - $escape (`bool`) -- 是否转义值

    返回:

      `BaseBuilder` 实例（方法链）

    返回类型:

      `BaseBuilder`

    添加字段/值对，稍后通过 `updateBatch()` 更新表中的数据。

    重要

    此方法已弃用。将在未来版本中删除。

  replace([$set = null])
    参数:

      - $set (`array`) -- 字段/值对的关联数组

    返回:

      成功时返回 `true`，失败时返回 `false`

    返回类型:

      `bool`

    编译并执行 `REPLACE` 语句。

  delete([$where = ''[, $limit = null[, $reset_data = true]]])
    参数:

      - $where (`string`) -- WHERE 子句

      - $limit (`int`) -- LIMIT 子句

      - $reset_data (`bool`) -- 是否重置查询的"写入"子句

    返回:

      `BaseBuilder` 实例（方法链）或失败时返回 `false`

    返回类型:

      `BaseBuilder|false`

    编译并执行 `DELETE` 查询。

  deleteBatch([$set = null[, $constraints = null[, $batchSize = 100]]])
    参数:

      - $set (`array|object|null`) -- 字段名，或字段/值对的关联数组

      - $constraints (`array|RawSql|string|null`) -- 用作删除键的字段或字段

      - $batchSize (`int`) -- 在单个查询中分组的条件数

    返回:

      删除的行数，失败时返回 `false`

    返回类型:

      `int|false`

    编译并执行批量 `DELETE` 查询。

  increment($column[, $value = 1])
    参数:

      - $column (`string`) -- 要递增的字段名

      - $value (`int`) -- 字段中递增的数量

    将字段的值按指定数量递增。如果字段 不是数字字段，如 `VARCHAR`，它可能会被替换 为 `$value`。

  decrement($column[, $value = 1])
    参数:

      - $column (`string`) -- 要递减的字段名

      - $value (`int`) -- 递减的数量

    将字段的值按指定数量递减。如果字段 不是数字字段，如 `VARCHAR`，它可能会被替换 为 `$value`。

  truncate()
    返回:

      成功时返回 `true`，失败时返回 `false`，测试模式下返回字符串

    返回类型:

      `bool|string`

    在表上执行 `TRUNCATE` 语句。

    备注

    如果使用的数据库平台不支持 `TRUNCATE`， 将使用 `DELETE` 语句代替。

  emptyTable()
    返回:

      成功时返回 `true`，失败时返回 `false`

    返回类型:

      `bool`

    通过 `DELETE` 语句从表中删除所有记录。

  getCompiledSelect([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置当前 QB 值

    返回:

      编译后的 SQL 语句字符串

    返回类型:

      `string`

    编译 `SELECT` 语句并将其作为字符串返回。

  getCompiledInsert([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置当前 QB 值

    返回:

      编译后的 SQL 语句字符串

    返回类型:

      `string`

    编译 `INSERT` 语句并将其作为字符串返回。

  getCompiledUpdate([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置当前 QB 值

    返回:

      编译后的 SQL 语句字符串

    返回类型:

      `string`

    编译 `UPDATE` 语句并将其作为字符串返回。

  getCompiledDelete([$reset = true])
    参数:

      - $reset (`bool`) -- 是否重置当前 QB 值

    返回:

      编译后的 SQL 语句字符串

    返回类型:

      `string`

    编译 `DELETE` 语句并将其作为字符串返回。