이것은 프로시져 내에서는 create table이 사용될 수 없다.
하지만 다음과 같은 방법을 이용하면 프로시져 내에서 커서를 이용해서 검색한 내용을 임시로 테이블을 생성해서 리턴값으로 임시테이블 이름을 넘어준다.
사용자는 파라메터 값을 넘겨주면서 프로시져를 호출하면 넘겨받은 임시테이블 이름으로 select를 하면 자신이 알고싶은 결과 집합을 쉽게 알수있다.
주의할점은 결과 집합을 쿼리후에는 반드시 삭제해줘야한다. 왜냐면 임시테이블이 계속 생성되므로, 데이터베이스안에 계속누적될수 있기떄문이다.
[환경설정]
우선 로그인 계정이 create table의 권한이 있어야한다.
TBL_SX_TBLCNT 의 이름으로 시퀀스를 생성한다.
start with = 1
min value = 1
max value = 99999
increment by = 1
cycle = true
number to cache = 20
order = false
이렇게 시퀀스를 생성하고 나면 프로시져내에서 테이블을 생성하게 만들 패키지를 호출해야하는데 이 패키지의 이름은 STR_SX_COM 이다. 내용은
CREATE OR REPLACE PACKAGE str_sx_Com AS
TYPE Tblname_tbl IS TABLE OF varchar2(100)
INDEX BY BINARY_INTEGER;
TYPE TblCnt_tbl IS TABLE OF number
INDEX BY BINARY_INTEGER;
TYPE Fldname_tbl IS TABLE OF varchar2(50)
INDEX BY BINARY_INTEGER;
TYPE SubProdCode_tbl IS TABLE OF varchar2(6)
INDEX BY BINARY_INTEGER;
TYPE NeedQty_tbl IS TABLE OF number
INDEX BY BINARY_INTEGER;
PROCEDURE sx_ComCreTbl -- Tbl 생성
(o_Tblname out varchar2,
i_Cnt in number,
i_Fldname in Fldname_tbl);
PROCEDURE sx_ComDelTblname -- 주어진 Table Drop
(i_Tblname in varchar2,
o_Cnt out number);
END str_sx_Com;
/
이렇게 패키지를 생성한 후에 이 패키지안에 들어갈 두개의 프로시져를 생성한다. 내용은
CREATE OR REPLACE PACKAGE BODY str_sx_Com AS
/*--------------------------------------------------------------------------*/
/* Create tbl */
/* grant create table to ace with grant option */
/*--------------------------------------------------------------------------*/
PROCEDURE sx_ComCreTbl
(o_Tblname out varchar2,
i_Cnt in number,
i_Fldname in Fldname_tbl)
IS
w_no number(3);
w_Tblname varchar2(100);
w_Sql varchar2(1000);
w_TblNo number(7);
w_Ignore number := 0;
cursor_name number;
w_FldTit varchar2(27) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
w_FldAttr varchar2(2);
w_FldLen varchar2(9);
input_para_err exception;
begin
dbms_output.ENABLE;
if i_Cnt > 26 then
raise input_para_err;
end if;
/*
select max(tname)
into w_Tblname
from tab
where tname like 'TBL_ZZ%';
if substr(w_Tblname, 5, 2) = 'ZZ' then
w_TblNo := to_number(substr(w_Tblname, 7, 5)) + 1;
else
w_TblNo := 1;
end if;
*/
--- ----------------------------------------------------------------------
--- 화일 고유번호 생성
--- ----------------------------------------------------------------------
select tbl_sx_tblcnt.nextval
into w_TblNo
from dual;
--- ----------------------------------------------------------------------
--- 화일 고유번호 생성
--- ----------------------------------------------------------------------
w_Tblname := 'TBL_ZZ' || substr(to_char(w_TblNo, '09999'), 2, 5);
o_Tblname := w_Tblname;
w_Sql := 'create table ' || w_Tblname || ' (';
for w_n in 1..i_Cnt loop
w_Sql := w_Sql || substr(w_FldTit, w_n, 1) || ' ';
w_FldAttr := substr(i_Fldname(w_n), 1, 1);
w_FldLen := substr(i_Fldname(w_n), 2, length(i_Fldname(w_n)) -1);
if w_FldAttr = 'c' or w_FldAttr = 'C' then
w_Sql := w_Sql || ' char(';
elsif w_FldAttr = 'v' or w_FldAttr = 'V' then
w_Sql := w_Sql || ' varchar2(';
elsif w_FldAttr = 'n' or w_FldAttr = 'N' then
w_Sql := w_Sql || ' number(';
else
raise input_para_err;
end if;
if w_n = i_Cnt then
w_Sql := w_Sql || w_FldLen || ')';
else
w_Sql := w_Sql || w_FldLen || '), ';
end if;
end loop;
w_Sql := w_Sql || ')';
cursor_name := dbms_sql.open_cursor;
dbms_sql.parse(cursor_name, w_Sql, dbms_sql.NATIVE);
w_Ignore := dbms_sql.execute(cursor_name);
dbms_sql.close_cursor(cursor_name);
exception
when input_para_err then
dbms_output.put_line('[sql error. please check tbl_name, fld name]=>');
dbms_output.put_line('input parameter error !!!');
o_Tblname := 'XXXXX';
when others then
dbms_output.put_line('[sql error. please check tbl_name, fld name]=>');
dbms_output.put_line('sqlerr =[' || sqlerrm || ']');
dbms_output.put_line('sqlcode=[' || to_char(sqlcode) || ']');
dbms_sql.close_cursor(cursor_name);
o_Tblname := 'XXXXX';
end sx_ComCreTbl;
/*--------------------------------------------------------------------------*/
/* TABLE delete and del cnt RETURN procedure */
/*--------------------------------------------------------------------------*/
procedure sx_ComDelTblname
(i_Tblname in varchar2,
o_Cnt out number)
is
cursor_name number;
w_Cnt number;
w_Tbl varchar2(21);
w_Sql varchar2(255);
begin
w_TBL := i_Tblname;
w_Sql := 'drop table ' || w_TBL || ' CASCADE CONSTRAINTS';
cursor_name := dbms_sql.open_cursor;
dbms_sql.parse(cursor_name, w_Sql, dbms_sql.V7);
w_Cnt := dbms_sql.execute(cursor_name);
o_Cnt := w_Cnt;
dbms_sql.CLOSE_cursor(cursor_name);
exception
when others then
dbms_output.put_line('[TBL NOT FND]');
o_Cnt := 1403;
if dbms_sql.is_open(cursor_name) then
dbms_sql.close_cursor(cursor_name);
end if;
END sx_ComDelTblname;
END str_sx_Com;
/
이렇게 하면 환경설정은 끝난다.
다음은 내가 작성한 조회 패키지 예이다.물론 패키지라해봤자 프로시져 하나 있지만...^^;
CREATE OR REPLACE PACKAGE str_sn_ItemList As
PROCEDURE sn_ItemList
(i_MemberId in varchar2,
o_TblName out varchar2);
END str_sn_ItemList;
/
CREATE OR REPLACE PACKAGE BODY str_sn_ItemList As
PROCEDURE sn_ItemList
(i_MemberId in varchar2,
o_TblName out varchar2)
IS
w_AuctionId number(13) := 0;
w_ItemId number(13) := 0;
w_SellerId varchar2(20):='';
w_MaxAmt number(13) := 0;
w_BuyerId varchar2(20):='';
w_Proc varchar2(10):='';
w_item_form varchar2(20):='';
w_item_kind varchar2(20):='';
w_item_name varchar2(40):='';
w_startAmt number(13) := 0;
w_endDate varchar2(10):='';
--- ------------------------------------------------------------------------
--- declare variable from table create --
--- ------------------------------------------------------------------------
w_FldName str_sx_com.FldName_tbl;
w_TblName varchar2(50);
w_Result number(4);
--- ------------------------------------------------------------------------
--- cursor define --
--- ------------------------------------------------------------------------
cursor DataFetch1_Cursor is
select 경매번호, 물품번호, 판매자, tender_amt, 구매자, okauction
from (select m.member_id 판매자, i.item_id 물품번호, a.okauction, t.member_id 구매자,
t.auction_id 경매번호, td.tender_amt
from member m, item i, auction a, tender t, tender_detail td
where m.member_id = i.member_id and
i.item_id = a.item_id and
a.auction_id = t.auction_id and
t.tender_id = td.tender_id and
m.member_id = 'longlee') t
where tender_amt = (select max(tender_amt)
from tender_detail, tender
where tender.tender_id = tender_detail.tender_id and
tender.auction_id = t.경매번호);
BEGIN
--- ------------------------------------------------------------------------
--- create table --
--- ------------------------------------------------------------------------
w_FldName(1) := 'N13'; -- 경매번호
w_FldName(2) := 'N13'; -- 물품번호
w_FldName(3) := 'V20'; -- 물품형태
w_FldName(4) := 'V20'; -- 물품종류
w_FldName(5) := 'V40'; -- 물품이름
w_FldName(6) := 'N13'; -- 시작금액
w_FldName(7) := 'V15'; -- 종료일
w_FldName(8) := 'N13'; -- 최고금액
w_FldName(9) := 'V20'; -- 낙찰자
w_FldName(10) := 'V10'; -- 진행여부
str_sx_Com.sx_ComCreTbl(w_TblName, 10, w_FldName);
dbms_output.enable(100000);
--dbms_output.put_line(' Start ');
o_TblName := w_TblName;
--dbms_output.put_line(' o_TblName=>'||o_TblName||'<');
OPEN DataFetch1_Cursor;
LOOP
FETCH DataFetch1_Cursor INTO
w_AuctionId, w_ItemId, w_SellerId, w_MaxAmt, w_BuyerId, w_Proc;
EXIT WHEN DataFetch1_Cursor%NOTFOUND;
--- 물품형태,물품종류,물품이름
begin
select item_form,item_kind,item_name into w_item_form,w_item_kind,w_item_name
from item
where item_id = w_itemId;
exception
when no_data_found then
w_item_form :='';
w_item_kind :='';
w_item_name :='';
end;
--- 시작금액,종료일
begin
select startAmt, endDate into w_startAmt, w_endDate
from auction
where auction_id = w_AuctionId;
exception
when no_data_found then
w_startAmt := 0;
w_endDate := '';
end;
end Loop;
CLOSE DataFetch1_Cursor;
--- ------------------------------------------------------------------------
--- insert table --
--- ------------------------------------------------------------------------
w_Result := str_InsTblF(w_TblName,
w_AuctionId,
w_ItemId,
w_item_form,
w_item_kind,
w_item_name,
w_startAmt,
w_endDate,
w_MaxAmt,
w_BuyerId,
w_Proc);
commit;
END sn_ItemList;
END str_sn_ItemList;
/
만일 위에서 오라클에 카탈도중 에러가 발생한다면. 프로시져 테스트 프로그램이 없으므로
sql>set serveroutput on
을 하고나서 프로시져 바디안에
dbms.output_put.line('출력할 내용 기술');
을 사용하면 디버깅에 이용할 수 있다
패키지 실행을 시키기 위해서는 다음처럼 실행한다.
sql> var g_name varchar2
sql> execute str_sn_itemlist.sn_itemlist('longlee',:g_name);
sql> print g_name
이렇게 하면 리턴된 임시테이블 명이 나올것이다.
tbl_99999 <--이런식으로.........
그럼
select * from tbl_99999 로 원하던 데이터의 값을 확인 할 수 있다.
이상...........................끝
패키지 실행을 시키기 위해서는 다음처럼 실행한다.
sql> var g_name varchar2
sql> execute str_sn_itemlist.sn_itemlist('longlee',:g_name);
sql> print g_name
이렇게 하면 리턴된 임시테이블 명이 나올것이다.
tbl_99999 <--이런식으로.........
그럼
select * from tbl_99999 로 원하던 데이터의 값을 확인 할 수 있다.
이상...........................끝
[펌] http://blog.naver.com/mijugari/120031432859
하지만 다음과 같은 방법을 이용하면 프로시져 내에서 커서를 이용해서 검색한 내용을 임시로 테이블을 생성해서 리턴값으로 임시테이블 이름을 넘어준다.
사용자는 파라메터 값을 넘겨주면서 프로시져를 호출하면 넘겨받은 임시테이블 이름으로 select를 하면 자신이 알고싶은 결과 집합을 쉽게 알수있다.
주의할점은 결과 집합을 쿼리후에는 반드시 삭제해줘야한다. 왜냐면 임시테이블이 계속 생성되므로, 데이터베이스안에 계속누적될수 있기떄문이다.
[환경설정]
우선 로그인 계정이 create table의 권한이 있어야한다.
TBL_SX_TBLCNT 의 이름으로 시퀀스를 생성한다.
start with = 1
min value = 1
max value = 99999
increment by = 1
cycle = true
number to cache = 20
order = false
이렇게 시퀀스를 생성하고 나면 프로시져내에서 테이블을 생성하게 만들 패키지를 호출해야하는데 이 패키지의 이름은 STR_SX_COM 이다. 내용은
CREATE OR REPLACE PACKAGE str_sx_Com AS
TYPE Tblname_tbl IS TABLE OF varchar2(100)
INDEX BY BINARY_INTEGER;
TYPE TblCnt_tbl IS TABLE OF number
INDEX BY BINARY_INTEGER;
TYPE Fldname_tbl IS TABLE OF varchar2(50)
INDEX BY BINARY_INTEGER;
TYPE SubProdCode_tbl IS TABLE OF varchar2(6)
INDEX BY BINARY_INTEGER;
TYPE NeedQty_tbl IS TABLE OF number
INDEX BY BINARY_INTEGER;
PROCEDURE sx_ComCreTbl -- Tbl 생성
(o_Tblname out varchar2,
i_Cnt in number,
i_Fldname in Fldname_tbl);
PROCEDURE sx_ComDelTblname -- 주어진 Table Drop
(i_Tblname in varchar2,
o_Cnt out number);
END str_sx_Com;
/
이렇게 패키지를 생성한 후에 이 패키지안에 들어갈 두개의 프로시져를 생성한다. 내용은
CREATE OR REPLACE PACKAGE BODY str_sx_Com AS
/*--------------------------------------------------------------------------*/
/* Create tbl */
/* grant create table to ace with grant option */
/*--------------------------------------------------------------------------*/
PROCEDURE sx_ComCreTbl
(o_Tblname out varchar2,
i_Cnt in number,
i_Fldname in Fldname_tbl)
IS
w_no number(3);
w_Tblname varchar2(100);
w_Sql varchar2(1000);
w_TblNo number(7);
w_Ignore number := 0;
cursor_name number;
w_FldTit varchar2(27) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
w_FldAttr varchar2(2);
w_FldLen varchar2(9);
input_para_err exception;
begin
dbms_output.ENABLE;
if i_Cnt > 26 then
raise input_para_err;
end if;
/*
select max(tname)
into w_Tblname
from tab
where tname like 'TBL_ZZ%';
if substr(w_Tblname, 5, 2) = 'ZZ' then
w_TblNo := to_number(substr(w_Tblname, 7, 5)) + 1;
else
w_TblNo := 1;
end if;
*/
--- ----------------------------------------------------------------------
--- 화일 고유번호 생성
--- ----------------------------------------------------------------------
select tbl_sx_tblcnt.nextval
into w_TblNo
from dual;
--- ----------------------------------------------------------------------
--- 화일 고유번호 생성
--- ----------------------------------------------------------------------
w_Tblname := 'TBL_ZZ' || substr(to_char(w_TblNo, '09999'), 2, 5);
o_Tblname := w_Tblname;
w_Sql := 'create table ' || w_Tblname || ' (';
for w_n in 1..i_Cnt loop
w_Sql := w_Sql || substr(w_FldTit, w_n, 1) || ' ';
w_FldAttr := substr(i_Fldname(w_n), 1, 1);
w_FldLen := substr(i_Fldname(w_n), 2, length(i_Fldname(w_n)) -1);
if w_FldAttr = 'c' or w_FldAttr = 'C' then
w_Sql := w_Sql || ' char(';
elsif w_FldAttr = 'v' or w_FldAttr = 'V' then
w_Sql := w_Sql || ' varchar2(';
elsif w_FldAttr = 'n' or w_FldAttr = 'N' then
w_Sql := w_Sql || ' number(';
else
raise input_para_err;
end if;
if w_n = i_Cnt then
w_Sql := w_Sql || w_FldLen || ')';
else
w_Sql := w_Sql || w_FldLen || '), ';
end if;
end loop;
w_Sql := w_Sql || ')';
cursor_name := dbms_sql.open_cursor;
dbms_sql.parse(cursor_name, w_Sql, dbms_sql.NATIVE);
w_Ignore := dbms_sql.execute(cursor_name);
dbms_sql.close_cursor(cursor_name);
exception
when input_para_err then
dbms_output.put_line('[sql error. please check tbl_name, fld name]=>');
dbms_output.put_line('input parameter error !!!');
o_Tblname := 'XXXXX';
when others then
dbms_output.put_line('[sql error. please check tbl_name, fld name]=>');
dbms_output.put_line('sqlerr =[' || sqlerrm || ']');
dbms_output.put_line('sqlcode=[' || to_char(sqlcode) || ']');
dbms_sql.close_cursor(cursor_name);
o_Tblname := 'XXXXX';
end sx_ComCreTbl;
/*--------------------------------------------------------------------------*/
/* TABLE delete and del cnt RETURN procedure */
/*--------------------------------------------------------------------------*/
procedure sx_ComDelTblname
(i_Tblname in varchar2,
o_Cnt out number)
is
cursor_name number;
w_Cnt number;
w_Tbl varchar2(21);
w_Sql varchar2(255);
begin
w_TBL := i_Tblname;
w_Sql := 'drop table ' || w_TBL || ' CASCADE CONSTRAINTS';
cursor_name := dbms_sql.open_cursor;
dbms_sql.parse(cursor_name, w_Sql, dbms_sql.V7);
w_Cnt := dbms_sql.execute(cursor_name);
o_Cnt := w_Cnt;
dbms_sql.CLOSE_cursor(cursor_name);
exception
when others then
dbms_output.put_line('[TBL NOT FND]');
o_Cnt := 1403;
if dbms_sql.is_open(cursor_name) then
dbms_sql.close_cursor(cursor_name);
end if;
END sx_ComDelTblname;
END str_sx_Com;
/
이렇게 하면 환경설정은 끝난다.
다음은 내가 작성한 조회 패키지 예이다.물론 패키지라해봤자 프로시져 하나 있지만...^^;
CREATE OR REPLACE PACKAGE str_sn_ItemList As
PROCEDURE sn_ItemList
(i_MemberId in varchar2,
o_TblName out varchar2);
END str_sn_ItemList;
/
CREATE OR REPLACE PACKAGE BODY str_sn_ItemList As
PROCEDURE sn_ItemList
(i_MemberId in varchar2,
o_TblName out varchar2)
IS
w_AuctionId number(13) := 0;
w_ItemId number(13) := 0;
w_SellerId varchar2(20):='';
w_MaxAmt number(13) := 0;
w_BuyerId varchar2(20):='';
w_Proc varchar2(10):='';
w_item_form varchar2(20):='';
w_item_kind varchar2(20):='';
w_item_name varchar2(40):='';
w_startAmt number(13) := 0;
w_endDate varchar2(10):='';
--- ------------------------------------------------------------------------
--- declare variable from table create --
--- ------------------------------------------------------------------------
w_FldName str_sx_com.FldName_tbl;
w_TblName varchar2(50);
w_Result number(4);
--- ------------------------------------------------------------------------
--- cursor define --
--- ------------------------------------------------------------------------
cursor DataFetch1_Cursor is
select 경매번호, 물품번호, 판매자, tender_amt, 구매자, okauction
from (select m.member_id 판매자, i.item_id 물품번호, a.okauction, t.member_id 구매자,
t.auction_id 경매번호, td.tender_amt
from member m, item i, auction a, tender t, tender_detail td
where m.member_id = i.member_id and
i.item_id = a.item_id and
a.auction_id = t.auction_id and
t.tender_id = td.tender_id and
m.member_id = 'longlee') t
where tender_amt = (select max(tender_amt)
from tender_detail, tender
where tender.tender_id = tender_detail.tender_id and
tender.auction_id = t.경매번호);
BEGIN
--- ------------------------------------------------------------------------
--- create table --
--- ------------------------------------------------------------------------
w_FldName(1) := 'N13'; -- 경매번호
w_FldName(2) := 'N13'; -- 물품번호
w_FldName(3) := 'V20'; -- 물품형태
w_FldName(4) := 'V20'; -- 물품종류
w_FldName(5) := 'V40'; -- 물품이름
w_FldName(6) := 'N13'; -- 시작금액
w_FldName(7) := 'V15'; -- 종료일
w_FldName(8) := 'N13'; -- 최고금액
w_FldName(9) := 'V20'; -- 낙찰자
w_FldName(10) := 'V10'; -- 진행여부
str_sx_Com.sx_ComCreTbl(w_TblName, 10, w_FldName);
dbms_output.enable(100000);
--dbms_output.put_line(' Start ');
o_TblName := w_TblName;
--dbms_output.put_line(' o_TblName=>'||o_TblName||'<');
OPEN DataFetch1_Cursor;
LOOP
FETCH DataFetch1_Cursor INTO
w_AuctionId, w_ItemId, w_SellerId, w_MaxAmt, w_BuyerId, w_Proc;
EXIT WHEN DataFetch1_Cursor%NOTFOUND;
--- 물품형태,물품종류,물품이름
begin
select item_form,item_kind,item_name into w_item_form,w_item_kind,w_item_name
from item
where item_id = w_itemId;
exception
when no_data_found then
w_item_form :='';
w_item_kind :='';
w_item_name :='';
end;
--- 시작금액,종료일
begin
select startAmt, endDate into w_startAmt, w_endDate
from auction
where auction_id = w_AuctionId;
exception
when no_data_found then
w_startAmt := 0;
w_endDate := '';
end;
end Loop;
CLOSE DataFetch1_Cursor;
--- ------------------------------------------------------------------------
--- insert table --
--- ------------------------------------------------------------------------
w_Result := str_InsTblF(w_TblName,
w_AuctionId,
w_ItemId,
w_item_form,
w_item_kind,
w_item_name,
w_startAmt,
w_endDate,
w_MaxAmt,
w_BuyerId,
w_Proc);
commit;
END sn_ItemList;
END str_sn_ItemList;
/
만일 위에서 오라클에 카탈도중 에러가 발생한다면. 프로시져 테스트 프로그램이 없으므로
sql>set serveroutput on
을 하고나서 프로시져 바디안에
dbms.output_put.line('출력할 내용 기술');
을 사용하면 디버깅에 이용할 수 있다
패키지 실행을 시키기 위해서는 다음처럼 실행한다.
sql> var g_name varchar2
sql> execute str_sn_itemlist.sn_itemlist('longlee',:g_name);
sql> print g_name
이렇게 하면 리턴된 임시테이블 명이 나올것이다.
tbl_99999 <--이런식으로.........
그럼
select * from tbl_99999 로 원하던 데이터의 값을 확인 할 수 있다.
이상...........................끝
패키지 실행을 시키기 위해서는 다음처럼 실행한다.
sql> var g_name varchar2
sql> execute str_sn_itemlist.sn_itemlist('longlee',:g_name);
sql> print g_name
이렇게 하면 리턴된 임시테이블 명이 나올것이다.
tbl_99999 <--이런식으로.........
그럼
select * from tbl_99999 로 원하던 데이터의 값을 확인 할 수 있다.
이상...........................끝
[펌] http://blog.naver.com/mijugari/120031432859