Oracle

게시글 보기
작성자 유건데이타 등록일 2015-05-16
제목 DBMS_DESCRIBE PACKAGE를 이용하여 PROCEDURE, FUNCTION의 ARGUME
DBMS_DESCRIBE PACKAGE를 이용하여 PROCEDURE, FUNCTION의 ARGUMENT를 확인하는 방법
===============================================================================


Purpose
-------
DBMS_DESCRIBE package를 이용하면 특정 procedure, function의 argument를
확인할 수 있다. (대상이 되는 procedure, function이 standalone이거나
package내부에 존재하거나 모두 가능하다.)


Explanation
-----------

DBMS_PACKAGE를 사용하려면 우선,
$ORACLE_HOME/rdbms/admin directory의 dbmsdesc.sql, prvtdesc.sql을
sys user로 수행해야 한다.(catproc.sql의 내부에서 수행되도록 되어 있다.)

이 package안에는 DESCRIBE_PROCEDURE라는 하나의 procedure만이 존재한다.

procedure describe_procedure (
object_name in varchar2,
reserved1 in varchar2,
reserved2 in varchar2,
overload out number_table,
position out number_table,
level out number_table,
argument_name out varchar2_table,
datatype out number_table,
default_value out number_table,
in_out out number_table,
length out number_table,
precision out number_table,
scale out number_table,
radix out number_table,
spare out number_table ) ;

이 procedure는 특정 procedure, function의 이름을 받아서 해당 procedure,
function의 argument에 대한 내용을 return한다.
return되는 argument에 대한 내용들은 모두 indexed PL/SQL table의 형태이다.
이들은 overload, position에 대해서 ordered된다.

이 package를 사용하는데 있어서 다음과 같은 제약사항이 있다.
. remote object에 대한 description은 추출할 수 없다.
. 특정 package내의 모든 procedure, function들에 대한 description을
한번에 return하지는 못한다.

input 변수로 받는 procedure, function의 이름(object_name)은 SQL의
규칙을 따른다. 만약 procedure, function이 특정 package내에 존재한다면
'object_name' argument는 package_name.procedure_name의 형태로 사용한다.
만약 DBMS_DESCRIBE package를 사용하는 user가, 대상이 되는 procedure,
function의 owner가 아니라면 'object_name' argument는
owner_name.obj_name형태를 사용해야 하며(이때 obj_name은 procedure_name,
function_name, package_name.procedure_name, package_name.function_name
중에 한가지이다.), EXECUTE privilege를 가지고 있어야 한다.


Example
-------

1. 예제1
이후에 진행되는 모든 example에서는 아래에 정의된 MYPACK package의 FUNC1
function을 이용한다.

create or replace package mypack as
type numtabtype is table of number(9) index by binary_integer;
type chartabtype is table of char(10) index by binary_integer;
type datetabtype is table of date index by binary_integer;
function func1 (tab_size in number, tabl in numtabtype) return chartabtype;
function func1 (tab_size in number, tabl in datetabtype) return chartabtype;
end;
/

create or replace package body mypack as
function func1 (tab_size in number, tabl in numtabtype)
return chartabtype
is
temptab chartabtype;
begin
for i in 1..tab_size loop
temptab(i) := to_char(tabl(i));
end loop;
return temptab;
end;

function func1 (tab_size in number, tabl in datetabtype)
return chartabtype
is
temptab chartabtype;
begin
for i in 1..tab_size loop
temptab(i) := to_char(tabl(i));
end loop;
return temptab;
end;
end;
/


2. PL/SQL을 이용한 예

stored procedure내에서 DBMS_DESCRIBE.DESCRIBE_PROCEDURE를 call하는 방법

create or replace procedure describe_any (obj_name in varchar2) as
overload dbms_describe.number_table;
position dbms_describe.number_table;
levl dbms_describe.number_table;
argument_name dbms_describe.varchar2_table;
datatype dbms_describe.number_table;
default_value dbms_describe.number_table;
in_out dbms_describe.number_table;
length dbms_describe.number_table;
precision dbms_describe.number_table;
scale dbms_describe.number_table;
radix dbms_describe.number_table;
spare dbms_describe.number_table;
maxrows integer := 15;
begin
dbms_describe.describe_procedure (
obj_name,
null,
null,
overload,
position,
levl,
argument_name,
datatype,
default_value,
in_out,
length,
precision,
scale,
radix,
spare ) ;

dbms_output.put_line('overload ' ||
'position ' ||
'argument ' ||
'level ' ||
'datatype ' ||
'length ' ||
'prec ' ||
'scale ' ||
'rad ');
dbms_output.put_line('-------------------------' ||
'-------------------------' ||
'-------------------------');
for counter in 1..maxrows loop
begin
dbms_output.put( overload(counter) || ' ' ||
position(counter) || ' ');
if argument_name(counter) is null then
dbms_output.put(' ');
else
dbms_output.put(rpad(argument_name(counter),10) || ' ');
end if;
dbms_output.put_line(
levl(counter) || ' ' ||
lpad(to_char(datatype(counter)),3) || ' ' ||
lpad(to_char(length(counter)),3) || ' ' ||
precision(counter) || ' ' ||
scale(counter) || ' ' ||
lpad(to_char(radix(counter)),2) );
exception
when no_data_found then exit;
end;
end loop;
end;
/

