Postgresql自定义函数返回表

时间:2014-02-03 15:29:16

标签: php sql postgresql stored-procedures plpgsql

我正在使用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的最新版本。

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

2 个答案:

答案 0 :(得分:3)

这部分不正确:

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

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

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

答案 1 :(得分:3)

@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表限定列名。

相关问题