【问题标题】:Execute text string returned from function as a query执行从函数返回的文本字符串作为查询
【发布时间】:2021-08-12 23:02:26
【问题描述】:

我有一个带有以下“签名”的函数:

CREATE OR REPLACE FUNCTION iterate_test()
RETURNS text
LANGUAGE plpgsql

...

以文本形式返回查询:

SELECT DISTINCT(t1.date) AS date, AMD.adjusted_close AS AMD, GME.adjusted_close AS GME FROM clean_daily AS t1 INNER JOIN clean_daily AS AMD ON t1.date=AMD.date AND AMD.ticker='AMD' INNER JOIN clean_daily AS GME ON AMD.date=GME.date AND GME.ticker='GME' ORDER BY t1.date DESC;

如何将此字符串作为查询执行?我试过这样执行:

EXECUTE iterate_test();
EXECUTE QUERY iterate_test();

但我无法让它工作。如何以文本形式执行数据查询?

完整功能代码:

CREATE OR REPLACE FUNCTION iterate_test()
RETURNS text
LANGUAGE plpgsql
AS
$$
    DECLARE
        temprow record;
        str_query text := 'SELECT DISTINCT(t1.date) AS date';
        prev_table text := 't1';
    BEGIN
        FOR temprow IN SELECT * FROM portfolios WHERE user_name='snigelnmjau'
        LOOP
            str_query := str_query || format(', %s.adjusted_close AS %s', temprow.ticker, temprow.ticker);
        END LOOP;

        str_query := str_query || format(' FROM clean_daily AS t1 ');

        FOR temprow IN SELECT * FROM portfolios WHERE user_name='snigelnmjau'
        LOOP
            str_query := str_query || format(E'INNER JOIN clean_daily AS %s ON %s.date=%s.date AND %s.ticker=''%s'' ', temprow.ticker, prev_table, temprow.ticker, temprow.ticker, temprow.ticker);
            prev_table := temprow.ticker;
        END LOOP;
        str_query := str_query || 'ORDER BY t1.date DESC;';

        --EXECUTE str_query;
        RETURN str_query;
    END;
$$;

【问题讨论】:

  • 与您的问题无关,但是:distinct 不是函数。它始终适用于选择列表中的所有列。用括号括住其中一列不会改变任何东西并且是无用的。 distinct (a),bdistinct a,(b)distinct a,b 相同

标签: sql postgresql


【解决方案1】:

回答您的问题:使用RETURN QUERY EXECUTE。见:

您的函数有几个修复,包括一个针对核心问题的修复:

CREATE OR REPLACE FUNCTION pg_temp.iterate_test()
  RETURNS SETOF text  -- !!
  LANGUAGE plpgsql AS
$func$
DECLARE
   temprow record;
   str_query text := 'SELECT DISTINCT t1.date';  -- !!
   prev_table text := 't1';
BEGIN
   FOR temprow IN
      SELECT * FROM portfolios WHERE user_name = 'snigelnmjau'
   LOOP
      str_query := str_query || format(', %1$I.adjusted_close AS %1$I', temprow.ticker);  -- !!
   END LOOP;

   str_query := str_query || ' FROM clean_daily AS t1 ';  -- !!

   FOR temprow IN
      SELECT * FROM portfolios WHERE user_name = 'snigelnmjau'
   LOOP
      str_query := str_query || format('JOIN clean_daily AS %1$I ON %2$I.date=%1$I.date AND %1$I.ticker=%1$L ', temprow.ticker, prev_table); -- !!
      prev_table := temprow.ticker;
   END LOOP;
   str_query := str_query || 'ORDER BY t1.date DESC';

   RETURN QUERY EXECUTE str_query;  -- !!!!
END
$func$;

但整个语句可能在单个SELECT 语句中生成而无需循环(两次)。为什么DISTINCT

此外,我不相信我们需要动态 SQL。一个简单的查询可能是可能的。

【讨论】:

    猜你喜欢
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 2021-12-30
    • 2018-03-14
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多