X

Oracle Application Express
Tipps, Tricks und Best Practice

APEX_STRING: String-Operationen leicht gemacht!

Carsten Czarski
Consulting Member of technical Staff

In der Community dreht sich derzeit fast alles um Application Express 18.1 - so findet Ihr auf dem englischsprachigen Application Express Blog eine Vielzahl von Artikeln zur neuen Unterstützung für REST Services und REST Enabled SQL.

In diesem Blog Posting geht es um das APEX_STRING package - das ist seit 5.1 vorhanden - Ihr könnt es also sofort nutzen. APEX_STRING enthält einige Funktionen und Prozeduren zum einfachen Umgang mit Zeichenketten. So ist mit der Funktion SPLIT ein String Tokenizer enthalten ...

select apex_string.split( 'a,b,c,d,e,f,g,h', ',' ) from dual;

COLUMN_VALUE                                                                                                            
---------------------------
a                                                                                                                       
b                                                                                                                       
c                                                                                                                       
d                                                                                                                       
e                                                                                                                       
f    

Auch in PL/SQL kann SPLIT verwendet werden.

declare
  l_array wwv_flow_t_varchar2;
begin
  l_array := apex_string.split( 'a,b,c,d,e,f,g,h', ',' );
  for i in 1 .. l_array.count loop
    dbms_output.put_line( apex_string.format( 'element at index %s: %s', i, l_array(i) ) );
  end loop;
end;
/

element at index 1: a
element at index 2: b
element at index 3: c
element at index 4: d
element at index 5: e
:

Ist man nur an den ersten Werten eines größeren Strings (oder CLOBs) interessiert, so ist der Parameter P_LIMIT bedeutsam: Ist das Limit erreicht, bricht die Funktion ab und spart so Rechenaufwand. Das letzte Element im zurückgegebenen Array enthält den Rest des Strings.

Neben VARCHAR2 unterstützt SPLIT auch den CLOB-Datentypen, SPLIT_NUMBERS liefert außerdem ein Array von NUMBER-Datentypen zurück. Aufmerksame Leser dürften bemerken, dass in obigem Block noch eine weitere Funktion aus dem APEX_STRING-Paket verwendet wurde: FORMAT.

FORMAT vereinfacht das Zusammensetzen von Strings aus festen Literalen und variablen Inhalten: anstelle vieler Konkatenationen mit || setzt man %s oder %{N} in den String ein. APEX_STRING ersetzt das n-te %s durch das n-the Argument p{N} (also das erste %s durch das Argument p0, das zweite durch p1 und so fort). Die Argumente p{N} können mit %{N} auch direkt angesprochen und so mehrfach verwendet werden: So spricht man p0 mit %0, p1 mit %1 an und so fort.

 

select apex_string.format( 
  p_message => 'Text mit Platzhaltern: USER: %s, SYSDATE: %s, RANDOM VALUE: %s', 
  p0 =>       user, 
  p1 =>       sysdate, 
  p2 =>       dbms_random.value 
) as formatted_text from dual;

FORMATTED_TEXT
------------------------------------------------------------------------------
Text mit Platzhaltern: USER: SYS, SYSDATE: 21.01.2017 06:39:47, 
RANDOM VALUE: ,52835625740274072229710302735665090347   

select apex_string.format( 
  p_message => 'Text mit Platzhaltern: USER: %0, SYSDATE: %1, nochmal USER: %0',
  p0 =>       user, 
  p1 =>       sysdate 
) as formatted_text from dual;

FORMATTED_TEXT                                                                                                          
------------------------------------------------------------------------------
Text mit Platzhaltern: USER: SYS, SYSDATE: 21.01.2017 06:42:34, 
nochmal USER: SYS
Mit den PLIST Prozeduren können einfache Property Listen verwaltet werden. Ein Eintrag in einer solchen Liste, die in einem Array vom Typ WWV_FLOW_T_VARCHAR2 abgelegt wird, ist ein Key-Value-Paar. Folgerichtig gibt es die Funktionen PLIST_GET, PLIST_PUT und PLIST_DELETE. Der folgende Code zeigt, wie's geht:
declare
  l_props wwv_flow_t_varchar2 := wwv_flow_t_varchar2();
