PHP Conference Japan 2024

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() 等效于以 PGSQL_ASSOC 作为可选的第三个参数调用 pg_fetch_array()。它只返回一个关联数组。如果需要数字索引,请使用 pg_fetch_row()

注意: 此函数将 NULL 字段设置为 PHP null 值。

pg_fetch_assoc() 并不比使用 pg_fetch_row() 慢很多,并且使用起来更加方便。

参数

result

pg_query()pg_query_params()pg_execute()(以及其它函数)返回的 PgSql\Result 实例。

row

要获取的结果中的行号。行号从 0 向上编号。如果省略或为 null,则获取下一行。

返回值

一个按关联方式(按字段名)索引的 arrayarray 中的每个值都表示为 string。数据库 NULL 值作为 null 返回。

如果 row 超出集合中的行数,没有更多行或发生任何其他错误,则返回 false

更新日志

版本 说明
8.1.0 result 参数现在需要一个 PgSql\Result 实例;以前,需要一个 资源(resource)

示例

示例 #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 条注释

up
13
slurppp at hotmail dot fr
12 年前
请注意,所有 pg_fetch_* 函数都忽略数据的原始类型,并且始终返回字符串。(数字也是如此)
up
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() 或重写查询以避免歧义。
up
6
Luke
19 年前
注意

设置为 TRUE 的 PostgreSQL 布尔值将作为字符串 "t" 返回

设置为 FALSE 的 PostgreSQL 布尔值将作为字符串 "f" 返回
up
2
匿名
18 年前
如果您请求不存在的行,它只会失败,而不是简单地返回 false。
up
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);
}
}
up
0
artem.eroshin gmail com
4 年前
将 't' 和 'f' 转换为 PHP 布尔值

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

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

//some other code
}

function 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;
}
}
}

}
up
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;
}
// 用于JS的隐藏文本框
echo "<form method='post' id='hiddenform'><input type='hidden' name='txthidden' id='txthidden'></form>";
$mysqli->close();
?>
</body>
</html>
up
0
阿列克谢·洛克季奥诺夫 (邮箱错误)
14年前
这是一个更强大的基于有限状态机的 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);

/**
* 将 PostgreSQL 数组字符串解析为 PHP 数组
*
* @param string $value 要解析的 PostgreSQL 数组字符串
* @return array 解析后的 PHP 数组
*/

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;
}

/**
* 有限状态机 (FSM) 处理函数
*
* @param string $chr 当前字符
* @param array $result 结果数组的引用
* @return int 层级变化值
*/

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;
}

?>
up
0
匿名用户
14年前
请注意,如果您的某个结果字段是一个数组,它将按照 Postgres 处理 SQL 数组的方式,以 '{value1,value2, ... }' 的通用格式输出为字符串。
https://postgresql.ac.cn/docs/8.4/static/arrays.html#ARRAYS-IO

因此,这里提供了一个将简单(一维)SQL 数组转换为 PHP 数组的函数。

<?php
function pg_parse_array($field)
/*
* 将简单的 SQL 数组字段转换为其 PHP 等效形式。例如:
*
* {null} --> Array(null);
* {"null"} --> Array("null");
* {foo,bar} --> Array("foo", "bar");
* {"foo,bar"} --> Array("foo,bar");
* {"Hello \"World\""} --> Array('Hello "World"');
*
*/
{
// NULL 字段始终为 NULL
if (!is_string($field)) return $field;

// 检查可能表示 SQL 数组字段的花括号
if ($field[0] != '{' or substr($field, -1) != '}') return $field;
$field = trim(substr($field, 1, -1));

$array = Array();

// 将字符串分解为以下内容:
// - 可能包含用反斜杠转义的特殊字符的带引号文本
// - 可能不包含特殊字符的无引号文本
$search = '/(")?+((?(1)(?:\\\\.|[^"])*|[^,]+))(?(1)\\1)/';
preg_match_all($search, $field, $matches, PREG_SET_ORDER);

foreach(
$matches as $value)
{
if (
$value[1])
{
// 带引号的元素,使用反斜杠转义字符
$array[] = preg_replace('#\\\\(.)#', '$1', $value[2]);
}
else
{
// 无引号的元素
$value[2] = trim($value[2]);
if (
strtolower($value[2]) == 'null') $array[] = null; // NULL
else $array[] = $value[2];
}
}
return
$array;
}

// 一些演示此函数的测试
var_export(pg_parse_array('{null}'); // 输出为 Array(null);
var_export(pg_parse_array('{foo,bar}'); // 输出为 Array('foo', 'bar');
var_export(pg_parse_array('{"null"}'); // 输出为 Array('null');

?>
up
0
匿名用户
16 年前
bytea 列以转义形式返回。
您需要对它们调用 pg_unescape_bytea() 才能获取原始二进制数据。
up
0
匿名用户
16 年前
关于可选的 int 参数

请求结果集中不存在的行号是错误的。不要这样做。

请先使用 pg_num_rows() 进行检查,或者直接使用默认行为,该行为按顺序返回行,并在返回最后一行后返回 false;如果没有返回任何行,则立即返回 false。
up
0
javier dot vilarroig at gmail dot com
17 年前
值得注意的是,当您查询多个表时,仅返回每个名称的第一行。

也就是说,如果您要连接到具有名为“name”的列的表,则您将在数组中仅收到一个名为“name”的字段,并且它将对应于第一个表中的字段。

在这种情况下,建议始终为您的列设置别名。
up
0
johniskew
17 年前
这是另一种迭代结果集并使用很少代码显示所有列的方法...可能比 foreach 更快

<?php

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

?>
up
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 也可能派上用场......我花了一点时间才弄明白。
up
0
spam at pasher dot org
21 年前
需要注意的一件重要事情(截至 PHP 4.3.2)

如果您习惯使用“扩展”比较运算符(=== 和 !==)来尝试使您的代码在视觉上更易于理解,则如果提供的资源句柄无效(与 false 相反),此函数将返回 NULL。即:

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

显然,您应该在开始 while 循环之前检查 $rs === false,但此示例用于说明如果 $rs 为 false 时潜在的无限循环问题。
up
0
Brenton Strickler
21 年前
乍一看,此页面顶部列出的语法与示例不匹配。不需要 PGSQL_ASSOC 标志。
up
-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