2013-08-19 31 views
6

Tôi đang sử dụng dblink để di chuyển dữ liệu nhất định giữa các cơ sở dữ liệu. Tất cả mọi thứ là tiết kiệm và âm thanh nhưng tôi tự hỏi nếu có một cách thuận tiện hơn để xác định danh sách định nghĩa cột của một kết quả truy vấn dblink. Tôi có thể làm một cái gì đó như thế này:Chỉ định danh sách định nghĩa cột dblink từ kiểu hiện tại cục bộ

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

Các bảng tôi tương tác có cùng định nghĩa lược đồ trong cả hai cơ sở dữ liệu (từ xa & địa phương). Tôi đã nghĩ đến một cái gì đó như:

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

Hoặc: danh sách định nghĩa

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

Cột có xu hướng trở nên khá dài. Có điều gì tôi có thể đã bỏ qua?

CHỈNH SỬA:

Vì đây là vấn đề đối với tôi trước khi tôi tạo một chức năng nhỏ làm việc xung quanh.

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$; 

Chức năng này tạo và mang lại chức năng kết thúc cuộc gọi dblink. Nó chắc chắn không có nghĩa là để nâng nặng nhưng thuận tiện. Nó sẽ được tốt đẹp nếu nó quay ra nó không cần thiết ở tất cả.

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

Tôi cần sự giúp đỡ của bạn. Tôi đang cố gắng làm những gì ban đầu bạn hỏi nhưng tôi không thể tìm được cách của mình ... –

+0

Tôi đang cố gắng tạo một phiên bản mã tuyệt vời của bạn mà không có chức năng trung gian ('dblink_star_func'), để có thể truy vấn 'select * từ select_remote ('dbname = ben', 'public', 'test') trong đó data = 'success';' ngay lập tức. Bạn có thể xem câu hỏi của tôi ở đó không: http://stackoverflow.com/questions/25691511/postgresql-error-structure-of-query-does-not-match-function-result-type-using? Cảm ơn –

Trả lời

1

Bạn có thể cần phải chắc chắn rằng các loại của bạn luôn luôn được đồng bộ hóa nhưng điều này nên làm việc:

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

Điều quan trọng là thường bạn cần dấu ngoặc đơn để đảm bảo rằng các phân tích cú pháp biết bạn đang đối phó với tuples.

Ví dụ này làm việc cho tôi:

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

Nhưng điều này ném một lỗi cú pháp:

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

Nó không hoạt động trong 'dblink' (Postgres 9.1). Ném lỗi 'một danh sách định nghĩa cột là cần thiết cho các chức năng trở về" kỷ lục "' – ADTC

+0

@ADTC Điều buồn cười tôi đến đây bởi vì thay đổi từ 'dblink' chức năng để' dblink_connect' và bây giờ là không làm việc. –

+0

Xem giải pháp của @ Rémy Baron bên dưới. Điều đó làm việc trong Postgres 9.6. – kirikaza

4

Hãy thử một cái gì đó như thế này:

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

Ví dụ (có được bảng số liệu thống kê từ cơ sở dữ liệu khác):

select (rec).* from dblink('dbname=foreignDb','select t1 from 
    pg_stat_all_tables t1') t2 (rec pg_stat_all_tables) 
Các vấn đề liên quan