2014-09-05 60 views
0

所以我寫了這個方法,其目的是使用dblink的查詢到另一個遠程數據庫具有相同的結構功能的結果類型(從這個職位Specify dblink column definition list from a local existing type啓發,這一個Refactor a PL/pgSQL function to return the output of various SELECT queriesPostgreSQL的:ERROR:查詢的結構不符合使用DBLINK

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接受這些數據?或者返回一些不同的東西來使它工作?

感謝

+0

我現在不能測試這個,所以這只是一個猜測:列udt_name只包含數據類型的名稱。 varchar和varchar(255)是不同的東西,儘管它應該被鑄造。列information_chema.columns.character_maximum_length可以保存信息以反映varchar列的最大長度,所以可能使用那個? – bentrm 2014-09-08 08:35:39

+0

我添加了一個答案,希望它有幫助。 – bentrm 2014-09-08 09:23:53

回答

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) 
+0

你是男人,非常感謝! SQL有嚴格的語法約束。我仍然認爲這個函數是dblink默認做的,因爲它可以完全自動化(事實上,遠程查詢'information_schema'會更加準確,因爲數據庫結構不需要是相同的本地和遠程的) – 2014-09-08 16:03:17

+0

感謝您的幫助,以下是我工作的最終版本,以防萬一您感到好奇:http://stackoverflow.com/questions/25741399/how-to-restore-specific-data-from-previous-backup-on- Postgres的,Heroku的-EG-ACCID/25741400#25741400 – 2014-09-09 09:47:13