ホームページ データベース mysql チュートリアル oracel中字符串分割成集合详解

oracel中字符串分割成集合详解

Jun 07, 2016 pm 05:49 PM
文字列の分割

文章分享一篇关于自己的学习笔记,oracel中字符串分割成集合详解有需要学习的同学可以看看。

首先分别使用两种方式构造两个函数

 代码如下 复制代码

-- use conventional plsql
create or replace function f_str2list_pls
(
  p_str       varchar2,
  p_separator varchar2 default ','
) return my_tk_str_tab_type is
  l_idx  pls_integer := 0;
  l_str  varchar2(32767) := trim(p_str);
  l_elmt varchar2(100) := null;
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
begin
  while l_str is not null loop
    l_idx := instr(l_str, p_separator);
    if l_idx = 0 then
      l_elmt := l_str;
      l_str  := null;
    else
      l_elmt := substr(l_str, 1, l_idx - 1);
      l_str  := substr(l_str, l_idx + 1);
    end if;
 
    l_list.extend;
    l_list(l_list.last) := trim(l_elmt);
  end loop;

  return l_list;
end;
/

-- use single sql
create or replace function f_str2list_sql
(
  p_str       varchar2,
  p_separator varchar2 default ','
) return my_tk_str_tab_type is
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
begin
  substr(a.str,
                instr(p_separator || a.str, p_separator, 1, rn),
                instr(a.str || p_separator, p_separator, 1, rn) -
                instr(p_separator || a.str, p_separator, 1, rn)) q
    bulk collect into l_list
    from (select p_str as str from dual) a,
         (select rownum rn from dual connect by rownum    where instr(p_separator || a.str, p_separator, 1, rn) > 0;

  return l_list;
end;
/

 

 


确认两种方法完成同样的功能

 

----------------------------------------------------

 代码如下 复制代码

-- same result
declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str varchar2(1000) := 'a,b,c';
begin
  l_list := f_str2list_pls(l_str,',');
  for i in 1..l_list.count loop
    dbms_output.put_line(l_list(i));
  end loop;
 
  dbms_output.put_line('');
  l_list := f_str2list_sql(l_str,',');
  for i in 1..l_list.count loop
    dbms_output.put_line(l_list(i));
  end loop;
end;
/

SQL> set serveroutput on
a
b
c
 
a
b
c

 

 

 

 

 

我们知道在PL/SQL和SQL里面,varchar2类型的长度限制是不同的。那么这两种方法是否也存在同样的限制?验证一下

先测试PL/SQL版本

 

-- 这里使用单个字母作为元素,加上必要的逗号分割符,一个元素占用长度2. PL/SQL中上限32767。当取(32767/2 = 16383)个元素的时候,运行成功
----------------------------------------------------

 代码如下 复制代码

-- pls versions tring length limit
declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 16383;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;
  l_str := substr(l_str, 2);

   l_list := f_str2list_pls(l_str, ',');
end;
/

PL/SQL procedure successfully completed

-- 增加一个元素,当取(16384)个元素的时候,超过了varchar2的限制,所以无法运行。(构造字符串就报错了,这个时候其实还没有调用f_str2list_pls)
 代码如下 复制代码

declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 16384;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;

  l_list := f_str2list_pls(l_str, ',');
end;
/

ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 9

-- 修改一下代码,实际调用这个函数。从结果可以看到,f_str2list_pls()内部报超长错误
declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 16383;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;

  l_list := f_str2list_pls(l_str||',a', ',');
end;
 
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "T2.F_STR2LIST_PLS", line 7
ORA-06512: at line 12

 

 

 


下面测试SQL版本

 

 代码如下 复制代码

-- 因为SQL中varchar2上限是4000,所以使用2000个元素。一切正常。
----------------------------------------------------
-- sql versions tring length limit
declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 2000;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;
  l_str := substr(l_str, 2);

   l_list := f_str2list_sql(l_str, ',');
end;
/

PL/SQL procedure successfully completed

-- 直接增加到2001个元素,发现f_str2list_sql()内部报错,说明构造字符串的成功传入,但是函数不能处理
 代码如下 复制代码

declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 2001;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;
  l_str := substr(l_str, 2);

   l_list := f_str2list_sql(l_str, ',');
end;
 
ORA-01460: unimplemented or unreasonable conversion ed
ORA-06512: at "T2.F_STR2LIST_SQL", line 8
ORA-06512: at line 13

备注:ORA-01460的描述很不清楚,其实这里就是varchar2超长

 

 

 

 

 

测试比较两种方式在不同数据量下的性能

 

 代码如下 复制代码

----------------------------------------------------
-- performance test
declare
  l_list my_tk_str_tab_type := my_tk_str_tab_type();
  l_str  varchar2(32767) := '';
  l_max  pls_integer := 2000;
begin
  -- construct string
  for i in 1 .. l_max loop
    l_str := l_str || ',' || 'a';
  end loop;
  l_str := substr(l_str, 2);

  -- warm up before actually calculation
  l_list := f_str2list_sql(l_str, ',');
  l_list := f_str2list_pls(l_str, ',');
 
  -- begin calc and diff
  my_rs.rs_start;
  -- 1. pls version
  l_list := f_str2list_pls(l_str, ',');
  my_rs.rs_middle;
  -- 2. sql version
  l_list := f_str2list_sql(l_str, ',');
  my_rs.rs_stop();
end;
/

 

 

 


我们分别测试当元素个数为100, 200, 500, 1000, 2000的情况。每种情况进行3-5次然后取平均

元素个数

PL/SQL 运行时间 (1/100 second)

SQL 运行时间 (1/100 second)

PCT

100

1

1

100%

200

1

1 - 2

50% - 100%

500

1 - 2

2 - 3

30% - 50%

1000

1

4

25%

2000

2

10

20%

总结:

SQL版本的书写简便,并且可以脱离PL/SQL环境直接使用(单条SQL进行行列转换)。

SQL版本只能处理长度小于4000的字符串,实际最大只能包含2000个元素。PL/SQL版本可以处理长度小于32767的字符串。

小数据量情况下,两者性能相当。随着数据量增大,PL/SQL版本性能明显占优

 

 

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Python 3.x で Split() 関数を使用して、指定された区切り文字に従って文字列を分割する方法 Python 3.x で Split() 関数を使用して、指定された区切り文字に従って文字列を分割する方法 Jul 31, 2023 pm 08:33 PM

Python は、文字列を処理するための多くの組み込み関数を提供する人気のあるプログラミング言語です。一般的に使用される関数の 1 つは、split() 関数です。この関数は、指定された区切り文字に従って文字列を複数の部分文字列に分割できます。この記事ではPython3.xのsplit()関数の使い方を紹介します。 Python では、split() 関数は string クラスの組み込み関数であり、その基本構文は次のとおりです: string.split(separator,maxsplit)

PHPでexplode関数を使用して文字列を分割する方法 PHPでexplode関数を使用して文字列を分割する方法 Jun 26, 2023 pm 12:03 PM

PHP 言語には、文字列を迅速かつ効率的に処理するのに役立つ基本的な関数が多数あります。その中でもexplode関数は非常に実用的な文字列分割関数です。指定された区切り文字に従って文字列を配列に分割し、より柔軟な文字列操作を実行できます。この記事では、PHPで文字列を分割するexplode関数の使い方を紹介します。 1.explode関数の形式 PHP言語でのexplode関数の形式は次のとおりです。

文字列内の各文字が部分文字列に現れるような文字列の最大分割長 文字列内の各文字が部分文字列に現れるような文字列の最大分割長 Aug 25, 2023 pm 02:41 PM

この記事では、一意の文字を含む文字列の最大パーティションの長さを見つける方法の問題を検討します。まず問題の内容を理解してから、それぞれのアルゴリズムや時間計算量を含めて、この問題を解決するための素朴で効率的な方法を研究します。最後に、ソリューションを C++ で実装します。問題の説明 文字列を指定して、文字列内の各文字が 1 つの部分文字列のみに現れるように、文字列をできるだけ多くの部分文字列に分割します。これらの最大化分割の長さを返します。単純なアプローチ 単純なアプローチは、文字列を反復処理して、各文字の最後の出現を記録することです。次に、文字列を再度繰り返し、現在の文字が最後に見つかったときにパーティションを作成します。文字列を格納する配列を初期化するアルゴリズム (単純)

PHPで文字列を配列に分割する方法 PHPで文字列を配列に分割する方法 Jul 08, 2023 pm 01:49 PM

PHP で文字列を配列に分割する方法 PHP では、文字列を処理して複数の部分に分割する必要がよくあります。文字列を配列に分割することは、文字列のさまざまな部分をより適切に処理するのに役立つ一般的な操作です。この記事では、PHP の関数を使用して文字列を配列に分割する方法を学び、いくつかのコード例を示します。文字列を配列に分割するには、explode 関数を使用します。PHP には、指定した区切り文字に従って文字列を分割できるexplode という関数が用意されています。

文字列を偶数から始まり最小長 M の K 個の部分文字列に分割する方法の数を数えます。 文字列を偶数から始まり最小長 M の K 個の部分文字列に分割する方法の数を数えます。 Sep 09, 2023 pm 02:01 PM

この問題では、問題文で指定された条件を満たすように、指定された文字列を K 個の部分文字列に分割する方法を計算します。この問題を解決するために再帰を使用します。さらに、表形式の動的プログラミング手法を使用して、この問題を効率的に解決します。問題ステートメント-bin_Strと呼ばれる特定の長さの文字列があります。文字列には「0」から「9」までの数字のみが含まれます。次の条件を満たすように、文字列を K 個の部分文字列に分割する方法の数を計算する必要があります。部分文字列には少なくとも 2 文字が含まれている必要があります。各部分文字列の最初の文字は偶数、最後の文字は奇数である必要があります。例例 inputM=2,K=2;bin_str="255687&q

PHPのexplode関数によって報告されるエラーを解決する方法 PHPのexplode関数によって報告されるエラーを解決する方法 Mar 11, 2024 am 11:45 AM

PHP のexplode関数によって報告されるエラーを解決する方法には、特定のコード例が必要です。PHPのexplode関数は、指定された区切り文字に従って文字列を配列に分割するために使用される関数です。ただし、主に渡されたパラメータが関数の要件を満たしていないことが原因で、explode 関数の使用時にエラーが発生することがあります。以下では、考えられる問題と解決策について詳しく説明し、具体的なコード例を示します。爆発関数使用時のパラメータの数が間違っているために発生するエラー

PHP 文字列関数の例: 文字列の分割 PHP 文字列関数の例: 文字列の分割 Jun 20, 2023 pm 01:58 PM

PHP には多くの文字列関数がありますが、その中でも文字列分割関数は非常によく使用されます。文字列分割関数は、指定された区切り文字に従って文字列を分割し、配列を返すことができます。以下に、一般的に使用されるいくつかの文字列分割関数を紹介します。 explode関数explode関数は、指定された区切り文字に従って文字列を分割し、配列を返すことができます。構文は次のとおりです:explode(string$separator,string$string

文字列を 3 つの部分文字列に分割できるかどうかを確認します。1 つの部分文字列は他の 2 つの部分文字列の部分文字列です。 文字列を 3 つの部分文字列に分割できるかどうかを確認します。1 つの部分文字列は他の 2 つの部分文字列の部分文字列です。 Sep 22, 2023 am 11:53 AM

この問題では、3 番目の部分文字列が最初の 2 つの部分文字列の部分文字列になるように、指定された文字列を分割する必要があります。解決策を考えてみましょう。最初の 2 つの文字列に 3 番目の文字列のすべての文字が含まれている場合にのみ、3 番目の文字列を最初の 2 つの文字列の部分文字列にすることができます。したがって、指定された文字列内で頻度が 3 を超える文字を少なくとも 1 つ見つける必要があり、その 1 文字の 3 番目の部分文字列を取得できます。問題ステートメント - N 個の小文字のアルファベットを含む文字列 str が与えられています。部分文字列 c が a と b の部分文字列になるように、文字列を 3 つの部分文字列 a、b、c に分割できるかどうかを確認する必要があります。 3 つの部分文字列が見つかるかどうかに応じて、「はい」または「いいえ」を出力します。

See all articles