2024 日本 PHP 研討會

pg_fetch_assoc

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

pg_fetch_assoc將一行擷取為關聯式陣列

說明

pg_fetch_assoc(PgSql\Result $result, ?int $row = null): array|false

pg_fetch_assoc() 會傳回一個對應於所擷取列 (紀錄) 的關聯式陣列。

pg_fetch_assoc() 等同於呼叫 pg_fetch_array() 並將 PGSQL_ASSOC 作為選用的第三個參數。它只會返回一個關聯式陣列。如果您需要數字索引,請使用 pg_fetch_row()

注意此函式會將 NULL 欄位設定為 PHP 的 null 值。

pg_fetch_assoc() 並不會比使用 pg_fetch_row() 慢很多,而且明顯更容易使用。

參數

result

一個 PgSql\Result 實例,由 pg_query()pg_query_params()pg_execute()(以及其他函式)返回。

row

要擷取的結果集中列的編號。列從 0 開始編號。如果省略或為 null,則會擷取下一列。

返回值

一個以欄位名稱作為索引的關聯式 陣列陣列 中的每個值都以 字串 表示。資料庫中的 NULL 值會以 null 返回。

如果 row 超過集合中的列數、沒有更多列或發生任何其他錯誤,則返回 false

更新日誌

版本 說明
8.1.0 result 參數現在需要一個 PgSql\Result 實例;以前需要的是一個資源

範例

範例 #1 pg_fetch_assoc() 範例

<?php
$conn
= pg_connect("dbname=publisher");
if (!
$conn) {
echo
"發生錯誤。\n";
exit;
}

$result = pg_query($conn, "SELECT id, author, email FROM authors");
if (!
$result) {
echo
"發生錯誤。\n";
exit;
}

while (
$row = pg_fetch_assoc($result)) {
echo
$row['id'];
echo
$row['author'];
echo
$row['email'];
}
?>

參見

新增註釋

使用者貢獻的註釋 17 則註釋

13
slurppp at hotmail dot fr
12 年前
請注意,所有 pg_fetch_* 函式都會忽略資料的原始類型,並一律返回字串。(數字也是如此)
3
匿名
15 年前
注意!如果您的查詢返回多個同名欄位,則結果陣列中只會包含最右邊的欄位。如果您使用聯結組合,這可能會導致問題。

例如
<?php
// 假設 'pkey' 是表格 a 和 b 的主鍵欄位(主鍵永遠不會是 null)
$res = pg_query("Select a.pkey, b.* FROM a LEFT JOIN b using (pkey)");
$data = pg_fetch_assoc($res);
var_dump($data['pkey']) // 實際上是 b.pkey,可能是 NULL!
?>

兩個表格都包含一個名為 'pkey' 的欄位。現在表格 'b' 位於 LEFT JOIN 的可選端,因此 b.pkey(透過 'b.*' 隱式包含)可能是 NULL。

當您使用 pg_fetch_assoc() 時,問題就出現了,有兩個名為 'pkey' 的欄位,但結果陣列每個鍵只能包含一個值——在這種情況下,它會選擇表格 B 中的值而不是表格 A 中的值,而且由於 B 位於左聯結的可選端,$data['pkey'] 可能是 NULL。因此,如果您期望從表格 A 中擷取該欄位,則需要使用不同的 pg_fetch() 或重寫您的查詢以避免歧義。
6
Luke
19 年前
註釋

設為 TRUE 的 PostgreSQL 布林值會以字串 "t" 返回。

設為 FALSE 的 PostgreSQL 布林值會以字串 "f" 返回。
2
匿名
18 年前
如果您請求一個不存在的列,它只會失敗,而不是簡單地返回 false。
1
ninja (whorl) thinkninja (stop) com
21 年前
如果您在不同版本的 PHP 之間移動,這可能很方便

