Возвращение набора данных с PL / SQL и именем таблицы переменных - PullRequest
2 голосов
/ 31 августа 2011

Я пытаюсь написать функцию PL / SQL для хранения оператора select с именем таблицы переменных (я знаю, что это немного странно, но на самом деле это хорошее дизайнерское решение).Следующий код не работает ... но я не уверен, как взять имя переменной таблицы (создание запроса) и вернуть набор данных.У кого-нибудь есть опыт в этом?TIA.

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;

Ответы [ 2 ]

1 голос
/ 01 сентября 2011

Ниже предполагается, что все таблицы похожи. Также можно выбрать подмножество столбцов, которые похожи в каждой таблице, без использования DBMS_SQL . Я также обратил некоторое внимание на SQL-инъекцию, упомянутую Олли.

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;
/
1 голос
/ 31 августа 2011

Если ваш resultset_subtype является ref_cursor (или просто замените resultset_subtype на ref_cursor), вы можете:

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, вы можете захотеть заглянуть в пакет DBMS_ASSERT, чтобы обернуть переменную casename для защиты отАтаки SQL-инъекций в вашем динамическом SQL.

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...