如何在 Oracle PLSQL 和 SQL 中执行字符串插值。给定一个带有命名占位符的文本模板,用变量替换它们

Rax*_*Rax 6 oracle plsql

问题: Oracle如何使用PLSQL进行字符串插值?给定一个包含在大括号内的命名参数的模板,然后用命名参数替换变量。功能类似于C# 字符串插值、Java 等语言。代码应该针对性能进行优化,尽管大多数代码不会经常使用。

大括号是强制性的,因为模板是业务用户定义并保存在表中的。这是公司使用的标准惯例。目标是在 Oracle 本身中“邮件合并”业务文档和片段。

实现: 最好封装在 PLSQL 和 SQL 中运行的函数。对于 SQL,名称值对的 csv 列表将在 example 中传递'name, jane, age, 26'name, value, name, valueETC...

示例用例:

请注意使用双大括号作为文字“{”的转义符。模板将存储在数据库表中,替换变量将在运行时根据复杂的规则导出。下面的例子很简单:

模板='Hi my name is {name}, I am aged {age}, yes {age}! Replaced placeholders {{name}}, {{age}}'

变量=name: jane, age: 26

输出=Hi my name is Jane, I am aged 26, yes 26! Replaced placeholders {name} and {age}

调用虚构包的 PLSQL 示例:

DECLARE v_template NVARCHAR2(500);
        v_name NVARCHAR2(50) := 'Jane';
        v_age NVARCHAR2(50) := '26';
        v_output NVARCHAR2(1000); TYPE ty_dictionary IS TABLE OF NVARCHAR2(1000) INDEX BY VARCHAR2(200);
        v_vars ty_dictionary;
BEGIN

   -- note, escaped double curly braces {{ will output {,
   v_template := 'Hi my name is {name}, I am aged {age}, yes {age}! Replaced placeholders {{name}}, {{age}}';
   v_vars('name') := v_name;
   v_vars('age') := v_age;

   v_output:= pkg_interpolation.fn_format(v_template, v_vars);
   -- should output:
   -- Hi my name is Jane, I am aged 26, yes 26! Replaced placeholders {name} and {age}
   dbms_output.put_line('output: ' || v_output);
END;
Run Code Online (Sandbox Code Playgroud)

0xd*_*xdb 8

尝试这样的事情(db<>fiddle):

declare 
    type vararg is table of varchar2 (96) index by varchar2 (32);
    
    function format (template varchar2, args vararg) return varchar2 is
        key varchar2 (32);
        ret varchar2  (32767) := template;
        pattern varchar2 (32) := '(^|[^{]){(\w+)}([^}]|$)';
    begin
        <<substitute>> loop
            key := regexp_substr  (ret, pattern, 1, 1, null, 2);
            exit substitute when key is null;
            ret := regexp_replace (ret, pattern, 
                '\1'||case when args.exists (key) then args (key) else '?'||key||'?' end||
                '\3', 1, 1);
        end loop;
        return replace (replace (ret, '{{','{'), '}}', '}');
    end;
begin
    dbms_output.put_line ('output: '||format (q'[
{name} said: Hi my name is {name}, I am aged {age}, yes {age}! 
Missing key {somekey}; Replaced placeholders {{name}}, {{age}}. Again I am {age}]',
        vararg ('name' => 'Jane', 
                'age'  => '26')));
end;
/
Run Code Online (Sandbox Code Playgroud)

输出:
Jane 说:嗨,我叫 Jane,我今年 26 岁,是的 26 岁!
缺少钥匙?somekey?;替换了占位符 {name}、{age}。我又26岁了