2024 年 PHP Conference Japan

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("無法連線");

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

$res1 = pg_get_result($dbconn);
echo
"第一次呼叫 pg_get_result(): $res1\n";
$rows1 = pg_num_rows($res1);
echo
"$res1$rows1 筆記錄\n\n";

$res2 = pg_get_result($dbconn);
echo
"第二次呼叫 pg_get_result(): $res2\n";
$rows2 = pg_num_rows($res2);
echo
"$res2$rows2 筆記錄\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 則註解

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(
"無法連線到資料庫");

$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 個剩餘... ";
$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_transaction_status($conn) === PGSQL_TRANSACTION_IDLE ) )
pg_send_query($conn, array_shift($queries));
return
count($queries) + (pg_connection_busy($conn) ? 1 : 0);
}
?>
Mikewithme at yahoo dot com
21 年前
由於一個錯誤,舊 API 在 PHP 4.2.0 和 4.2.1 中無法使用。

PHP 4.2.2 將再次支援舊 API,並且會維持相當長一段時間。

新 API 將在 PHP 4.2.0 以後的版本中提供。
yohgaki at php dot net
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 也會保留相當長一段時間。
ceco at noxis dot net
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 )

不知道原因
moodsey211 at gmail dot com
13 年前
pg_send_query 不會停止你的腳本執行,但會阻止腳本結束。

範例

<?php
$con
= pg_connect('dbname=payroll');
pg_send_query('SELECT process_payroll()'); // process_payroll 是一個非常耗時的程序
?>

你仍然需要等待查詢完成,瀏覽器才會收到任何顯示內容。而且令人驚訝的是,與 pg_query 不同,這個腳本不會產生「Maximum execution time error」(最大執行時間錯誤)。
Likeyouover others at hotmail dot com
21 年前
<?php
// --------- OPEN CONN ---

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

// --------- OPEN FILE ---

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

// --------- CREATE - INSERT 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");

// --------- OPEN - INSERT 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");

// --------- UNLINK OID ---

pg_exec($conn, "begin");

$loid = $row[0];
pg_lounlink($conn, $loid);

pg_exec ($conn, "commit");

// --------- DELETE OID ---

pg_exec($conn, "DELETE FROM test WHERE tipo = 'A1';");

// --------- CLOSE CONN ---

pg_close();
?>
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 陣列將只會有兩個項目。
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