【问题标题】:Split the string into variables将字符串拆分为变量
【发布时间】:2015-11-30 12:37:12
【问题描述】:

执行下面的 select 后,如何赋值给变量。

如果输入字符串是 "x/y/z" ,我必须将 "x" 存储到变量 say A 中, "y" 存储到变量 B 和 z 到变量 "C" 中。

假设如果字符串是“x/z”,那么我必须将“x”存储到变量 A 中,但将 z 存储到变量“c”中。

在所有其他情况下,假设输入字符串仅为“x”或“x/y/z/z”,则无法存储任何内容

 SELECT REGEXP_SUBSTR(<<Input String>>, '[^/]+', 1, LEVEL)
                               FROM DUAL
                    CONNECT BY REGEXP_SUBSTR((<<Input String>>,  '[^/]+', 1, LEVEL)

 IS NOT NULL;

【问题讨论】:

  • 这个问题还不清楚。要访问查询的元素,您应该阅读游标,它可以通过几种方式完成。例如,您可以在 FOR 循环中迭代元素并将值赋给变量。

标签: oracle plsql


【解决方案1】:

我不会使用 SQL,而是使用 PL/SQL,因为似乎不需要引入不必要的上下文切换:

declare
  v_a varchar2(10);
  v_b varchar2(10);
  v_c varchar2(10);
  v_string varchar2(33);
  procedure split_string (p_string in varchar2,
                          p_a out varchar2,
                          p_b out varchar2,
                          p_c out varchar2)
  is
  begin
    if regexp_count(p_string, '/') = 2 then
      p_a := regexp_substr(p_string, '[^/]+', 1, 1);
      p_b := regexp_substr(p_string, '[^/]+', 1, 2);
      p_c := regexp_substr(p_string, '[^/]+', 1, 3);
    elsif regexp_count(p_string, '/') = 1 then
      p_a := regexp_substr(p_string, '[^/]+', 1, 1);
      p_c := regexp_substr(p_string, '[^/]+', 1, 2);
    end if;
  end;
begin
  v_string := 'x/y/z';
  split_string(v_string, v_a, v_b, v_c);
  dbms_output.put_line('v_string = "'||v_string||'", v_a = "'||v_a||'", v_b = "'||v_b||'", v_c = "'||v_c||'"');

  v_string := 'x/y';
  split_string(v_string, v_a, v_b, v_c);
  dbms_output.put_line('v_string = "'||v_string||'", v_a = "'||v_a||'", v_b = "'||v_b||'", v_c = "'||v_c||'"');

  v_string := 'x/y/z/1';
  split_string(v_string, v_a, v_b, v_c);
  dbms_output.put_line('v_string = "'||v_string||'", v_a = "'||v_a||'", v_b = "'||v_b||'", v_c = "'||v_c||'"');

  v_string := 'x';
  split_string(v_string, v_a, v_b, v_c);
  dbms_output.put_line('v_string = "'||v_string||'", v_a = "'||v_a||'", v_b = "'||v_b||'", v_c = "'||v_c||'"');
end;
/

v_string = "x/y/z", v_a = "x", v_b = "y", v_c = "z"
v_string = "x/y", v_a = "x", v_b = "", v_c = "y"
v_string = "x/y/z/1", v_a = "", v_b = "", v_c = ""
v_string = "x", v_a = "", v_b = "", v_c = ""

如果您绝对必须使用 SQL,则无需使用 connect by - 您只需将结果分成 3 列以匹配您要输入结果的 3 个变量:

with strings as (select 'x/y/z' str from dual union all
                 select 'x/y' str from dual union all
                 select 'x/y/z/1' str from dual union all
                 select 'x' str from dual)
select str,
       case when regexp_count(str, '/') in (1, 2) then regexp_substr(str, '[^/]+', 1, 1) end v_a,
       case when regexp_count(str, '/') = 2 then regexp_substr(str, '[^/]+', 1, 2) end v_b,
       case when regexp_count(str, '/') = 2 then regexp_substr(str, '[^/]+', 1, 3)
            when regexp_count(str, '/') = 1 then regexp_substr(str, '[^/]+', 1, 2) 
       end v_c
from   strings;

STR     V_A                   V_B                   V_C                  
------- --------------------- --------------------- ---------------------
x/y/z   x                     y                     z                    
x/y     x                                           y                    
x/y/z/1                                                                  
x      

【讨论】:

    【解决方案2】:

    注意,regex_substr 使用'[^/]+' 格式解析字符串元素do not handle null list elements。这是一种从处理空值的列表中提取特定元素的方法,可以是put into a function for reuse(这会获取分隔符为斜杠的第一个元素):

    REGEXP_SUBSTR(string_in, '(.*?)(/|$)', 1, 1, NULL, 1);
    

    请参见上面的链接,但调用类似这个简单示例的方法,其中列表元素由名为 get_list_element 的函数按顺序提取并分配给变量。也许您可以将此逻辑应用于您的需求:

    SQL> declare
      2  a varchar2(1);
      3  b varchar2(1);
      4  c varchar2(1);
      5  begin
      6    select get_list_element('x/y/z', 1, '/'),
      7           get_list_element('x/y/z', 2, '/'),
      8           get_list_element('x/y/z', 3, '/')
      9    into a, b, c
     10    from dual;
     11
     12    dbms_output.put_line('a: ' || a);
     13    dbms_output.put_line('b: ' || b);
     14    dbms_output.put_line('c: ' || c);
     15  end;
     16  /
    a: x
    b: y
    c: z
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    或者修复你最初尝试将元素变成行的方法:

    SQL> with tbl(str) as (
      2    select 'x/y/z' from dual
      3  )
      4  select regexp_substr(str, '(.*?)(/|$)', 1, level, null, 1) element
      5  from tbl
      6  connect by level <= regexp_count(str, '/')+1;
    
    ELEME
    -----
    x
    y
    z
    
    SQL>
    

    【讨论】:

      猜你喜欢
      • 2019-02-05
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2015-08-17
      • 1970-01-01
      相关资源
      最近更新 更多