【问题标题】:Postgresql custom function returning tablePostgresql 自定义函数返回表
【发布时间】:2014-02-27 04:01:06
【问题描述】:

我使用的是 PostgreSQL 9.1.11。
我需要将 SELECT 的结果返回到我的 php 脚本。 php中的调用是这样的:

$res = $pdb->getAssoc("SELECT * FROM my_profile();");

用于说明 php 中发生了什么的类代码

public function getAssoc($in_query) {
  $res = pg_query($this->_Link, $in_query);
  if($res == FALSE) {
    return array("dberror", iconv("utf-8", "windows-1251", pg_last_error($this->_Link)));
  }
  return pg_fetch_all($res);
}

接下来是我在 Postgres 中的函数。当我更新任何函数时,我通过放入一个脚本来完全重新创建数据库。 (该项目处于开发的早期阶段。)我几乎没有做存储过程的经验。

我收到此错误:

structure of query does not match function result type
CONTEXT: PL/pgSQL function "my_profile" line 3 at RETURN QUERY )

试着写:

CREATE FUNCTION my_profile()
RETURNS TABLE (_nick text, _email text) AS $$
BEGIN
  RETURN QUERY SELECT (nick, email) FROM my_users WHERE id = 1;
END;
$$
LANGUAGE 'plpgsql' SECURITY DEFINER;

表结构为:

CREATE TABLE my_users(
  id integer NOT NULL,
  nick text,
  email text,
  pwd_salt varchar(32),
  pwd_hash character(128),
  CONSTRAINT users_pk PRIMARY KEY (id)
);

当我在表中返回 1 列时,查询有效。尝试在 LANGUAGE sql 而不是 plpgsql 中重写过程并取得了一些成功,但我想坚持使用 plpgsql。

我使用的 Postgres 9.1.11,php-fpm 是最新的,用于完全更新的 amd64 Debian wheezy。

我想要做的是在关联数组中返回一个包含从 proc 到 php 的 0 到 n 行的记录集。

【问题讨论】:

    标签: php sql postgresql stored-procedures plpgsql


    【解决方案1】:

    这部分不正确:

    RETURN QUERY SELECT (nick, email) FROM my_users WHERE id = 1;
    

    您应该删除nick,email 周围的括号,否则它们会形成一个具有ROW 类型的唯一列。

    这就是它与结果类型不匹配的原因。

    【讨论】:

      【解决方案2】:

      @Daniel 已经指出了您的直接问题(括号使用不正确)。但还有更多:

      • 切勿在此上下文中引用语言名称 plpgsql。它是一个标识符,而不是字符串文字。现在可以容忍它,因为它是一种广泛传播的反模式。但在以后的版本中可能会被视为语法错误。

      • SECURITY DEFINER 子句应伴随search_path 的本地设置。请务必阅读according chapter in the manual。

      所有东西放在一起,它可能看起来像这样:

      CREATE FUNCTION my_profile()
        RETURNS TABLE (nick text, email text) AS
      $func$
      BEGIN
         RETURN QUERY
         SELECT m.nick, m.email FROM my_users m WHERE m.id = 1;
      END
      $func$
      LANGUAGE plpgsql SECURITY DEFINER SET search_path = public, pg_temp;
      

      将public 替换为您的表的实际架构。

      为了避免RETURNS TABLE ... 中的 OUT 参数和 SELECT 语句中的表列之间可能出现的命名冲突,我使用给定别名 m 对表限定列名。

      【讨论】:

      • 感谢您的建议,您的代码风格建议似乎很有用。我在描述问题时跳过了 search_path,因为它看起来与问题无关。
      猜你喜欢
      • 2011-01-03
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2013-07-05
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      相关资源
      最近更新 更多