PHP Conference Japan 2024

pg_send_query

(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

pg_send_query 发送异步查询

描述

pg_send_query(PgSql\Connection $connection, string $query): int|bool

pg_send_query() 将查询或查询异步发送到 connection。与 pg_query() 不同,它可以一次将多个查询发送到 PostgreSQL 并使用 pg_get_result() 一次获取一个结果。

在查询执行期间,脚本执行不会被阻塞。使用 pg_connection_busy() 检查连接是否繁忙(即查询是否正在执行)。可以使用 pg_cancel_query() 取消查询。

尽管用户可以一次发送多个查询,但不能通过繁忙的连接发送多个查询。如果在连接繁忙时发送查询,它将等待最后一个查询完成并丢弃其所有结果。

参数

connection

一个 PgSql\Connection 实例。

query

要执行的 SQL 语句或语句。

查询中的数据应该正确转义

返回值

成功时返回 true,失败时返回 false0。使用 pg_get_result() 确定查询结果。

变更日志

版本 描述
8.1.0 connection 参数现在期望一个 PgSql\Connection 实例;以前,期望一个资源

示例

示例 #1 pg_send_query() 示例

<?php
$dbconn
= pg_connect("dbname=publisher") or die("Could not connect");

if (!
pg_connection_busy($dbconn)) {
pg_send_query($dbconn, "select * from authors; select count(*) from authors;");
}

$res1 = pg_get_result($dbconn);
echo
"First call to pg_get_result(): $res1\n";
$rows1 = pg_num_rows($res1);
echo
"$res1 has $rows1 records\n\n";

$res2 = pg_get_result($dbconn);
echo
"Second call to pg_get_result(): $res2\n";
$rows2 = pg_num_rows($res2);
echo
"$res2 has $rows2 records\n";
?>

以上示例将输出

First call to pg_get_result(): Resource id #3
Resource id #3 has 3 records

Second call to pg_get_result(): Resource id #4
Resource id #4 has 1 records

参见

添加注释

用户贡献的注释 6 条注释

0
rw burgholzer is name at deq dot virginia dot gov
15 年前
关于现在无法处理所有查询,然后稍后检索结果,我发现如果在“stack_query()”方法中的 while 循环中添加另一个条件,所有查询都将成功返回。

通过添加
&& (pg_transaction_status($conn) === PGSQL_TRANSACTION_IDLE ) )

每个查询都执行且没有错误。

<?php
$conn
= pg_connect("dbname=dbname host=localhost user=psql ");
if (
$conn === FALSE)
exit(
"Can't connect to db");

$q = array();
// 发送一些查询
foreach (range(0, 50) as $i)
stack_query($q, $conn, "SELECT 'query $i' AS str;");
// 接收它们
while (true)
{
$left = stack_query($q, $conn);
echo
"$left left... ";
$result = pg_get_result($conn);
if (
$left == 0 && $result === FALSE)
break;
$row = pg_fetch_assoc($result);
// 根据竞争条件,您不会在这里获得所有原始查询。
echo "got $row[str]\n";
}

function
stack_query(&$queries, $conn, $sql = FALSE)
{
if (
$sql !== FALSE)
$queries[] = $sql;
while (
count($queries) && !pg_connection_busy($conn) && (pg_transaction_status($conn) === PGSQL_TRANSACTION_IDLE ) )
pg_send_query($conn, array_shift($queries));
return
count($queries) + (pg_connection_busy($conn) ? 1 : 0);
}
?>
0
[email protected]
21年前
由于一个bug,OLD API在PHP 4.2.0和4.2.1版本中不可用。

PHP 4.2.2将再次支持OLD API,并且会保留足够长的时间。

New API将从PHP 4.2.0到更高版本可用。
[email protected]
2002年6月19日 04:00
由于一个bug,PHP 4.2.0和4.2.1不支持pg_lo_import()旧API。此问题已在PHP 4.2.2中修复。

