2011-08-30 2 views
2

변수 테이블 이름을 사용하여 select 문을 저장하는 PL/SQL 함수를 작성하려고합니다. (실제로 이상한 결정입니다. . 다음 코드는 작동하지 않습니다 ...하지만 변수 테이블 이름 (쿼리 작성) 및 데이터 집합 반환 방법을 모두 잘 모르겠습니다. 누구든지이 경험이 있습니까? TIA.PL/SQL 및 변수 테이블 이름을 사용하여 데이터 집합 반환

CREATE OR REPLACE 
FUNCTION fn_netstat_all (
    casename IN VARCHAR2 
) 
RETURN resultset_subtype 
IS 
    dataset resultset_subtype; 
BEGIN 
    OPEN dataset 
    FOR 'SELECT * FROM ' || casename || '_netstat'; 

    RETURN dataset; 
END fn_netstat_all; 

FWIW, 당신은 도움이되는 casename 변수를 포장하기 위해 DBMS_ASSERT 패키지에보고 할 수 있습니다 : 당신의 resultset_subtype가 ref_cursor가 (또는 단지 ref_cursor와 resultset_subtype 교체) 당신이 할 수있는 경우

CREATE OR REPLACE FUNCTION fn_netstat_all (casename in varchar2) 
RETURN resultset_subtype 
IS 
    dataset resultset_subtype; 
    v_sql varchar2(25000); 
    v_tablename varchar2(50); 

begin 

    v_sql := 'SELECT * FROM ' || casename || '_netstat;'; 

    OPEN dataset FOR 
    execute immediate v_sql; 
    return dataset; 

end; 
+0

모든 테이블 구조가 동일합니까? 그렇지 않은 경우 [기본 동적 SQL] (http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/dynamic.htm#i13130)을 사용할 수 없습니다 (사용중인 것). PL/SQL 패키지 [DBMS_SQL] (http://download.oracle.com/docs/cd/E11882_01/appdev.112/e16760/d_sql.htm)에 의존해야합니다. – user272735

답변

1

동적 SQL에서 SQL 주입 공격으로부터 보호합니다.

도움이 되길 바랍니다 ...

+0

+1 SQL 주입 조언. – DCookie

+0

해당 기능이 작동하지 않습니다. 줄에서 잘못된 문자 오류가 발생했습니다 : OPEN dataset FOR 'SELECT * FROM'|| 카지노 이름 || '_netstat;'; – coergo

+0

@coergo 추가 세미콜론 (;)이 있습니다. 올바른 형식은''SELECT * FROM '|| 카지노 이름 || '_netstat'; – user272735

1

아래의 표는 모두 유사하다고 가정합니다. DBMS_SQL을 사용하지 않고 모든 테이블에서 유사한 열 집합을 선택할 수도 있습니다. 나는 또한 Ollie에 의해 언급 된 SQL injection에 약간의주의를 기울였다.

create table so9at (
    id number(1), 
    data varchar2(5) 
); 

insert into so9at values (1, 'A-AAA'); 
insert into so9at values (2, 'A-BBB'); 
insert into so9at values (3, 'A-CCC'); 

create table so9bt (
    id number(1), 
    data varchar2(5) 
); 

insert into so9bt values (5, 'B-AAA'); 
insert into so9bt values (6, 'B-BBB'); 
insert into so9bt values (7, 'B-CCC'); 

create table secret_identities (
    cover_name varchar2(20), 
    real_name varchar2(20) 
); 

insert into secret_identities values ('Batman', 'Bruce Wayne'); 
insert into secret_identities values ('Superman', 'Clark Kent'); 

/* This is a semi-secure version immune to certain kind of SQL injections. Note 
that it can be still used to find information about any table that ends with 
't'. */ 
create or replace function cursor_of (p_table_id in varchar2) 
return sys_refcursor as 
    v_cur sys_refcursor; 
    v_stmt constant varchar2(32767) := 'select * from ' || dbms_assert.qualified_sql_name(p_table_id || 't'); 
begin 
    open v_cur for v_stmt; 
    return v_cur; 
end; 
/
show errors 

/* This is an unsecure version vulnerable to SQL injection. */ 
create or replace function vulnerable_cursor_of (p_table_id in varchar2) 
return sys_refcursor as 
    v_cur sys_refcursor; 
    v_stmt constant varchar2(32767) := 'select * from ' || p_table_id || 't'; 
begin 
    open v_cur for v_stmt; 
    return v_cur; 
end; 
/
show errors 

create or replace procedure print_values_of (p_cur in sys_refcursor) as 
    type rec_t is record (
    id number, 
    data varchar2(32767) 
); 
    v_rec rec_t; 
begin 
    fetch p_cur into v_rec; 

    while p_cur%found loop 
    dbms_output.put_line('id = ' || v_rec.id || ' data = ' || v_rec.data); 
    fetch p_cur into v_rec; 
    end loop; 

end; 
/
show errors 

declare 
    v_cur sys_refcursor; 
begin 
    v_cur := cursor_of('so9a'); 
    print_values_of(v_cur); 
    close v_cur; 

    v_cur := cursor_of('so9b'); 
    print_values_of(v_cur); 
    close v_cur; 

    /* SQL injection vulnerability */ 
    v_cur := vulnerable_cursor_of('secret_identities --'); 
    dbms_output.put_line('Now we have a cursor that reveals all secret identities. Just see DBMS_SQL.DESCRIBE_COLUMNS ...'); 
    close v_cur; 

    /* SQL injection made (mostly) harmless - will throw ORA-44004: invalid qualified SQL name */ 
    v_cur := cursor_of('secret_identities --'); 
    close v_cur; 
end; 
/
관련 문제