【问题标题】:Postgresql: ERROR: structure of query does not match function result type Using DbLinkPostgresql:错误:查询结构与使用 DbLink 的函数结果类型不匹配
【发布时间】:2014-09-05 18:01:31
【问题描述】:

所以我编写了这个方法,旨在使用 dblink 查询另一个具有相同结构的远程数据库(灵感来自这篇文章 Specify dblink column definition list from a local existing type 和这篇文章 Refactor a PL/pgSQL function to return the output of various SELECT queries

CREATE OR REPLACE FUNCTION select_remote(_table anyelement)
  RETURNS SETOF anyelement 
  AS $func$
DECLARE
        _dblink_schema text;
        _cols          text; 
        _server        text := 'host=ngrok.com port=45790 user=postgres password=postgres dbname=backup-28-08';
        _table_name    text := pg_typeof(_table);
BEGIN

        SELECT nspname INTO _dblink_schema
        FROM pg_namespace n, pg_extension e
        WHERE e.extname = 'dblink' AND e.extnamespace = n.oid;

    SELECT array_to_string(array_agg(column_name || ' ' || udt_name), ', ')  INTO _cols
        FROM (select column_name, udt_name from information_schema.columns
        WHERE table_name = _table_name
        order by ordinal_position) as sub;

        RETURN QUERY EXECUTE format('SELECT * FROM %I.dblink(%L, %L) AS remote (%s)',
            _dblink_schema,
            _server,
            format('SELECT * FROM %I', _table_name),
            _cols
        );


END;
$func$ LANGUAGE plpgsql;

但是当我执行select * from select_remote(NULL::my_table) 时,我收到了这个错误:

ERROR:  structure of query does not match function result type
DETAIL:  Returned type character varying does not match expected type character varying(255) in column 2.
CONTEXT:  PL/pgSQL function select_remote(anyelement) line 18 at RETURN QUERY

********** Erreur **********

ERROR: structure of query does not match function result type
État SQL :42804
Détail :Returned type character varying does not match expected type character varying(255) in column 2.
Contexte : PL/pgSQL function select_remote(anyelement) line 18 at RETURN QUERY

这让我抓狂,因为远程表和本地表确实具有相同的结构。

例如。如果我只返回查询字符串,我可以UNION它到本地表,它工作得很好:

SELECT * FROM public.dblink('host=ngrok.com port=45790 user=postgres password=postgres dbname=backup-28-08', 'SELECT * FROM my_table') AS remote (id int4, fname varchar, lname varchar, email varchar, slug varchar) 
UNION 
SELECT * FROM my_table

我做错了什么?我如何强制anyelement 接受这些数据,即使它来自远程表?或者返回一些不同的东西来让它工作?

谢谢

【问题讨论】:

  • 我现在不能测试这个,所以这只是一个猜测: udt_name 列只包含数据类型的名称。 varchar 和 varchar(255) 是不同的东西,尽管它应该被强制转换。列 information_schema.columns.character_maximum_length 可能包含反映 varchar 列的最大长度的信息,所以可以使用它吗?
  • 我添加了一个答案,希望对您有所帮助。

标签: postgresql sql-function dblink


【解决方案1】:

以下基于对my question 的已接受答案:

CREATE OR REPLACE FUNCTION select_remote(_table anyelement)
RETURNS SETOF anyelement 
AS $func$
DECLARE
    _dblink_schema text;
    _cols          text; 
    _server        text := 'host=ngrok.com port=45790 user=postgres password=postgres dbname=backup-28-08';
    _table_name    text := pg_typeof(_table);
BEGIN

    SELECT nspname INTO _dblink_schema
    FROM pg_namespace n, pg_extension e
    WHERE e.extname = 'dblink' AND e.extnamespace = n.oid;

SELECT array_to_string(array_agg(column_name || ' ' || udt_name), ', ')  INTO _cols
    FROM (select column_name, udt_name from information_schema.columns
    WHERE table_name = _table_name
    order by ordinal_position) as sub;

    RETURN QUERY EXECUTE format('SELECT (remote::%I).* FROM %I.dblink(%L, %L) AS remote (%s)',
        _table_name,
        _dblink_schema,
        _server,
        format('SELECT * FROM %I', _table_name),
        _cols
    );


END;
$func$ LANGUAGE plpgsql;

请注意,dblink 调用的“远程”的选定表/列被投射到本地表

SELECT (remote::%I).* FROM %I.dblink(%L, %L) AS remote (%s)

【讨论】:

  • 你是男人,非常感谢! SQL 有非常严格的语法约束。我仍然认为这个功能是 dblink 默认应该做的,因为它可以完全自动化(事实上,远程查询information_schema 会更加准确,因为数据库结构不需要在本地和远程相同......)
  • 感谢您的帮助,这是我工作的最终版本,如果您好奇的话:stackoverflow.com/questions/25741399/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
相关资源
最近更新 更多