============================================ ORACLE8I : DYNAMIC SQL (NATIVE DYNAMIC SQL) ============================================ PURPOSE --------- DBMS_SQL packageÀ» »ç¿ëÇÏ¿© compile ½Ã¿¡ °íÁ¤µÇ¾îÁö´Â Á¦ÇÑÀ» ±Øº¹ Çϸç Dynamic SQL statementÀ» ±¸ÇöÇÒ ¼ö ÀÖ´Ù. Explanation ------------- Oracle 8i¿¡¼­ÀÇ Dynamic SQLÀº µÎ°¡Áö ¹æ¹ýÀÌ ÀÖ´Ù.ù¹øÂ° ¹æ¹ýÀº "EXECUTE IMMEDIATE" ÀýÀ» »ç¿ëÇÏ¿© embedded dynamic sqlÀ» ±¸ÇöÇÏ´Â °ÍÀ̰í, µÎ¹øÂ° ¹æ¹ýÀº ¼±¾ðµÇ¾îÁö´Â °Í ´ë½Å¿¡ ½ÇÇà½Ã¿¡ ¹®ÀåÀ» º¸³»´Â ref cursorÀÇ È®ÀåµÈ °³³äÀ¸·Î query¸¦ À§ÇØ »ç¿ëµÇ¾îÁö´Â ¹æ¹ýÀÌ´Ù. Example --------- ¹æ¹ý 1: EXECUTE IMMEDIATE ---------------------------- Syntax: EXECUTE IMMEDIATE dynamic_sql_string [INTO {define_var1 [, define_var2] ... | plsql_record }] [USING [IN | OUT | IN OUT] bind_arg1 [, [IN | OUT | IN OUT] bind_arg2] ...]; 1. DDL¹® ½ÇÇà. bind variableÀ» Çã¿ëÇÏÁö ¾Ê´Â´Ù. declare str varchar2(200); begin str := 'create table msg (msg varchar2(120))'; EXECUTE IMMEDIATE str; end; 2. bind variableÀ» »ç¿ëÇÏÁö ¾Ê´Â non-query DML¹® ½ÇÇà ¿¹. declare str varchar2(200); begin str := 'insert into msg values (''Hello'')'; EXECUTE IMMEDIATE str; end; 3. bind variableÀ» »ç¿ëÇÏÁö ¾Ê´Â non-query DML¹® ½ÇÇà ¿¹. variableÀº default·Î IN bindÀ̹ǷΠIN, OUT modeÀ» ³ªÅ¸³¾ ÇÊ¿ä´Â ¾ø´Ù. declare str varchar2(200); val varchar2(20); begin str := 'insert into msg values (:b1)'; val := 'Bye'; EXECUTE IMMEDIATE str USING val; end; 4. bind variableÀ» ÀÌ¿ëÇÏ¿© single row selectÀ» ½ÇÇàÇϰí, single define variable¿¡ fetchÇÏ´Â ¿¹. declare str varchar2(200); val varchar2(20); ret varchar2(20); begin str := 'select msg from msg where msg = :b1'; val := 'Hello'; EXECUTE IMMEDIATE str INTO ret USING val; dbms_output.put_line('Value fetched from table: '||ret); end; Result: Value fetched from table: Hello 5. 4.ÀÇ ¿¹¿Í °°Àº select¹®À» ¼öÇàÇϸç , PL/SQL record type¿¡ fetchÇÏ´Â ¿¹. declare str varchar2(200); val varchar2(20); ret msg%rowtype; begin str := 'select msg from msg where msg = :b1'; val := 'Hello'; EXECUTE IMMEDIATE str INTO ret USING val; dbms_output.put_line('Value fetched from table: '||ret.msg); end; Result: Value fetched from table: Hello 6. returningÀýÀ» Æ÷ÇÔÇÑ delete¹®À» ¼öÇàÇÏ´Â ¿¹. ÀÌ °æ¿ì¿¡´Â OUT mode·Î ¼±¾ðµÈ bind variableÀÌ Á¸ÀçÇØ¾ß ÇÑ´Ù. deleteµÈ rowÀ» ¾Ë±â À§Çؼ­´Â sql%rowcountÀ» »ç¿ëÇϸç, ¸ðµç sql% attribute°¡ À¯È¿ÇÏ´Ù. declare str varchar2(200); val varchar2(20); ret varchar2(20); begin val := 'Bye'; str := 'delete from msg where msg = :b1 returning msg into :b2'; EXECUTE IMMEDIATE str USING val, OUT ret; dbms_output.put_line('Deleted '||sql%rowcount|| ' row(s) with value: '||ret); end; Result: Deleted 1 row(s) with value: Bye 7. errorÀ» checkÇϸ鼭 stored functionÀ» ¸¸µé°í ¸¸µé¾îÁø functionÀ» ½ÇÇàÇϸç, functionÀº return typeÀ¸·Î OUT bind variableÀÌ Á¦°øµÈ´Ù. declare str varchar2(200); -- Declare an exception to trap "compiled with errors" compile_warn exception; pragma exception_init(compile_warn,-24344); val number; ret number; begin begin -- A deliberate error (spelling of number) str := 'create or replace function doubleit (p1 in umber)'|| ' return number as begin return p1*2; end;'; EXECUTE IMMEDIATE str; exception when compile_warn then -- Correct and reexecute str := replace(str,'in umber','in number'); EXECUTE IMMEDIATE str; when others then raise; end; -- Call the stored function str := 'begin :b1 := doubleit(:b2); end;'; val := 30; EXECUTE IMMEDIATE str USING OUT ret, IN val; dbms_output.put_line('Result of '||val||' doubled is '||ret); end; Result: Result of 30 doubled is 60 8. 7ÀÇ ¿¹¿Í °°Àº functionÀ» »õ·Î¿î CALL ÀýÀ» ÀÌ¿ëÇÏ¿© ½ÇÇàÇÑ´Ù. declare str varchar2(200); val number; ret number; begin -- Call the stored function str := 'CALL doubleit(:b2) INTO :b1'; val := 30; EXECUTE IMMEDIATE str USING IN val, OUT ret; dbms_output.put_line('Result of '||val||' doubled is '||ret); end; Result: Result of 30 doubled is 60 9. Áߺ¹µÈ place holder°¡Áø SQL¹®À» ½ÇÇàÇÏ´Â ¿¹. declare str varchar2(200); val_str varchar2(20); val_num number; ret number; begin -- DML : ÀÌ °æ¿ì´Â SQL¹®À¸·Î bind variable ¼ö¸¸Å­ÀÇ place holder -- °¡ ÇÊ¿äÇÏ´Ù. str := 'insert into msg values (:b1||'' ''||:b1)'; val_str := 'Hello'; EXECUTE IMMEDIATE str USING val_str, val_str; -- PL/SQL ¿¡¼­´Â bind variable ¼ö¸¸Å­ÀÇ place holder°¡ ÇÊ¿äÇÏÁö ¾Ê´Ù. str := 'begin :b1 := doubleit(:b2+:b2); end;'; val_num := 30; EXECUTE IMMEDIATE str USING OUT ret, IN val_num; dbms_output.put_line('Result of '||val_num||' quadrupled is ' ||ret); end; Result: Result of 30 quadrupled is 120 10. NOCOPY parameterÀ» °¡Áø stored procedureÀ» ºÎ¸£´Â ¿¹. create or replace procedure add_stars (p1 in varchar2, p2 out NOCOPY varchar2) as begin p2 := p1||'***'; end; NOCOPY parameter´Â version 8.1¿¡¼­ ¼Ò°³µÇ¾ú´Ù. value¿¡ ÀÇÇØ¼­±â º¸´Ù´Â reference¿¡ ÀÇÇØ Àü´ÞµÇ¾îÁö´Â output parameterÀ̸ç, ¼º´ÉÀ» Áõ°¡½Ãų»Ó¸¸ ¾Æ´Ï¶ó ¸Þ¸ð¸®¸¦ Àý¾àÇÒ ¼ö ÀÖ´Ù. value¿¡ ÀÇÇØ Àü´ÞµÇ¾îÁö´Â parameteró·³ bind variableÀÌ ¼±¾ðµÇ¾îÁø´Ù. declare str varchar2(100) := 'call add_stars(:b1,:b2)'; in_str varchar2(20) := 'Hello World'; out_str varchar2(20); begin EXECUTE IMMEDIATE str USING IN in_str, OUT out_str; dbms_output.put_line(out_str); end; Result: Hello World*** ¹æ¹ý 2: ref cursor ---------------------- Syntax: OPEN cursor_var FOR dynamic_query_string [USING bind_arg1 [, bind_arg2] ...]; ´ÙÀ½ÀÇ ¿¹Á¦¸¦ ¼öÇàÇϱâ Àü¿¡ ¼öÇàµÇ¾îÁú »çÇ×: create table msg (msg varchar2(120)); insert into msg values ('Hello'); insert into msg values ('Bye'); Weak: type my_cur_type is ref cursor; Strong: type my_cur_type is ref cursor return emp%rowtype; 1. bind ¾øÀÌ cursorÀ» openÇÏ´Â ¿¹. declare type my_curs_type is REF CURSOR; -- must be weakly typed curs my_curs_type; str varchar2(200); ret varchar2(20); begin str := 'select msg from msg'; -- No placeholders so no USING clause OPEN curs FOR str; loop FETCH curs INTO ret; exit when curs%notfound; dbms_output.put_line(ret); end loop; CLOSE curs; end; Result: Hello Bye 2. bind variableÀ» »ç¿ëÇÏ¿© cursorÀ» openÇϰí single rowÀ» fetchÇÏ´Â ¿¹. declare type my_curs_type is REF CURSOR; -- must be weakly typed curs my_curs_type; str varchar2(200); ret varchar2(20); val varchar2(20); begin str := 'select msg from msg where msg = :b1'; val := 'Bye'; OPEN curs FOR str USING val; FETCH curs INTO ret; dbms_output.put_line('Value fetched from table: '||ret); CLOSE curs; end; Result: Value fetched from table: Bye 3. »õ·Î¿î bulk collect À» ÀÌ¿ëÇÏ¿© Çѹø¿¡ ¿©·¯ rowÀ» fetchÇÏ´Â ¿¹. declare str varchar2(200); type my_curs_type is REF CURSOR; -- must be weakly typed curs my_curs_type; -- Use a nested table to fetch into. This could equally be -- a VARRAY or index by table. type string_tab is table of varchar2(20); ret_tab string_tab; -- don't need to initialise, fetching -- will do this automatically begin str := 'select msg from msg'; OPEN curs FOR str; FETCH curs BULK COLLECT INTO ret_tab; dbms_output.put_line('Array fetch: '); for i in 1..curs%rowcount loop dbms_output.put_line(ret_tab(i)); end loop; CLOSE curs; end; Result: Array fetch: Hello Bye