if (!function_exists('pg_fetch_assoc')) {
function pg_fetch_assoc ($result)
{
return @pg_fetch_array($result, NULL, PGSQL_ASSOC);
}
}
0
artem.eroshin gmail com
4 年前
將 't' 和 'f' 轉換為 PHP 布林值

$result = pg_query($_db, $sql);

while ( $row = pg_fetch_assoc( $result ) )
{
fixBooleans($result, $row);

//其他程式碼
}

函式 fixBooleans($result, &$row)
{

for ($fld_i = 0; $fld_i < pg_num_fields($result); $fld_i++)
{
$fld_name = pg_field_name($result, $fld_i);

if( pg_field_type($result, $fld_i) == 'bool' )
{
if( $row[ $fld_name ] == 't' )
{
$row[ $fld_name ] = true;
}
elseif($row[ $fld_name ] == 'f')
{
$row[ $fld_name ] = false;
}
}
}

}
0
huntfalow at yahoo dot com
9 年前
<html>
<head>
<script>
function waarde(){
var text = document.getElementById("optVakken").value;
document.getElementById("txthidden").value = text;
document.forms["hiddenform"].submit();
}
</script>
<?php
// 選擇所有教師的下拉式選單
function leerkrachten($aName){
include(
"includes/connect.php");

}
// 選擇所有科目的下拉式選單
function vakken($aID){
include(
"includes/connect.php");
$SelectVakkenQuery = "SELECT * FROM vakken";
$SelectVakkenResult = $mysqli->query($SelectVakkenQuery);
$Choice = "<select id='$aID' onchange=waarde()><option>請選擇科目</option>";

while(
$rij2 = $SelectVakkenResult->fetch_assoc()){
$VakID = $rij2['vakid'];
$Vaknaam = $rij2['voluit'];
$Choice .= "<option value='$VakID'>$Vaknaam</option>";
}
$Choice .= "</select>";
return
$Choice;
}
?>
<title>補救教學練習</title>
</head>
<body>
<?php
include("includes/connect.php");
// 建立下拉式選單

// 第一個下拉式選單
echo vakken("optVakken")."<br><br>";

// 第二個下拉式選單
if(!isset($_POST['txthidden'])){
$SelectLeerkrachtenQuery = "SELECT * FROM leerkrachten";
$SelectLeerkrachtResult = $mysqli->query($SelectLeerkrachtenQuery);

$Choice = "<select>";
while(
$rij=$SelectLeerkrachtResult->fetch_assoc()){
$Voornaam = $rij['voornaam'];
$Naam = $rij['naam'];
$LKID = $rij['leerkrachtid'];
$Volledig = $Voornaam . " " . $Naam;
$Choice .= "<option value='$LKID'>$Volledig</option>";
}
$Choice .= "</select><br><br>";
echo
$Choice;
}else{
$vakid = $_POST['txthidden'];
$SelectLeerkrachtenQuery = "SELECT * FROM leerkrachten JOIN leerkrachtpervak ON leerkrachten.leerkrachtid = leerkrachtpervak.leerkrachtid WHERE vakid = '$vakid'";
$SelectLeerkrachtResult = $mysqli->query($SelectLeerkrachtenQuery);
$Choice = "<select>";
while(
$row3=$SelectLeerkrachtResult->fetch_assoc()){
$Voornaam = $row3['voornaam'];
$Naam = $row3['naam'];
$Volledig = $Voornaam . " " . $Naam;
$Choice .= "<option>$Volledig</option>";
}
$Choice .= "</select><br><br>";
echo
$Choice;
}
// 隱藏的 textbox 給 JS 使用
echo "<form method='post' id='hiddenform'><input type='hidden' name='txthidden' id='txthidden'></form>";
$mysqli->close();
?>
</body>
</html>
0
Alexey Loktionov (error at pochta dot ru)
14 年前
基於有限狀態機 (FSM) 的強大 pg_parse_array() 變體:適用於任何維度的 Postgres 陣列(其字串表示法必須格式良好),具備引號規則檢查,複雜度為 O(N),其中 N 是 Postgres 陣列字串表示法的長度。