begin
  apex_string.plist_put( l_props, 'username', 'SCOTT' ); 
  apex_string.plist_put( l_props, 'password', 'tiger' ); 
  apex_string.plist_put( l_props, 'connection', 'localhost:1521/orcl' );

  for i in 1 .. l_props.count loop
    dbms_output.put_line( apex_string.format( '%0: %1', i, l_props( i ) ) );
  end loop;

  dbms_output.put_line( apex_string.format( 
     p_message => '*** %0/%1@%2', 
     p0 => apex_string.plist_get(l_props, 'username'), 
     p1 => apex_string.plist_get(l_props, 'password'), 
     p2 => apex_string.plist_get(l_props, 'connection')
  ));

  apex_string.plist_delete( l_props, 'password' );

  for i in 1 .. l_props.count loop
    dbms_output.put_line( apex_string.format( '%0: %1', i, l_props( i ) ) );
  end loop;
end;
/

1: username
2: SCOTT
3: password
4: tiger
5: connection
6: localhost:1521/orcl

*** SCOTT/tiger@localhost:1521/orcl

1: username
2: SCOTT
3: 
4: 
5: connection
6: localhost:1521/orcl

Die Prozedur PUSH ist ein bequemer Weg, einen einfachen Wert an das Array anzuhängen. Der folgende Code zeigt sie im Zusammenspiel mit der Funktion SHUFFLE, welche das Array "durcheinanderwürfelt".

declare
  l_array wwv_flow_t_varchar2;
begin
  apex_string.push( l_array, 'Value 1' );
  apex_string.push( l_array, 'Value 2' );
  apex_string.push( l_array, 'Value 3' );
  apex_string.push( l_array, 'Value 4' );
  apex_string.shuffle( l_array );

  for i in 1 .. l_array.count loop
    dbms_output.put_line( apex_string.format( '%0: %1', i, l_array( i ) ) );
  end loop;
end;
/

1: Value 3
2: Value 2
3: Value 1
4: Value 4

 

Eine sehr mächtige Funktion ist für GREP, diese funktioniert wie die REGEXP_* SQL-Funktionen, liefert mehrere Ergebnisse aber als Array zurück. Das folgende Beispiel zeigt das: Aus einem Text sollen alle Email-Adressen extrahiert werden (die Regexp für Emailadressen ist sicherlich nicht die beste, für dieses Beispiel soll es aber reichen).

select * from table( apex_string.grep(
  'This is a text with some mail adresses. The first one is a.a@oracle.com, we have ' || 
  'noname@company.com and thesupport@firma.de',
  '[A-Z0-9._%+-]*@[A-Z0-9.-]*\.[A-Z]*',
  'i'
));

COLUMN_VALUE
--------------------------
a.a@oracle.com
noname@company.com
thesupport@firma.de

Die "normale" Funktion REGEXP_SUBSTR liefert stets genau einen String zurück; APEX_STRING.GREP dagegen ein Array mit einem Element für jeden Match. Genau das macht die Arbeit mit den extrahierten Werten massiv einfacher.

Zum Schluß stellen wir mit JOIN das Gegenstück zur eingangs vorgestellten Funktion SPLIT vor und schließen so den Kreis.

declare
  l_array wwv_flow_t_varchar2;
begin
  apex_string.push( l_array, 'Value 1' );
  apex_string.push( l_array, 'Value 2' );
  apex_string.push( l_array, 'Value 3' );
  apex_string.push( l_array, 'Value 4' );
  apex_string.shuffle( l_array );

  dbms_output.put_line( apex_string.join( l_array, '#' ) );
end;
/

Value 4#Value 2#Value 1#Value 3

APEX_STRING ist ein mit Sicherheit sehr nützliches Paket - welches einen näheren Blick absolut verdient.

 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.