【问题标题】:Strange 'Unknown table' when performing plpgsql script执行 plpgsql 脚本时出现奇怪的“未知表”
【发布时间】:2014-08-25 21:24:29
【问题描述】:

我在 PostgreSQL 数据库服务器的多个模式中有一个相同的表。我需要 执行如下查询:

CREATE OR REPLACE FUNCTION git_search() RETURNS SETOF git_log AS $$
DECLARE
sch name;
BEGIN
    FOREACH sch IN 
     select schema_name from information_schema.schemata where schema_name not in ('pg_toast','pg_temp_1','pg_toast_temp_1','pg_catalog','information_schema') 
    LOOP 
        qry := 'select count(*) from'|| quote_ident(sch) || '.git_log gl where gl.author_contributor_id = 17';      
    RETURN QUERY qry; 
    END LOOP;
    RETURN;
END;    
$$ LANGUAGE plpgsql; 

select git_search();

但我有错误:

错误:“git_log”类型不存在
SQL 状态:42704

git_log 表在脚本的第一行中是未知的。 (子句CREATE

有人可以帮帮我吗?

我需要在 100 多个模式中执行针对这种情况进行调整的查询。做这个的最好方式是什么?我可以在哪里为此目的创建函数?

【问题讨论】:

  • 推测git_log 在创建函数的架构中不是已知类型。
  • @GordonLinoff 我需要在 100 多个模式中执行针对这种情况进行调整的查询。做这个的最好方式是什么?我可以在哪里为此目的创建函数?
  • 您需要定义一个类型,该类型可以是字符串(对于当前编写函数的方式)或整数(假设您的意思是返回查询执行)。
  • 抱歉,Gordon 的 cmets 完全不正确。您在其中创建函数的模式与此处的任何内容无关。您不必定义更多类型,当然不是a type that is either a string .. or an integer。请忽略这一点。我发布了一个全面的答案。
  • @ErwinBrandstetter 感谢您的帮助,现在脚本可以正常工作了。

标签: sql postgresql plpgsql dynamic-sql postgresql-9.3


【解决方案1】:

表名可以用作复合类型名,因为每个表都会自动创建同名(模式限定)的复合类型。

错误的直接原因:在当前search_path中找不到你的名为git_log的表(实际上是关联的同名复合类型),所以类型名称无法解决。

由于您正在使用许多模式和许多名为git_log 的表实例,因此您需要明确且对表名进行模式限定。只需在其中一个架构中选择任何一个表,它们都共享相同的布局:

但是您的其他功能也不起作用。它不是“plpgsql 脚本”,而是函数定义。试试这个:

CREATE OR REPLACE FUNCTION git_search()
  RETURNS SETOF one_schema.git_log AS
$func$
DECLARE
   sch text;
BEGIN
   FOR sch IN 
      SELECT schema_name
      FROM   information_schema.schemata
      WHERE  schema_name NOT LIKE 'pg_%'
      AND    schema_name <> 'information_schema'
      ORDER  BY schema_name
   LOOP 
      RETURN QUERY EXECUTE format(
         'SELECT count(*)
          FROM   %I.git_log
          WHERE  author_contributor_id = 17', sch);      
   END LOOP;
END  
$func$ LANGUAGE plpgsql;

呼叫:

SELECT <b>* FROM</b> git_search();

要点

【讨论】:

  • 在最终代码中,我的函数返回 'SETOF record' 而不是 'one_schema.git_log' 以及我调整为的调用上下文: SELECT * FROM git_search () AS foo (val bigint);
  • @TarcisioM.:我几乎从不返回带有RETURNS SETOF record 的匿名记录。 Postgres 无法分解记录,您必须在每次调用时提供列定义列表。 If you know the return type, declare it. 还有if you have your answer, please accept it.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
相关资源
最近更新 更多