<?php

define
('STATE_BEGIN', 1);
define('STATE_INARRAY',2);
define('STATE_OUTARRAY', 3);
define('STATE_INSLASH', 4);
define('STATE_INQUOTES', 5);

function
pg_parse_array($value) {
$resultArray = $indexArray = array(); $level = $index = 0;
$ptr = &$resultArray;
for(
$i = 0; $i < strlen($value); $i++){
switch(
$level){
case
1:
if(
$index > 0){
$ptr = & $ptr[sizeof($ptr)];
}
$indexArray[++$index] = & $ptr;
break;
case -
1:
$ptr = & $indexArray[--$index];
break;
}
$level = processFSM($value{$i}, $ptr);
}
return
$resultArray;
}

function
processFSM($chr, &$result){
static
$state = STATE_BEGIN, $index = 0;
$level = 0;
switch(
true){
case
$chr == '{' && in_array($state, array(STATE_BEGIN,STATE_INARRAY,STATE_OUTARRAY), true):
$state = STATE_INARRAY;
$index = 0;
$level = +1;
break;
case
$chr == '}' && in_array($state, array(STATE_INARRAY,STATE_OUTARRAY), true):
$state = STATE_OUTARRAY;
$level = -1;
break;
case
$chr == '\\' && $state !== STATE_BEGIN:
$state = $state === STATE_INSLASH ? STATE_INQUOTES : STATE_INSLASH;
break;

case
$chr == '"' && !in_array($state, array(STATE_BEGIN,STATE_INSLASH), true):
$state = $state === STATE_INQUOTES ? STATE_INARRAY : STATE_INQUOTES;
break;

case
$chr == ',' && in_array($state, array(STATE_INARRAY,STATE_OUTARRAY), true):
$index = sizeof($result);
break;

case
$state !== STATE_BEGIN:
$state = $state === STATE_INSLASH ? STATE_INQUOTES : $state;
isset(
$result[$index]) or $result[$index] = '';
$result[$index] .= $chr;
break;
}
return
$level;
}

?>
0
匿名
14 年前
請注意,如果您的結果欄位之一是陣列,它將會以 '{value1,value2, ... }' 的通用格式輸出為字串,這與 postgres 處理 SQL 陣列的行為一致。
https://postgresql.dev.org.tw/docs/8.4/static/arrays.html#ARRAYS-IO

以下是一個將簡單(一維)SQL 陣列轉換為 PHP 陣列的函式:

<?php
function pg_parse_array($field)
/*
* Converts a simple SQL array field to its PHP equivalent. e.g:
*
* {null} --> Array(null);
* {"null"} --> Array("null");
* {foo,bar} --> Array("foo", "bar");
* {"foo,bar"} --> Array("foo,bar");
* {"Hello \"World\""} --> Array('Hello "World"');
*
*/
{
// NULL fields are always NULL
if (!is_string($field)) return $field;

// Check for curly braces which may indicate an SQL array field
if ($field[0] != '{' or substr($field, -1) != '}') return $field;
$field = trim(substr($field, 1, -1));

$array = Array();

// Break up the string into the following:
// - quoted text that MAY have special chars escaped by a backslash
// - unquoted text that may NOT have special chars
$search = '/(")?+((?(1)(?:\\\\.|[^"])*|[^,]+))(?(1)\\1)/';
preg_match_all($search, $field, $matches, PREG_SET_ORDER);

foreach(
$matches as $value)
{
if (
$value[1])
{
// Quoted element, with backslash used to escape chars
$array[] = preg_replace('#\\\\(.)#', '$1', $value[2]);
}
else
{
// Unquoted element
$value[2] = trim($value[2]);
if (
strtolower($value[2]) == 'null') $array[] = null; // NULL
else $array[] = $value[2];
}
}
return
$array;
}

