如何在SQL中将字符串标记化后将其反转

如何在SQL中将字符串标记化后将其反转,sql,oracle,Sql,Oracle,我需要标记一个字符串并在SQL中反转它。例如,如果字符串是'L3:L2:L1:L0',我需要将其反转为'L0:L1:L2:L3'。标记化可以使用分隔符“:”完成,然后将其反转。请建议在SQL中使用相同的函数 提前感谢,, 吉莎类似于: SELECT REGEXP_REPLACE('L1:L2:L3', '([[:alnum:]]{1,}):([[:alnum:]]{1,}):([[:alnum:]]{1,})', '\3 \

我需要标记一个字符串并在SQL中反转它。例如,如果字符串是'L3:L2:L1:L0',我需要将其反转为'L0:L1:L2:L3'。标记化可以使用分隔符“:”完成,然后将其反转。请建议在SQL中使用相同的函数

提前感谢,, 吉莎

类似于:

SELECT
  REGEXP_REPLACE('L1:L2:L3',
                 '([[:alnum:]]{1,}):([[:alnum:]]{1,}):([[:alnum:]]{1,})',
                 '\3 \2 \1') "REGEXP_REPLACE"
from dual
但您可能需要详细说明令牌的构成。

类似于:

SELECT
  REGEXP_REPLACE('L1:L2:L3',
                 '([[:alnum:]]{1,}):([[:alnum:]]{1,}):([[:alnum:]]{1,})',
                 '\3 \2 \1') "REGEXP_REPLACE"
from dual

但是您可能需要详细说明令牌的构成。

如果可能,最好的解决方案是更改数据,以便将每个值存储在不同的行中

如果这不起作用,您可以创建一个PL/SQL函数


如果需要纯SQL解决方案,通常必须将每个值拆分为多行(与对象表交叉连接,或按级别连接,如果可能,最好的解决方案是更改数据,以便将每个值存储在不同的行中)

如果这不起作用,您可以创建一个PL/SQL函数


如果您想要纯SQL解决方案,通常必须将每个值拆分为多行(与对象表交叉连接,或按级别连接)这里有一个使用PL/SQL流水线函数拆分元素的解决方案:

create type t_str_array as table of varchar2(4000);

create or replace function split_str (p_str in varchar2,
                                      p_separator in varchar2 := ':') return t_str_array pipelined
as
  l_str varchar2(32000) := p_str || p_separator;
  l_pos pls_integer;
begin

  loop
    l_pos := instr(l_str, p_separator);
    exit when (nvl(l_pos,0) = 0);
    pipe row (ltrim(rtrim(substr(l_str,1,l_pos-1))));
    l_str := substr(l_str, l_pos+1);
  end loop;

  return;

end split_str;
select * from table(split_str('L3:L2:L1:L0')) order by column_value
然后使用普通SQL对元素进行排序:

create type t_str_array as table of varchar2(4000);

create or replace function split_str (p_str in varchar2,
                                      p_separator in varchar2 := ':') return t_str_array pipelined
as
  l_str varchar2(32000) := p_str || p_separator;
  l_pos pls_integer;
begin

  loop
    l_pos := instr(l_str, p_separator);
    exit when (nvl(l_pos,0) = 0);
    pipe row (ltrim(rtrim(substr(l_str,1,l_pos-1))));
    l_str := substr(l_str, l_pos+1);
  end loop;

  return;

end split_str;
select * from table(split_str('L3:L2:L1:L0')) order by column_value

下面是一个使用PL/SQL流水线函数拆分元素的解决方案:

create type t_str_array as table of varchar2(4000);

create or replace function split_str (p_str in varchar2,
                                      p_separator in varchar2 := ':') return t_str_array pipelined
as
  l_str varchar2(32000) := p_str || p_separator;
  l_pos pls_integer;
begin

  loop
    l_pos := instr(l_str, p_separator);
    exit when (nvl(l_pos,0) = 0);
    pipe row (ltrim(rtrim(substr(l_str,1,l_pos-1))));
    l_str := substr(l_str, l_pos+1);
  end loop;

  return;

end split_str;
select * from table(split_str('L3:L2:L1:L0')) order by column_value
然后使用普通SQL对元素进行排序:

create type t_str_array as table of varchar2(4000);

create or replace function split_str (p_str in varchar2,
                                      p_separator in varchar2 := ':') return t_str_array pipelined
as
  l_str varchar2(32000) := p_str || p_separator;
  l_pos pls_integer;
begin

  loop
    l_pos := instr(l_str, p_separator);
    exit when (nvl(l_pos,0) = 0);
    pipe row (ltrim(rtrim(substr(l_str,1,l_pos-1))));
    l_str := substr(l_str, l_pos+1);
  end loop;

  return;

end split_str;
select * from table(split_str('L3:L2:L1:L0')) order by column_value

由于您使用Oracle,因此很容易生成一个java存储过程,该过程传递字符串,然后

  • 分门别类
  • 向后循环数组并合并结果字符串
  • 返回结果字符串

  • 这将是一个小的java代码,速度不会比pl/sql慢。但是如果您想使用pl/sql,您也可以使用DBMS_实用程序.table_to_comma/.comma_to_table。但是作为函数名,让我们假设->您必须使用“,”作为令牌。

    因为您使用Oracle,所以很容易生成一个java存储过程,传递字符串,然后

  • 分门别类
  • 向后循环数组并合并结果字符串
  • 返回结果字符串

  • 这将是一个小java代码,速度不会比pl/sql慢。但是如果您想使用pl/sql,也可以使用DBMS_实用程序.table_to_comma/.comma_to_table。但是作为函数名,让我们假设->您必须使用“,”作为标记。

    将CSV字符串中的元素转换为记录,并抑制所有空值:

    SELECT  REGEXP_SUBSTR( :csv,'[^,]+', 1, LEVEL )  AS element
    FROM    dual
    CONNECT BY REGEXP_SUBSTR( :csv, '[^,]+', 1, LEVEL ) IS NOT NULL ;
    

    将CSV字符串中的元素转换为记录,保留空值(但不保留顺序):

    选择REGEXP_SUBSTR(:csv,[^,]+',1,LEVEL)作为元素
    来自双重
    
    按级别连接将CSV字符串中的元素转换为记录,抑制所有空值:

    SELECT  REGEXP_SUBSTR( :csv,'[^,]+', 1, LEVEL )  AS element
    FROM    dual
    CONNECT BY REGEXP_SUBSTR( :csv, '[^,]+', 1, LEVEL ) IS NOT NULL ;
    

    将CSV字符串中的元素转换为记录,保留空值(但不保留顺序):

    选择REGEXP_SUBSTR(:csv,[^,]+',1,LEVEL)作为元素
    来自双重
    
    通过级别连接改进Kevan的答案,以下是我尝试的:

    select listagg(TOKEN, ':') WITHIN GROUP (ORDER BY TOKEN_LEVEL DESC)
    from
    (SELECT  REGEXP_SUBSTR( myStr,'[^:]+', 1, LEVEL )  AS TOKEN, LEVEL TOKEN_LEVEL
    FROM    dual
    CONNECT BY REGEXP_SUBSTR( myStr, '[^:]+', 1, LEVEL ) IS NOT NULL);
    

    根据Kevan的回答,我尝试了以下内容:

    select listagg(TOKEN, ':') WITHIN GROUP (ORDER BY TOKEN_LEVEL DESC)
    from
    (SELECT  REGEXP_SUBSTR( myStr,'[^:]+', 1, LEVEL )  AS TOKEN, LEVEL TOKEN_LEVEL
    FROM    dual
    CONNECT BY REGEXP_SUBSTR( myStr, '[^:]+', 1, LEVEL ) IS NOT NULL);
    


    Oracle数据库。抱歉,忘记在问题中提及。这是需要在SQL qusry中完成还是可以使用PL/SQL完成?Oracle数据库。抱歉,忘记在问题中提及。这是需要在SQL qusry中完成还是可以使用PL/SQL完成?如果我的输入字符串为“United States.CA.Santacrara.Redwood Shores.XXX.YYYY”,则此操作无效,空格会产生问题。如果有一个转义空格的解决方案会更好。谢谢。您可以使用split_str函数的第二个参数指定用于分隔字符串每个元素的字符。但是请注意,如果您的实际需求是反转字符串(不仅仅是按字母顺序、升序或降序排序),您需要使用除“order by”之外的其他内容。我已经向您展示了如何使用流水线函数标记字符串,以便在任何SQL语句中使用。太好了,这正是我要找的。Thx!如果我的输入字符串是“United States.CA.Santacrara.Redwood Shores.XXX.YYYY”,空格会产生一个问题。如果有一个逃逸空格的解决方案会更好。谢谢。您可以使用split_str函数的第二个参数来指定用于分隔字符串每个元素的字符。但是请注意,如果您的实际需求是反转字符串(不仅仅是按字母顺序、升序或降序排序),您需要使用除“order by”之外的其他内容。我已经向您展示了如何使用流水线函数标记字符串,以便在任何SQL语句中使用。非常好,这正是我要找的。Thx!这不适用于测试输入”United States.CA.Santacrara.Redwood Shores.XXX.YYY“必须转义猜测空间。这不适用于测试输入”United States.CA.Santacrara.Redwood Shores.XXX.YYY“必须转义猜测空间”。最好的解决方案是更改数据,使每个值存储在不同的行中”-a.k.a.满足第一个范式(1NF)!你们不是都指“字段”吗?还是说使用一个键并从另一个表中加入此数据?我认为后者允许不同数量的令牌…@deed02392我指的是加入另一个表。这会更费力,但会更灵活。取决于令牌的数量,“令牌”具体是什么“这意味着在此上下文中,添加TOKEN1、TOKEN2等列可能更有意义。如果不了解更多有关模型的信息,很难说哪种解决方案更好。但这两种解决方案都比存储分隔字符串好得多。如果没有1NF,您可能会读写文本文件,而不是使用数据库。“最好的解决方案是更改数据,以便将每个值存储在不同的行中”-a.k.a.满足第一范式(1NF)!你们不是都指“字段”吗?还是说使用一个键并从另一个表中加入此数据?我想后者允许不同数量的令牌…@deed02392我指的是加入另一个表