SQL> execute describe_any('MYPACK.FUNC1');
overload position argument level datatype length prec scale rad
---------------------------------------------------------------------
1 0 0 251 0 0 0 0
1 0 1 96 10 0 0 0
1 1 TAB_SIZE 0 2 0 0 0 0
1 2 TABL 0 251 0 0 0 0
1 2 1 2 22 9 0 10
2 0 0 251 0 0 0 0
2 0 1 96 10 0 0 0
2 1 TAB_SIZE 0 2 0 0 0 0
2 2 TABL 0 251 0 0 0 0
2 2 1 12 0 0 0 0

PL/SQL procedure successfully completed.

위의 예에서 각 column의 의미는 다음과 같다.
overload : overload된(이름은 같지만 argument의 갯수, type등이 다른)
procedure나 function이 있다면 각각에 고유한 number가 부여
position : parameter list안에서의 위치
이값이 0이면 function의 return value를 의미함.
argument : argument 이름
level : 만약 argument가 composite type인 경우 각 argument의 level
datatype : argument의 datatype을 나타내는 number
0 - This row is a placeholder for a procedure with
no arguments.
1 - VARCHAR2
2 - NUMBER
3 - NATIVE INTEGER (for PL/SQL's BINARY_INTEGER)
8 - LONG
11 - ROWID
12 - DATE
23 - RAW
24 - LONG RAW
96 - CHAR (ANSI FIXED CHAR)
106 - MLSLABEL
250 - PL/SQL RECORD (see "Notes:" below)
251 - PL/SQL TABLE
252 - PL/SQL BOOLEAN (see "Notes:" below)
length : datatype의 length
prec, scale, rad : datatype이 number일 경우 사용


3. Precompiler를 이용한 예

#include
#include


/* Define constants for VARCHAR lengths. */
#define UNAME_LEN 20
#define PWD_LEN 40
#define ARRAY_SIZE 10

typedef char str[11];

EXEC SQL TYPE str IS STRING(11) REFERENCE;

/* Declare variables. No declare section is
needed if MODE=ORACLE. */
VARCHAR username[UNAME_LEN]; /* VARCHAR is an
Oracle-supplied struct */
varchar password[PWD_LEN]; /* varchar can be in
lower case also. */
varchar object_name[30];
int overload[ARRAY_SIZE];
int position[ARRAY_SIZE];
int level[ARRAY_SIZE];
str argument_name[ARRAY_SIZE];
short arg_name_ind[ARRAY_SIZE];
int datatype[ARRAY_SIZE];
int default_value[ARRAY_SIZE];
int in_out[ARRAY_SIZE];
int length[ARRAY_SIZE];
int precision[ARRAY_SIZE];
int scale[ARRAY_SIZE];
int radix[ARRAY_SIZE];
int spare[ARRAY_SIZE];

int i;

/* Include the SQL Communications Area.
You can use #include or EXEC SQL INCLUDE. */
#include


/* Declare error handling function. */
void sql_error();


main()
{

/* Connect to ORACLE--
* Copy the username into the VARCHAR.
*/
strncpy((char *) username.arr, "SCOTT", UNAME_LEN);

/* Set the length component of the VARCHAR. */
username.len = strlen((char *) username.arr);

/* Copy the password. */
strncpy((char *) password.arr, "TIGER", PWD_LEN);
password.len = strlen((char *) password.arr);

/* Register sql_error() as the error handler. */
EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--\
");

/* Connect to ORACLE. Program will call sql_error()
* if an error occurs when connecting to the default database.
*/
EXEC SQL CONNECT :username IDENTIFIED BY :password;

printf("\
Connected to ORACLE as user: %s\
", username.arr);

printf("\
Enter the name of the procedure or function to be described: ");
gets((char *) object_name.arr);
object_name.len = strlen((char *) object_name.arr);

for (i=0; ifc]);
do_exit(n);
}


/*
* Exit program with an exit code.
*/
do_exit(exit_code)
sword exit_code;
{
sword error = 0;

if (ologof(&lda))
{
fprintf(stderr, "Error on disconnect.\
");
fprintf(stderr, "Error on disconnect.\
");
error++;
}

exit(exit_code);
}


결과 :

Connected to ORACLE as SCOTT
Overload Level Pos ProcName Datatype
1 0 0 251
1 1 0 96
1 0 1 TAB_SIZE 2
1 0 2 TABL 251
1 1 2 2
2 0 0 251
2 1 0 96
2 0 1 TAB_SIZE 2
2 0 2 TABL 251
2 1 2 12


Reference Document
------------------
Oracle Developer's Guide
Comment
등록된 코멘트가 없습니다.