Recently a friend asked me for this. I see it a lot on OraFaq as a question in the forums so here are the basics of working with delimited strings. I will show the various common methods for creating them and for unpacking them. Its not like I invented this stuff so I will also post some links for additional reading.
Here are some link for more reading:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15637744429336
http://www.oracle-base.com/articles/10g/StringAggregationTechniques.php
Creating Delimited Strings
There are five basic methods for creating a delimited string in Oracle:
1) (my favorite) use a hierarchical query, also known as the sys_connect_by_path method 2) create a simple plsql function for your own needs 3) use an oracle supplied function DBMS_UTIL.TABLE_TO_COMMA and WM_CONCAT 4) bulid your own user defined aggregate (I first saw this on asktomhome) 5) even use XML (super ugly and not sure why anyone would do it this way so I won't show it)
sys_connect_by_path
In this method we take advantage of oracle's hierarchical processing in sql to do string concatenation all inside the sql statement.
SQL> select substr(sys_connect_by_path(table_name,','),2) table_list 2 from ( 3 select rownum rowno,table_name 4 from user_tables 5 where rownum < 4 6 ) 7 where connect_by_isleaf = 1 8 connect by prior rowno = rowno - 1 9 start with rowno = 1 10 / TABLE_LIST ------------------------------------------------------------------------------------ MV_UW_PROD_ASSIGNMENTS,MV_CALL_MEMO_REPORT,MV_SALES_TEAMS 1 row selected.
I like this because of its flexibility. You can supply any query you want without using any procedural code.
Simple PLSQL Function
Maybe the most common method is creating your own special purpose function. Not my favorite method as it usually is not general use and is not terribly efficient. There are many variations on this theme depending upon what the format of your incomming data is and how you get it ready for sending to the function. I have seen varations that use PLSQL table types and database object types and of course query parameters like this one.
create or replace function kev_get_string_list (query_p in varchar2) return varchar2 is c1 sys_refcursor; comma_seperated_list_v varchar2(4000); string_v varchar2(4000); begin open c1 for query_p; loop fetch c1 into string_v; if c1%notfound then exit; end if; comma_seperated_list_v := comma_seperated_list_v||','||string_v; end loop; close c1; comma_seperated_list_v := substr(comma_seperated_list_v,2); return (comma_seperated_list_v); end; / show errors SQL> select kev_get_string_list('select table_name from user_tables where rownum < 4') thestring from dual; THESTRING --------------------------------------------------------------------------------------------------------------- MV_UW_PROD_ASSIGNMENTS,MV_CALL_MEMO_REPORT,MV_SALES_TEAMS 1 row selected.
Use an Oracle Supplied Function
DBMS_UTIL.TABLE_TO_COMMA does it but his is a procedure not a function and is not callable directly from sql. It also requires a plsql table input so has limited use outside of plsql. I won't bother with an example as it is in fact like the example above just shown.
But this is interesting. WM_CONCAT is an oracle supplied aggregate function that creates comma delimited strings.
SQL> select wm_concat(table_Name) comma_delimited_list 2 from user_tables 3 where rownum < 4 4 / COMMA_DELIMITED_LIST ----------------------------------------------------------- CONTACT_POINT,ELECTRONIC_ADDRESS,POSTAL_ADDRESS 1 row selected.
But there are some issues:
1) it may or may not be documented depending upon your release.
2) you must have installed oracle workspace manager for it to be available.
Roll Your Own User Defined Aggregate
I first saw this on asktomhome. It may be the most natural method philosophically and most versatile. It is also the basic example of using user defined aggregate for something useful. We basically build our own WM_CONCAT so to speak.
create or replace type our_string_agg as object ( string_v varchar2(32767) ,static function odciaggregateinitialize(sctx in out our_string_agg) return number ,member function odciaggregateiterate(self in out our_string_agg, value in varchar2 ) return number ,member function odciaggregateterminate(self in our_string_agg, returnvalue out varchar2, flags in number) return number ,member function odciaggregatemerge(self in out our_string_agg, ctx2 in our_string_agg) return number ); / show errors create or replace type body our_string_agg is static function odciaggregateinitialize(sctx in out our_string_agg) return number is begin sctx := our_string_agg(null); return odciconst.success; end; member function odciaggregateiterate(self in out our_string_agg, value in varchar2) return number is begin self.string_v := self.string_v || ',' || value; return odciconst.success; end; member function odciaggregateterminate(self in our_string_agg, returnvalue out varchar2, flags in number) return number is begin returnvalue := rtrim(ltrim(self.string_v, ','), ','); return odciconst.success; end; member function odciaggregatemerge(self in out our_string_agg, ctx2 in our_string_agg) return number is begin self.string_v := self.string_v || ',' || ctx2.string_v; return odciconst.success; end; end; / show errors create or replace function agg_get_comma_delimited_string (data_in_p in varchar2) return varchar2 parallel_enable aggregate using our_string_agg; / show errors SQL> select agg_get_comma_delimited_string(table_name) comma_delimited_string 2 from user_tables 3 where rownum < 4 4 / COMMA_DELIMITED_STRING -------------------------------------------------------------------------------------- CONTACT_POINT,ELECTRONIC_ADDRESS,POSTAL_ADDRESS 1 row selected.
It is my understanding that WC_CONCAT is in fact a "user defined aggregate" just defined by oracle for us. For those not familiar with user defined aggregates consider this:
SUM is an aggregate function. It operates across a set of rows. Could you write your own SUM function? Sure, you use the ODCIAggregate API to do it. Thus you can extend oracle with your own aggregate functions. Of course you need a reason to do it. This is one reason. Not many people have a reason so not many people use this. User Defined Aggregates were I believe created most to support Oracle's geocoding stuff.
As you can see UDA is somewhat involved. However, good things come from the effort. The result is another function that operates like all other functions. A very handy way to extend oracle if you have a need for it.
XML method
OK this method is ugly. It requires use of XMLAGG and XML_ELEMENT functions and multiple passes of the data and even when done is very unclear what it is doing. I won't show it, but you can easily find it with a google search.
Then there is the unpacking side of things. How does one unpack a delimited string. Well for this there are two basic methods:
1) sql method
2) function method
Unpacking is less exciting than packing.
The SQL Method
This is pretty much the reverse of the sys_connect_by_path. Once again we use the hierarchical capabilities of Oracle but this time we unpack instead of pack. The calculation of how many items are in the string is part of the trick here.
variable v1 varchar2(30) exec begin :v1 := 'xyz,pdq,abc'; end; SQL> select substr(','||:v1||',' 2 ,instr(','||:v1||',',',',1,rownum)+1 3 ,instr(','||:v1||',',',',1,rownum+1)-instr(','||:v1||',',',',1,rownum)-1) avalue 4 from dual 5 connect by level <= length(:v1)-length(replace(:v1,','))+1 6 / AVALUE ---------------------------------- xyz pdq abc 3 rows selected.
The Function Method
create or replace type c_varchar2_30 is table of varchar2(30) / create or replace function unpack_delimited_string (string_p in varchar2) return c_varchar2_30 is c_varchar2_30_v c_varchar2_30 := c_varchar2_30(); begin for i in 1..nvl(length(string_p)-length(replace(string_p,','))+1,0) loop c_varchar2_30_v.extend; c_varchar2_30_v(c_varchar2_30_v.last) := substr(','||string_p||',' ,instr(','||string_p||',',',',1,i)+1 ,instr(','||string_p||',',',',1,i+1)-instr(','||string_p||',',',',1,i)-1) ; end loop; return (c_varchar2_30_v); end; / show errors SQL> select * 2 from table(cast(unpack_delimited_string('xyz,abc,pdq') as c_varchar2_30)) 3 / COLUMN_VALUE ------------------------------ xyz abc pdq 3 rows selected.
Once again there are many variations of this theme mostly depending upon how you want the unpacked result returned. I like keeping things SQL ready so I choose the table type as my return type so I could get access to it via sql easily.
from: http://www.orafaq.com/node/2290
相关推荐
由SANS机构安全研究员编写的NsPack 3.4和3.7脱壳教程,使用OllyDbg调式并分析NsPack壳的程序,实现脱壳并分析其原理。
本文档主要介绍了脱壳的原理及应用,很有研究价值不仅仅是简单的脱壳教程
解决git pull的时候卡在unpacking 58%(57/97),网上搜了很多资料,都没有中文的详细解决案例,这里在这里上传一段总结,本来想写blog的。但因为没有分了,坑你们一分吧。但绝对实用。
国外的脱壳电子书,This ebook is a collection of unpacking tutorials, papers and documents gathered together by members of Reverse Engineering Association (REA).这是一本逆向工程相关的脱壳教程、论文和...
逆向工程核心原理推荐的初学者入门必学视频。 A collection of tutorials ...39. Inlining a blowfish scheme in a packed & CRC protected dll + unpacking Asprotect SKE 2.2 40. Obfuscation and algorithm hiding
using array shorthand syntax for list(), array dereferencing, and array unpacking with the splat operator. The problem is, you're not a programmer and the thought of writing code sends a chill up ...
Gain access to real world solutions in the art and science of report planning and creation using System Center data Practical cookbook with recipes that will help you get the most out of Microsoft ...
types=1) and the new available data types, scalar type declarations for function arguments and return statements, constant arrays using define(), argument unpacking with the ... operator, integer ...
PEP 448 - Additional Unpacking Generalizations PEP 461 - percent formatting support for bytes and bytearray PEP 484 - Type Hints PEP 471 - os.scandir() function – a better and faster directory ...
该技术资料由cektop大神(ZPfixer作者)编写,非常经典的ZProtect 1.6脱壳教程。
A Shockwave Flash movie tutorial showing a method of unpacking Gie Protector 0.2.
Converting Between Unicode and Plain Strings Recipe 1.22. Printing Unicode Charactersto Standard Output Recipe 1.23. Encoding Unicode Data for XML and HTML Recipe 1.24. Making Some Strings Case...
PE-sieve:An Open-Source Process Scanner for Hunting and Unpacking Malware.pdf Practical Uses for Hardware-assisted Memory Visualization.pdf Supply Chain Security:If I were a Nation State....pdf ...
教程ZProtect-1.600脱壳教程,可跳过注册或无限重试,是比较完整的教程,方便,有用,图文,有需要的请下载使用。
You'll start with the basics—unpacking your board and using a simple program to make something happen. Then, you'l attempt progressively more complex projects as you connect Arduino to motors, LCD ...
High compression ratio in 7z format with LZMA and LZMA2 compression Supported formats: Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM Unpacking only: ARJ, CAB, CHM, CPIO, CramFS, DEB, DMG,...
4.7.4. Unpacking Argument Lists 36 4.7.5. Lambda Expressions 37 4.7.6. Documentation Strings 38 4.7.7. Function Annotations 39 4.8. Intermezzo: Coding Style 39 5. Data Structures 40 5.1. More on Lists...
High compression ratio in 7z format with LZMA and LZMA2 compression Supported formats: Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM Unpacking only: AR, ARJ, CAB, CHM, CPIO, CramFS, DMG, ...