【问题标题】:Postgres format string using arrayPostgres 使用数组格式化字符串
【发布时间】:2014-01-09 09:52:27
【问题描述】:

我正在寻找一种使用数组格式化字符串的简单方法,如下所示:

select format_using_array('Hello %s and %s', ARRAY['Jane', 'Joe']);

 format_using_array
--------------------
Hello Jane and Joe
(1 row)

有一个格式函数,但它需要显式参数,我不知道数组中有多少项。我想出了一个这样的功能:

CREATE FUNCTION format_using_array(fmt text, arr anyarray) RETURNS text
    LANGUAGE plpgsql
AS $$
    declare 
        t text;
        length integer;
    begin
        length := array_length(arr, 1);
        t := fmt;
        for i in 1..length loop
           t := regexp_replace(t, '%s', arr[i]);
        end loop;

        return t;
    end
$$;

但也许有一种我不知道的更简单的方法,这是我使用 pgsql 的第一天。

【问题讨论】:

  • 如果可以的话,检查 orafce 扩展 github.com/orafce/orafce - plvsubst.string 正是你想要的
  • @PavelStehule 看起来很完美,但我假设因为这是一个扩展,所以没有内置函数。我不确定能否在我的项目中编译和安装扩展。
  • Orafce 位于 RHEL 或 DEB 存储库中。

标签: arrays postgresql format


【解决方案1】:

如果您错过了它,Postgres 带有一个内置函数,该函数基本上包装了 C 的 sprintf,它接受任意数量的参数,速度更快,并且比您尝试创建的更简洁:

select format('Hello %s and %s', 'Jane', 'Joe');       -- Hello Jane and Joe

考虑到它允许位置参数而不是依赖regexp_replace(),并且支持格式化标志作为奖励,它也不会那么容易出错:

select format('Hello %2$s and %1$s', 'Jane', 'Joe');   -- Hello Joe and Jane

http://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT

无论如何,如果你真的坚持想要这样一个数组驱动的函数,你可能需要unnest() 数组来构建(并正确转义)一个 SQL 字符串,以便最终调用上面提到的format()使用动态SQL:

http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

【讨论】:

  • 正如我在问题中所说:格式需要显式参数,我不能从表中选择格式(消息,arr[1],arr[2]),因为表中的消息有时需要 2有时需要数组中的 4 个参数。
  • 正确。这就是为什么您需要运行诸如select escape_literal(val) || ', ' from unnest(arr) val; 之类的复杂查询以构建_values_string 变量的原因,然后您将执行如下操作:execute 'select format(' || escape_literal(_format_string) || ', ' || _values_string || ')' — 或按此顺序执行的操作。这将是非常丑陋的。而且慢。恕我直言,您可能应该重新考虑这个想法并使用内置的format() 函数。
【解决方案2】:

您可以使用格式函数和 VARIADIC 关键字。需要9.3,可变参数函数实现中fixed bug在哪里

postgres=# SELECT format('%s %s', 'first', 'second');
    format    
--------------
 first second
(1 row)

postgres=# SELECT format('%s %s', ARRAY['first', 'second']);
ERROR:  too few arguments for format
postgres=# SELECT format('%s %s', VARIADIC ARRAY['first', 'second']);
    format    
--------------
 first second
(1 row)

【讨论】:

  • 我想知道是否可以在我创建预先传递到格式的数组的地方做类似的事情。喜欢variables text[]; FOR col IN SELECT column_name FROM information_schema.columns WHERE table_name = TG_TABLE_NAME LOOP variables := array_append(variables, ('NEW.' || col)); END LOOP; EXECUTE format(insert_query, VARIADIC variables); -- there it is very likely wrong, I don't know how to tell it to use 'variables' as variadic array
  • 我刚刚在其他地方找到了解决问题的方法 (stackoverflow.com/questions/7914325/…) 所以我使用 '($1).col 然后使用 NEW。我们不会删除,所以我们不需要关心 NEW/OLD 的区别。
  • 太糟糕了,您不能在数组中包含格式字符串,例如select format(variadic array['It is %s.', 'nice'])。我在 CSV 样式的字符串中有格式字符串和参数,例如'It is %s and %s.|nice|warm'
  • @user9645 - 你可以使用 array_to_string 函数 - 下面的代码不是很有效(由于重复解析) - 它是一个班轮,但它是一个例子,它是如何工作的 - select format((array_to_string(str, '|')[1], variadic (array_to_string(str,'|')[2:])) - 也许是 PostgreSQL由于语法[x:] 需要 9.5
  • @user9645:我的错误,对不起-应该有功能string_to_array:以下功能正在工作:create or replace function fmt(text) returns text as $$ select format((string_to_array($1, '|'))[1], variadic (string_to_array($1, '|'))[2:]) $$ language sql;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多