【问题标题】:PHP - mysqli_fetch_field equivalent for PostgreSQLPHP - PostgreSQL 的 mysqli_fetch_field 等效项
【发布时间】:2021-04-10 02:19:33
【问题描述】:

我正在尝试将我的项目从 MySQL 迁移到 PostgreSQL。对于 MySQL,PHP 提供了很好的功能来获取 SELECT 查询元数据。

mysqli_fetch_fieldmysqli_fetch_field_direct 函数可以为查询中的每个字段提供以下值

  • 姓名
  • 组织名称
  • 表格
  • 组织表
  • 最大长度
  • 长度
  • 类型
  • (以及其他一些我目前不感兴趣的)

例如,查询中“id”字段的示例查询和元数据将如下所示:

查询:

从 table1 t1 中选择 id 作为 id2

字段“id”的元数据:

  • 姓名:id2
  • 组织名称:id
  • 表:t1
  • orgtable : table1
  • 长度:765
  • 类型:253

mysqli_fetch_field 的好处是它能够返回查询中字段和表的别名和原始名称。

当我尝试为 PostgreSQL 模仿此功能时,我发现 PostgreSQL 没有等效的 mysqli_fetch_field 函数,相反,有几个 pg_field_* 函数,每个函数都为字段提供单个信息。

  • pg_field_name 仅返回名称,对于此示例,它给出“id2”
  • pg_field_table 返回原始表名,例如“表 1”
  • pg_field_type 返回类型(这里没问题)
  • pg_field_size返回字段长度(也可以)

显然,如果 pg_field_* 函数在查询中被重命名,而 mysqli_fetch_field 提供,则不会向程序员提供表/字段的原始名称。

有没有一种方法可以获取 PostgreSQL 中查询的“详细”元数据?它可以使用额外的查询或 DBMS 提供的工具,如 EXPLAIN 和 DESCRIBE(我也尝试过)或其他任何东西。

【问题讨论】:

  • 这是一个错误,对不起。我用 mysqli_* 函数更新了帖子。

标签: php mysql postgresql


【解决方案1】:

您是否投资于 Postgres 特定的功能 API?如果没有,请查看PDO,它为您的数据库提供了一个通用接口,无论是 MySQL 还是 Postgres。它还为您提供了一种获取特定列的方法:

$pdo = new PDO(...);
$statement = $pdo->prepare("SELECT foo FROM bar WHERE baz = ?");
$statement->execute([42]);
$foo = $statement->fetchColumn(0);
// $foo is the column value or false

您还可以获取所有结果行的列值:

$foos = $statement->fetchAll(\PDO::FETCH_COLUMN, 0);
// $foos is an array, possibly empty

请注意,fetchAll 会导致通常的内存损失,因为可能会将较大的结果加载到您的进程中。如果已知结果集总是很小,您应该只使用fetchAll。否则,请在循环中使用 fetchfetchColumn 并使用 LIMIT n, m 子句对查询进行分页。

如果只查询一列,则获取特定列是资源友好的。当您的查询中有其他列时,它们仍会被提取到您的进程中,只是被丢弃。您应该确保不包含任何不必要的列。

对于列元数据,使用getColumnMeta:

$meta = $statement->getColumnMeta(0);
// $meta is false or array{native_type, driver:decl_type, flags, name, table, len, precision, pdo_type}

要获得更详细的元数据,您应该查询information_schema.columns。最好在数据查询之前进行,因为数据查询可能会循环执行。元数据只需要预先获取一次。

【讨论】:

  • 这看起来确实与获取列值而不是元数据有关。
  • 感谢您的更新。但是,如果字段/表用别名重命名,PDO 似乎仍然没有给出字段的“名称”和“原始”名称。如果是这样,请纠正我。
  • PDO 或 PG 函数 API 均未涵盖此特定用例。你必须自己做。例如,PDO API 是相当低级的。我最终创建了一个适配器 API,它允许我执行诸如多数据库事务之类的事情。在您的适配器中,您可以分析查询(preg_match 或其他)并查看是否有重命名。
  • 通过 preg_match 分析查询会很困难并且容易出错。尽管如此,仍有一些库/包可用于此特定目的。如果我无法通过 PostgreSQL 查询/工具和 PHP API 选项找到解决方案,我可以使用它们。
  • 我想知道这些包是如何做到的。除非他们使用原始 Postgres 连接并执行一些协议,否则我想他们也必须分析查询。重新“这很难而且容易出错”我不太明白这一点。它可能涉及一些非零工作和单元测试,但另一方面,您可以控制关​​键的基础设施组件(数据库访问层)。
【解决方案2】:

经过一番研究,我最终确信 PHP Postgres API 和 PostreSQL 本身都没有提供这样的功能。因此,我可以通过 pg_field_* 函数和用 PHP 编写的 SQL Parser 的组合来解决这个问题,即PHP-SQL-Parser

尽管 SQL 解析器是为 MySQL 编写的,但默认功能适用于我的用例,并且在任何情况下都是可扩展的。

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2012-10-22
    • 1970-01-01
    • 2010-12-14
    • 2012-05-11
    • 2019-11-11
    • 2013-05-03
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多