顺便说一句,新API将始终从PHP 4.2.0到更高版本可用。旧API也会保留足够长的时间。
[email protected]
2002年5月15日 09:08
在我的环境下它可以工作(php-4.2.1)

不是像这样

int pg_lo_import ( string pathname [, resource connection])

而是
int pg_lo_import ( resource connection, string pathname )

不知道原因
-1
[email protected]
13年前
pg_send_query不会阻止脚本执行,但会阻止脚本退出。

示例

<?php
$con
= pg_connect('dbname=payroll');
pg_send_query('SELECT process_payroll()'); // 其中process_payroll是一个超长进程
?>

您仍然需要等待查询完成,然后才能将任何显示发送到浏览器。令人惊讶的是,与pg_query不同,此脚本不会生成最大执行时间错误。
-2
Likeyouover [email protected]
21年前
<?php
// --------- 打开连接 ---

$conn = pg_connect("host='127.0.0.1' dbname='test' user='usertest' password='passtest'");

// --------- 打开文件 ---

$fp = fopen('logo.gif', "r");
$buffer = fread($fp, filesize('logo.gif'));
fclose($fp);

// --------- 创建 - 插入OID ---

pg_exec($conn, "begin");

$oid = pg_locreate($conn);

$rs = pg_exec($conn,"INSERT INTO test(tipo, images) VALUES('A1', $oid);");
$handle = pg_loopen ($conn, $oid, "w");

pg_lowrite ($handle, $buffer);
pg_loclose ($handle);

pg_exec($conn, "commit");

// --------- 打开 - 插入OID ---

$rs = pg_exec($conn, "SELECT images FROM test WHERE tipo = 'A1';");
$row = pg_fetch_row($rs, 0);

pg_exec($conn, "begin");
$loid = pg_loopen($conn, $row[0], "r");

header("Content-type: image/gif");

pg_loreadall($loid);
pg_loclose($loid);

pg_exec ($conn, "commit");

// --------- 删除OID ---

$rs = pg_exec($conn, "SELECT images FROM test WHERE tipo = 'A1';");
$row = pg_fetch_row($rs, 0);
pg_lounlink($conn, $row[0]);

// --------- 关闭连接 ---

pg_close();
?>
-2
Ron Howard
21年前
如果您的某个查询中存在错误,则其后的查询将不会执行,并且不会显示错误消息。我能想到的唯一确定是否发生SQL错误的方法是使用pg_trace。

示例

pg_send_query($connection,
"SELECT id FROM users;
SELECT * FROM customers;
[无效SQL语句];
SELECT name FROM countries;");

while ($result = pg_get_result($connection))
$results[] = $result;

$results数组中将只有两个项目。
-5
vincentdephily
19年前
请注意,如果您发送查询而没有为上一个查询调用pg_get_result()(假设它已完成并且连接不忙),则上一个查询将被丢弃。

自己看看(在php4.4.0、postgres8.0.4、Linux/FreeBSD上测试过)
<?
$conn = pg_connect("dbname=template1 host=localhost user=pgsql");
if ($conn === FALSE)
exit("无法连接到数据库");

$q = array();
// 发送一些查询
foreach (range(0, 500) as $i)
stack_query($q, $conn, "SELECT 'query $i' AS str;");
// 接收它们
while (true)
{
$left = stack_query($q, $conn);
echo "$left 剩余... ";
$result = pg_get_result($conn);
if ($left == 0 && $result === FALSE)
break;
$row = pg_fetch_assoc($result);
// 根据竞争条件,您不会在这里获得所有原始查询。
echo "获取到 $row[str]\n";
}

function stack_query(&$queries, $conn, $sql = FALSE)
{
if ($sql !== FALSE)
$queries[] = $sql;
while (count($queries) && !pg_connection_busy($conn))
pg_send_query($conn, array_shift($queries));
return count($queries) + (pg_connection_busy($conn) ? 1 : 0);
}
?>

如果您希望获得“立即发送所有查询,稍后接收它们”的行为,则必须编写更高级别的抽象。
To Top