SQLite3::createAggregate

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

SQLite3::createAggregate注册一个 PHP 函数以用作 SQL 聚合函数

说明

public SQLite3::createAggregate(
    string $name,
    callable $stepCallback,
    callable $finalCallback,
    int $argCount = -1
): bool

注册一个 PHP 函数或用户定义函数以用作 SQL 聚合函数,用于 SQL 语句中。

参数

name

要创建或重新定义的 SQL 聚合的名称。

stepCallback

针对结果集的每一行调用的回调函数。您的 PHP 函数应该累积结果并将其存储在聚合上下文中。

此函数需要定义为

step(
    mixed $context,
    int $rownumber,
    mixed $value,
    mixed ...$values
): mixed
context

对于第一行,是 null;在后续行中,它将具有之前从 step 函数返回的值;您应该使用它来维护聚合状态。

rownumber

当前行号。

value

传递给聚合的第一个参数。

values

传递给聚合的进一步参数。

此函数的返回值将用作 step 或 finalize 函数下次调用的 context 参数。

finalCallback

回调函数,用于聚合每一行的“步进”数据。一旦所有行都处理完毕,此函数将被调用,它应该获取聚合上下文中的数据并返回结果。此回调函数应该返回 SQLite 理解的类型(即 标量类型)。

此函数需要定义为

fini(mixed $context, int $rownumber): mixed
context

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

rownumber

始终是 0

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

argCount

SQL 聚合接受的参数数量。如果此参数为负,则 SQL 聚合可以接受任意数量的参数。

返回值

成功创建聚合后返回 true,失败时返回 false

示例

示例 #1 max_length 聚合函数示例

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

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

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

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

var_dump($db->querySingle('SELECT max_len(a) from strings'));
?>

上面的示例将输出

int(5)

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

处理完所有行后,SQLite 调用 max_len_finalize 函数来确定聚合结果。在这里,我们可以根据 $context 中找到的数据执行某种计算。然而,在我们简单的示例中,我们已经随着查询的进行计算了结果,因此我们只需要返回上下文的值。

提示

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

提示

您可以使用 SQLite3::createAggregate() 覆盖 SQLite 本地 SQL 函数。

添加注释

用户贡献的注释 2 个注释

boris dot dd at gmail dot com
7 年前
<?php
class Test extends SQLite3
{
public function
__construct($file)
{
parent::__construct($file);
$this->createAggregate('groupConcat', [$this, 'concatStep'], [$this, 'concatFinal']);
}
public function
concatStep(&$context, $rowId, $string, $delimiter)
{
if (!isset(
$context)) {
$context = [
'delimiter' => $delimiter,
'data' => []
];
}
$context['data'][] = $string;
return
$context;
}
public function
concatFinal(&$context)
{
return
implode($context['delimiter'], $context['data']);
}
}
$SQLite = new Test('/tmp/test.sqlite');
$SQLite->exec("create table `test` (`id` TEXT, `color` TEXT, `size` TEXT)");
$SQLite->exec("insert into `test` (`id`, `color`, `size`) values ('1', 'red', 'M')");
$SQLite->exec("insert into `test` (`id`, `color`, `size`) values ('1', 'green', 'M')");
$SQLite->exec("insert into `test` (`id`, `color`, `size`) values ('1', 'blue', 'S')");
$Result = $SQLite->query("select `size`, groupConcat(`color`, ';') as `color` from `test` group by `size`");
while (
$row = $Result->fetchArray(SQLITE3_ASSOC)) {
print_r($row);
}
/*
Array
(
[size] => M
[color] => red;green
)
Array
(
[size] => S
[color] => blue
)
*/
sukmaagungsaputra at gmail dot com
9 years ago
缺少示例,对吧?
让我们尝试为 SQlite3 提供类似 MySQL 的功能
- REGEXP 运算符,
- MD5 函数,以及
- GROUP_CONCAT 聚合函数

$db = new SQLite3($filename);
$db->createFunction('regexp', function ($a,$b) { return preg_match("/$a/i", $b); });
$db->createFunction('md5', function ($a) { return md5($a); });
$db->createAggregate ('group_concat',
function(&$context, $rownumber, $str) { $context[]=$str; return $context; },
function(&$context) {return implode(",", (array) $context); });
To Top