DBLINK 匹配本地表中的值

G. *_*tho 4 postgresql

我正在尝试运行以下 dblink start 事务;

select dblink_connect('host=remote port=5432 dbname=remote_db user=user password=pass');
insert into local_table (column1, column2 )
select * from dblink(`
    select remote_column1 ltrim(remote_column2, ''TEST'') from remote_table
       where remote_column2 ilike ''TEST%''  
) as t(column1 varchar, column2 varchar) ;
Run Code Online (Sandbox Code Playgroud)

现在上述工作正常,但我遇到了一个挑战: - 我想要而不是硬编码TEST,我希望它从本地表中查询,所以我希望替换TEST为类似SELECT uniq_id from some_local_table的东西它背后的逻辑是我想要获取具有的记录前缀匹配的结果SELECT uniq_id from some_local_table但在插入时修剪前缀以local_table希望有人理解我

Erw*_*ter 6

这实际上应该与相关子查询一起使用:

SELECT dblink_connect(
                'host=remote port=5432 dbname=remote_db user=user password=pass');


INSERT INTO local_table (column1, column2)
SELECT *
FROM   dblink((
          SELECT '
             SELECT remote_column1 ltrim(remote_column2, ''' || uniq_id || ''')
             FROM   remote_table
             WHERE  remote_column2 ILIKE ''' || uniq_id || '%''
             AND    row_counter > ' || coalesce((
                SELECT max(row_counter)
                FROM   yet_another_local_table), -1)
          FROM   some_local_table
          --WHERE <some_condition>
          LIMIT  1  -- make sure it's one row
          )
       ) AS t(column1 varchar, column2 varchar);

SELECT dblink_disconnect();
Run Code Online (Sandbox Code Playgroud)

单引号的元级别和层级可能有点混乱。

这种形式容易受到SQLi 的攻击。确保没有任何不好的东西可以来自some_local_table或使用quote_literal(uniq_id)普通uniq_id.


为了回复评论,我在示例中添加了一个嵌套的相关子查询。它返回一行,所以它应该可以正常工作。也可以通过在FROM子句中左加入它来完成。

请注意,我重写了表达式以制作COALESCE()外部包装器,因此如果没有 rows 查询不会失败yet_another_local_table。您拥有它的方式只会捕获max(row_counter) IS NULL.

可能更容易阅读format()(需要 Postgres 9.1+):

INSERT INTO local_table (column1, column2)
SELECT *
FROM   dblink(
         (SELECT format(
            'SELECT remote_column1 ltrim(remote_column2, %1$L)
             FROM   remote_table
             WHERE  remote_column2 ILIKE %2$L
             AND    row_counter > %3s'
            ,uniq_id,  uniq_id || '%'
            ,COALESCE((
               SELECT max(row_counter)
               FROM   yet_another_local_table), -1)
            )
          FROM   some_local_table
          --WHERE <some_condition>
          LIMIT  1)
   ) AS t(column1 varchar, column2 varchar);
Run Code Online (Sandbox Code Playgroud)