本文介绍了从本地现有类型指定 dblink 列定义列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 dblink 在数据库之间移动某些数据.一切都保存完好,但我想知道是否有更方便的方法来定义 dblink 查询结果的列定义列表.我可以这样做:

I am using dblink to move certain data between databases. Everything is save and sound but I am wondering if there is a more convenient way to define the column definition list of a dblink query result. I can do something like this:

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

我正在与之交互的表在两个数据库(远程和本地)中具有相同的架构定义.我在想这样的事情:

The tables I'm interacting with have the same schema definition in both databases (remote & local). I was thinking of something like:

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

或者:

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

列定义列表往往会变得很长.有什么我可能忽略的地方吗?

The column definition list tends to become quite long. Is there something I may have overlooked?

因为在我创建一个小函数作为解决方法之前,这对我来说一直是个问题.

As this has been a problem for me before I created a small function as a work-around.

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

此函数创建并生成一个包装 dblink 调用的函数.它当然不是为了繁重的工作,而是为了方便.如果事实证明根本没有必要,那就太好了.

This function creates and yields a function that wraps the dblink call. It's certainly not meant for heavy lifting but convenience.It would be nice if it turns out it's not necessary at all.

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

推荐答案

您可能需要确保您的类型始终保持同步,但这应该可行:

You might need to make sure that your types are always in sync but this should work:

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

关键是你经常需要括号来确保解析器知道你在处理元组.

The key is that often you need parentheses to ensure that the parser knows you are dealing with tuples.

例如这对我有用:

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

但这会引发语法错误:

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

这篇关于从本地现有类型指定 dblink 列定义列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-16 07:15
查看更多