// Some tests to demonstrate this function
var_export(pg_parse_array('{null}'); // Output is Array(null);
var_export(pg_parse_array('{foo,bar}'); // Output is Array('foo', 'bar');
var_export(pg_parse_array('{"null"}'); // Output is Array('null');

?>
0
匿名
16 年前
bytea 欄位會以跳脫字元的形式返回。
您需要對它們呼叫 pg-unescape-bytea() 才能取回原始二進位資料。
0
匿名
16 年前
關於可選的 int 參數

請求結果集中不存在的行號是錯誤的。不要這樣做。

請事先使用 pg_num_rows() 檢查,或者使用預設行為,依序返回每一列,並在返回最後一列後返回 false;如果沒有返回任何列,則立即返回 false。
0
javier dot vilarroig at gmail dot com
17 年前
值得注意的是,當您查詢多個表格時,只會返回每個名稱的第一列。

也就是說,如果您連接兩個都具有名為 'name' 欄位的表格,您在陣列中只會收到一個名為 name 的欄位,它會對應到第一個表格中的那個欄位。

建議您在這種情況下永遠使用別名來區分您的欄位。
0
johniskew
17 年前
這裡有另一種方法可以用很少的程式碼迭代結果集並顯示所有欄位... 可能比 foreach 更快

<?php

print '<table>';
while(
$row=pg_fetch_assoc($rs2)) print '<tr><td>'.join('</td><td>',$row2).'</td></tr>';
print
'</table>';

?>
0
petrus at bmail dot com dot au
19 年前
$dbconn3 = pg_connect("host=127.0.0.1 port=5432 dbname=blah user=blah password=blah");
$result = pg_query($dbconn3, "SELECT * FROM Packages");

echo "<HTML><HEAD><TITLE>PostgreSQL 測試頁面</TITLE></HEAD><BODY>";
echo "<TABLE>";

$pkg = pg_fetch_assoc($result);
foreach ($pkg as $value) {
echo "<TR><TD>$value";
echo "</TR></TD>";
}

echo "</TABLE><P>";
echo "這個套件的完整檔名是: {$pkg['name']}-{$pkg['version']}{$pkg['extension']}";
echo "</BODY></HTML>";

對於產生表格,這個方法有效,而且我個人比較喜歡用 foreach() 而不是 while 迴圈,因為沒有意外造成無限迴圈的風險… foreach 只會在有東西可以處理的時候運作,然後就會停止。我覺得底部的 echo 指令也可能會派上用場… 我花了一點時間才發現這一點。
0
spam at pasher dot org
21 年前
一個需要注意的重點 (從 PHP 4.3.2 開始)

如果您習慣使用「擴展」比較運算子 (=== 和 !==) 來讓程式碼更容易閱讀,當提供的資源句柄無效時,這個函式會返回 NULL(而不是 false)。例如:

$rs = @pg_query('SELECT * FROM fake_table');
while (false !== ($row = @pg_fetch_assoc($rs)))
{
print_r($row);
}

顯然,您應該在開始 while 迴圈之前檢查 $rs 是否 === false,但這個例子是用來說明如果 $rs 為 false 時,可能會出現無限迴圈的問題。
0
Brenton Strickler
21 年前
乍看之下,此頁面頂部列出的語法與範例不符。PGSQL_ASSOC 旗標不是必需的。
-3
strata_ranger at hotmail dot com
16 年前
補充 Luke 關於 SQL 布林值的說明(這是我吃盡苦頭才學到的一件事),一個相對簡單的解決方法是在查詢內將布林值欄位強制轉換為整數,例如:

<?php
// 假設 'foo' 是表格中一個布林值類型的欄位
$res = pg_query("Select foo as foo1, foo::integer as foo2 from bar");

$data = pg_fetch_assoc($res);
if (
$data['foo1']) echo 'foo1 = TRUE'; // 無法如預期運作(字串 't' 和字串 'f' 都會被評估為 TRUE)
if ($data['foo2']) echo 'foo2 = TRUE'; // 如預期運作(字串 '0' 會被評估為 FALSE)
?>
To Top