2013-08-19 17 views
6

Veritabanları arasında belirli verileri taşımak için dblink kullanıyorum. Her şey kaydediliyor ve ses geliyor ama bir dblink sorgu sonucunun sütun tanımlama listesini tanımlamak için daha uygun bir yol olup olmadığını merak ediyorum. Böyle bir şey yapabilirsiniz:Yerel varolan bir türden dblink sütun tanımı listesini belirtin

SELECT * 
FROM dblink('dbname=remote', 'select * from test') 
AS t1(id integer, data text); 

ben etkileşim ediyorum tablolar her iki veritabanları (uzaktan & yerel) aynı şema tanım var. Ben böyle bir şey düşünüyordum:

SELECT * 
FROM dblink('dbname=remote', 'select * from test') 
AS t1 LIKE public.test; 

Veya:

SELECT * 
FROM dblink('dbname=remote', 'select * from test') 
AS t1::public.test; 

kolon tanımlama listesi oldukça uzun olma eğilimindedir. Gözardı ettiğim bir şey var mı?

DÜZENLEME: İşle etrafında gibi küçük işlevi yaratmadan önce bu benim için bir sorun olmuştur gibi

.

CREATE OR REPLACE FUNCTION dblink_star_func(_conn text, _schema_name text, _table_name text) 
RETURNS text 
LANGUAGE PLPGSQL 
VOLATILE STRICT 
AS $function$ 
    DECLARE  
     _dblink_schema text; 
     _cols   text; 
     _q    text; 
     _func_name  text := format('star_%s', $3); 
     _func   text;   
    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 information_schema.columns 
     WHERE table_schema = $2 AND table_name = $3; 

     _q := format('SELECT * FROM %I.dblink(%L, %L) AS remote (%s)', 
      _dblink_schema, 
      _conn, 
      format('SELECT * FROM %I.%I', $2, $3), 
      _cols 
     ); 

     _func := $_func$ 
      CREATE OR REPLACE FUNCTION %s() 
      RETURNS SETOF %I.%I 
      LANGUAGE SQL 
      VOLATILE STRICT 
      AS $$ %s; $$ 
     $_func$; 

     EXECUTE format(_func, _func_name, $2, $3, _q); 

     RETURN _func_name; 
    END; 
$function$; 

Bu işlev, dblink çağrısını saran bir işlev oluşturur ve üretir. Kesinlikle ağır kaldırma için değil, kolaylık anlamına gelmez.İhtiyaç duyulmadığı ortaya çıktığında hoş olurdu.

> select dblink_star_func('dbname=ben', 'public', 'test'); 
┌──────────────────┐ 
│ dblink_star_func │ 
├──────────────────┤ 
│ star_test  │ 
└──────────────────┘ 
(1 row) 

> select * from star_test() where data = 'success'; 
┌────┬─────────┐ 
│ id │ data │ 
├────┼─────────┤ 
│ 1 │ success │ 
└────┴─────────┘ 
(1 row) 
Sen tipleri her zaman senkronize ancak bu çalışması gerekir emin olmak gerekebilir
+0

Yardımınıza ihtiyacım var. Başlangıçta sorduğum şeyi yapmaya çalışıyorum ama yolumu bulamıyorum ... –

+0

Arabuluculuk ('dblink_star_func') olmadan harika kodunuzun bir versiyonunu sorgulayabilmek için strugling yapıyorum select_remote öğesinden select seçin ('dbname = ben', 'public', 'test'), data = 'success'; '' doğrudan. Soruma bir göz atabilir misiniz: http://stackoverflow.com/questions/25691511/postgresql-error-structure-of-query-does-not-match-function-result-type-using? Teşekkürler –

cevap

1

:

SELECT (t1::test).* 
    FROM dblink('dbname=remote', 'select * from test') AS t1; 

anahtar sıklıkla ayrıştırıcı sizinle ilgilenen sahibi olmasını sağlamak için parantez gerektiğidir Tuplelerin.

CREATE TABLE test (id int, test bool); 
select (t1::test).* from (select 1, true) t1; 

Ama bu bir sözdizimi hatası atar:

Örneğin bu benim için çalışıyor

select t1::test.* from (select 1, true) t1; 
+5

'dblink'de çalışmaz (Postgres 9.1). Hata atar \ "Kayıt" döndüren işlevler için bir sütun tanımı listesi gereklidir " – ADTC

+0

@ADTC" dblink "işlevinden" dblink_connect "'e geçtiğinden ve şu an çalışmıyorsa buraya geldiğim komik şey. –

+0

Aşağıdaki @ Rémy Baron çözümüne bakın. Bu Postgres 9.6'da çalışıyor. – kirikaza

4

böyle bir şey deneyin:

select (rec).* from dblink('dbname=...','select myalias from foreign_table 
    myalias') t1 (rec local_type) 

Örnek (gelen tablolar istatistikleri almak diğer veritabanı):

select (rec).* from dblink('dbname=foreignDb','select t1 from 
    pg_stat_all_tables t1') t2 (rec pg_stat_all_tables) 
İlgili konular