Как определить типы динамически в PLSQL - PullRequest
2 голосов
/ 12 мая 2011

У меня есть такая процедура:

create or replace procedure pname (tn varchar2) is
-- here i want to declare the variable

  col1 tn%COL_ID

begin

end;

и я знаю, что каждая таблица, которую я передаю в качестве аргумента, будет содержать столбец с именем COL_ID. Но я не могу этого сделать, я получаю сообщение об ошибке, подобное этому

PLS-00487: недопустимая ссылка на переменную 'tn' PL / SQL: элемент игнорируется PLS-00487: недопустимая ссылка на переменную 'tn' PL / SQL: элемент игнорируется

Пожалуйста, помогите мне, как объявлять такие переменные.

Ответы [ 3 ]

4 голосов
/ 12 мая 2011

Интересный вопрос. Как отметил APC, Oracle, как и другие языки, не имеет рефлексии, так что передача имени (varchar2) не сильно помогает Oracle (особенно во время компиляции). Я полагаю, что вы здесь говорите, что у вас есть набор таблиц, которые имеют общие характеристики (1 или более столбцов одного типа, используемых одинаковым образом), поэтому вы хотите создать универсальную функцию, которая будет работать для любой из их.

Вы можете сделать это, но вам нужно будет определить тип объекта, который определяет общие столбцы и типы, которые разделяют ваши различные таблицы. Скажем, это следующие 2 столбца:

create or replace type my_obj as object (name varchar2(100), num number);

Теперь ваша функция (или процедура) будет принимать этот тип в качестве параметра:

create or replace function my_fn(obj my_obj) return varchar2 is
  begin
    -- do something with object
    return obj.name || ',' || obj.num;
  end;

И вы бы назвали это так:

declare
    obj my_obj;
    rv varchar2(1000);
  begin
    for rec in (select * from sometable)
    loop
      obj := my_obj(rec.some_varchar_col, rec.some_number_col);
      select my_fn(obj) into rv from dual;
      dbms_output.put_line(rv);
    end loop;
  end;

Единственный другой способ, который я могу придумать, - это принять слабо типизированный sys_refcursor и затем заставить вызывающие процессы отправлять правильный курсор (рискованно из-за потенциальных исключений во время выполнения и не очень ясно). Я предпочитаю описанный выше подход, если кодирую «универсальную» функцию.

EDIT Чтобы закончить, я добавлю пример sys_refcursor, который я упомянул выше:

create or replace procedure my_proc(cur sys_refcursor) is
  v_name varchar2(100);
  v_num number;
begin
  loop
    fetch cur into v_name, v_num;
    exit when cur%notfound;

    -- do something with our common fields
    dbms_output.put_line(v_name || ',' || v_num);
  end loop;
end;

И назовите это как:

declare
  v_cur sys_refcursor;
begin
  open v_cur for select my_name, my_num from some_table;
  my_proc(v_cur);
  close v_cur;
end;

Примечание Это кажется слишком тривиальным с двумя столбцами (почему бы просто не задать параметры как varchar2 и число), но у вас могут быть десятки столбцов, над которыми вы хотите работать в функции, и входной объект может иметь любое количество заполненных ими.

Приветствия

3 голосов
/ 12 мая 2011

Просмотрите все типы данных, используемые COL_ID во всех таблицах, которые вы можете передать процедуре.Скорее всего, все они могут вписаться в один из базовых типов данных - то есть NUMBER, VARCHAR2(4000).

Создать отдельную процедуру для каждого типа данных, вызвать соответствующую версию процедуры (или выработатькакую переменную использовать с логикой в ​​процедуре) и не беспокойтесь о привязке типа.

3 голосов
/ 12 мая 2011

Синтаксис такой:

declare
    col1  t23.col1%type;
begin
    null;
end;
/ 

Комплект документации Oracle находится в сети. Найдите здесь . Информация о% TYPE содержится в Руководстве пользователя PL / SQL .


"В вашем примере t23 - таблица. Не параметр с именем таблицы. "

Справедливая точка зрения. Я предполагал, что каждое объявление COL1 имеет один и тот же тип данных, поэтому объявление его с использованием одного фиксированного имени таблицы будет работать для всех таблиц. Если это не так, то я согласен, что мое решение не сработает.

Проблема с передачей имени таблицы является обычной: PL / SQL ее не поддерживает. Это не имеет ничего общего с отражением в Java.

Всегда есть динамический SQL, но это может быть излишним. Я думаю, что ОП должен предоставить больше деталей о том, чего они пытаются достичь.

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