Fujitsu-Siemens
 
M A G A Z I N
 
SOFTWARE 
  Ivan Korać

Automatsko generisanje test podataka

U poslu se često dešavaju situacije da treba da ugradite neku business logiku u stored package, a da često dobijete samo opis tabela bez flat file-ova sa test podacima. Kako god bilo isprogramirana, logika se mora testirati na nekim podacima.
Izuzetno je naporno kreirati insert statement-e za punjenje test podataka, prvo zato što može da se radi o milionima slogova - potrebnih za testiranje performansi, a drugo što test podaci najčešće treba da poštuju određene domene i pravila (constraints), npr. foreign key constraint.
Zato je više nego potrebno imati pri ruci različite dynamic procedure, koje bi zavisno od tipa kolone u tabeli i/ili constrainta insertovale željeni broj slogova u tabelu.
Ovde će biti navedeno nekoliko ideja proizašlih iz konsultacija sa Thomasom Kytom (autor "najjače" ikad izdate Oracle knjige: Expert one-on-one).
Prvi primer je procedura koja klonira već postojeću tabelu (kopira strukturu) i puni je sa željenim brojem slogova respektujući tip kolone. Umesto dbms_random package-a (proverite da li je dbms_random instaliran u vašoj bazi), možete koristiti svoje vrednosti.


Primer 1


> create or replace procedure clone( p_tname in varchar2, p_records in number )
2 authid current_user
3 as
4 l_insert long;
5 l_rows number default 0;
6 begin
7
8 execute immediate 'create table clone_' || p_tname ||
9 ' as select * from ' || p_tname ||
10 ' where 1=0';
11
12 l_insert := 'insert into clone_' || p_tname ||
13 ' select ';
14
15 for x in ( select data_type, data_length,
16 nvl(rpad( ‘9’,data_precision,’9’)/power(10,data_scale),9999999999) maxval
17 from user_tab_columns
18 where table_name = 'CLONE_' || upper(p_tname)
19 order by column_id )
20 loop
21 if ( x.data_type in ('NUMBER', 'FLOAT' ))
22 then
23 l_insert := l_insert || 'dbms_random.value(1,' || x.maxval || ),';
24 elsif ( x.data_type = 'DATE' )
25 then
26 l_insert := l_insert || 'sysdate+dbms_random.value+dbms_random.value(1,1000),';
27 else
28 l_insert := l_insert || 'dbms_random.string(''A'',' || x.data_length || '),';
29 end if;
30 end loop;
31 l_insert := rtrim(l_insert,',') || ' from all_objects where rownum <= :n';
32
33 loop
34 execute immediate l_insert using p_records - l_rows;
35 l_rows := l_rows + sql%rowcount;
36 exit when ( l_rows >= p_records );
37 end loop;
38 end;
39 /
Procedure created.
> exec clone( 'emp', 5 );
PL/SQL procedure successfully completed.
> select * from clone_emp;



Da bi se pri generisanju podataka, poštovalo pravilo foreign key-a, navodimo ideju kako slučajno izabrati proizvoljno veliki set vrednosti iz već postojećeg. Npr. u tabelu emp, polje deptno je spoljni ključ iz tabele dept.
Ideja je da se vrednosti primarnog ključa iz tabele DEPT napune u plsql table type i koristi dbms_random da izindeksira slučajno izabrane vrednosti u nizu:


Primer 2


> declare
2 type numArray is table of number index by binary_integer;
3
4 l_deptnos numArray;
5 begin
6 select deptno bulk collect into l_deptnos from dept;
7
8 for i in 1 .. 5
9 loop
10 dbms_output.put_line( l_deptnos( dbms_random.value( 1, l_deptnos.count ) ) );
11 end loop;
12 end;
13 /
PL/SQL procedure successfully completed.


Instaliranje DBMS_RANDOM package-a


Za instaliranje dbms_random package, potrebno je da se konektujete kao user SYS ili INTERNAL i da pokrenete sledece scriptove:

SVRMGR> connect internal
Connected.
SVRMGR> @utlraw
Statement processed.

SVRMGR> @prvtrawb.plb
Statement processed.

SVRMGR> @dbmsoctk
Statement processed.
Statement processed.
Statement processed.
Statement processed.
Statement processed.
Statement processed.

SVRMGR> @prvtoctk.plb
Statement processed.
Statement processed.
Statement processed.

SVRMGR> @dbmsrand
Statement processed.
Statement processed.
Statement processed.
Statement processed.
Statement processed.
SVRMGR>
Po instaliranju za “quick start”, potrebno je samo:

SVRMGR> select text from all_source
2 where name = 'DBMS_RANDOM'
3 and type = 'PACKAGE'
4 order by line;

 

VRH STRANE

(c) 2003 OMEGA - sva prava zadržana