Эквивалент Oracle 'printf'

есть ли эквивалент или альтернативные следующий?

SELECT mix_type || ' (' || mix_num || ')' as description
  FROM acid_batch
 WHERE mix_num < 10

есть ли у Oracle что-то вроде форматирования стиля printf?

SELECT printf("%s (%s)", mix_type, mix_num) as description,
  FROM acid_batch
 WHERE mix_num < 10

5 ответов


нет нет встроенных функций Oracle, которые применяют строку форматирования таким образом. Хотя было бы легко написать пользовательскую функцию для этого конкретного примера, написание реализации printf на основе PL/SQL было бы сложным.

Если у вас есть частая потребность в этом, возможно, вы могли бы написать функцию Oracle, которая обертывает вызов Java для более богатой среды обработки строк.


самое близкое стандартное приближение к printf для Oracle, которое я могу придумать, это utl_lms.format_message. Однако он не будет работать в SQL-операторах, то есть это нормально:

begin
  dbms_output.put_line(
    utl_lms.format_message('hello %s, the number is %d', 'world', 42)
  );
end;
/

но это ORA-00902: недопустимый тип данных ошибка:

select utl_lms.format_message('hello %s, the number is %d', 'world', 42)
  from dual

еще одна идея для вас: я нашел замену, чтобы быть полезным для такого рода вещей, особенно когда шаблон сложный:

SELECT REPLACE(REPLACE(
        '%mix_type% (%mix_num%)' /*template*/
       ,'%mix_type%', mix_type)
       ,'%mix_num%' , mix_num ) as description,
FROM   acid_batch
WHERE  mix_num < 10

единственный недостаток - вам нужно добавить как можно больше REPLACE(как есть переменные для замены - но, по крайней мере, вам нужно иметь только одну переменную, независимо от того, сколько раз она появляется в шаблоне.

(Примечание:нет никакого особого значения для использования " % " в качестве разделителя, это просто личное соглашение мой-вы можете выбрать другой шаблон, например <mix_type> или [mix_type])

для этого конкретного случая это выглядит как перебор, но в некоторых случаях это может сделать вещи намного проще, например:

template := 'bla bla %a% %b% %a%';
output := REPLACE(REPLACE(template
    ,'%a%', some_complex_expression)
    ,'%b%', b);

сравнить с:

output := 'bla bla ' || some_complex_expression || ' ' || b || ' ' || some_complex_expression;

Я сделал простой движок шаблонов с именем ora_te (на GitHub) для Oracle SQL / PLSQL. С его помощью ваша цель может быть достигнута следующими способами:

неэффективная реализация с несколькими разборами строки шаблона:

with acid_batch as (
  select rownum as mix_type, rownum + 2 as mix_num 
  from all_objects
  where rownum < 10
)
--
SELECT pk_te.substitute(' ()', ty_p( mix_type, mix_num ) ) as description
FROM acid_batch
WHERE mix_num < 10;

эффективная реализация с однократной компиляцией (разбором):

with acid_batch as (
  select rownum as mix_type, rownum + 2 as mix_num 
  from all_objects
  where rownum < 10
),
--
o as ( 
  select ty_te.compile_numbered( ' ()' ) te from dual
)
SELECT pk_te.substitute( o.te, ty_p( mix_type, mix_num ) ) as description
FROM acid_batch, o
WHERE mix_num < 10;

BTW он также поддерживает именованные заполнители.


вы можете разрешить его в select.

SELECT mix_type || '(' ||  mix_num || ')' as description,
FROM acid_batch
WHERE mix_num < 10

вы также должны взглянуть на функции

to_char

даты

to_number

поскольку они дают вам более тонкую гранулярность о том, как вы хотите, чтобы вещи были представлены.