PHP Conference Japan 2024

Pdo\Sqlite::createAggregate

(PHP 8 >= 8.4.0)

Pdo\Sqlite::createAggregate 注册用于 SQL 语句的聚合用户自定义函数

描述

public Pdo\Sqlite::createAggregate(
    字符串 $name,
    可调用 $step,
    可调用 $finalize,
    整数 $numArgs = -1
): 布尔值

此方法类似于 Pdo\Sqlite::createFunction(),但它注册的函数可用于计算查询所有行中聚合的结果。

此方法与 Pdo\Sqlite::createFunction() 的主要区别在于,它需要两个函数来管理聚合。

提示

通过使用此方法,可以覆盖本机 SQL 函数。

参数

name
在 SQL 语句中使用的函数名称。
step
为结果集的每一行调用的回调函数。回调函数应累积结果并将其存储在聚合上下文中。

此函数需要定义为

step(
    混合 $context,
    整数 $rownumber,
    混合 $value,
    混合 ...$values
): 混合
context
对于第一行,null;在后续行中,它将具有先前从 step 函数返回的值;您应该使用它来维护聚合状态。
rownumber
当前行号。
value
传递给聚合的第一个参数。
values
传递给聚合的其他参数。
此函数的返回值将用作 step 或 finalize 函数下次调用的 context 参数。

finalize
回调函数,用于聚合来自每一行的“分步”数据。处理完所有行后,将调用此函数,然后它应获取聚合上下文中的数据并返回结果。此回调函数应返回 SQLite 理解的类型(即 标量类型)。

此函数需要定义为

fini(混合 $context, 整数 $rowcount): 混合
context

保存 step 函数最后一次调用的返回值。

rowcount

保存执行聚合的行数。

此函数的返回值将用作聚合的返回值。

numArgs
如果回调函数接受预定数量的参数,则提示 SQLite 解析器。

返回值

成功时返回 true,失败时返回 false

示例

示例 #1 Pdo\Sqlite::createAggregate() 示例

在此示例中,我们将创建一个名为 max_length 的自定义聚合函数,该函数可用于 SQL 查询。

在此示例中,我们创建了一个名为 max_length 的聚合函数,它将计算表中某一列中最长字符串的长度。对于每一行,都会调用 max_len_step 函数并传递一个 $context 参数。context 参数就像任何其他 PHP 变量一样,可以设置为保存一个 数组 甚至一个 对象。在此示例中,我们使用它来保存到目前为止我们看到的最大长度;如果 $string 的长度大于当前最大值,我们将更新上下文以保存此新的最大长度。

处理完所有行后,SQLite 会调用 max_len_finalize 函数来确定聚合结果。可以根据 $context 中的数据执行某种计算。在此基本示例中,结果是在查询进行过程中计算的,因此可以直接返回上下文值。

<?php
$data
= [
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
];
$db = new Pdo\Sqlite('sqlite::memory:');
$db->exec("CREATE TABLE strings(a)");
$insert = $db->prepare('INSERT INTO strings VALUES (?)');
foreach (
$data as $str) {
$insert->execute(array($str));
}
$insert = null;

function
max_len_step($context, $row_number, $string)
{
if (
strlen($string) > $context) {
$context = strlen($string);
}
return
$context;
}

function
max_len_finalize($context, $row_count)
{
return
$context === null ? 0 : $context;
}

$db->createAggregate('max_len', 'max_len_step', 'max_len_finalize');

var_dump($db->query('SELECT max_len(a) from strings')->fetchAll());

?>
提示

不建议您在上下文环境中存储值的副本,然后在最后处理它们,因为这会导致 SQLite 使用大量内存来处理查询——只需考虑一下,如果一百万行数据存储在内存中,每一行包含一个长度为 32 字节的字符串,您需要多少内存。

另请参阅

添加注释

用户贡献的注释

此页面没有用户贡献的注释。
To Top