Поиск типа данных курсора или столбца таблицы в блоке - PullRequest
4 голосов
/ 09 января 2012

Можно ли узнать тип данных столбца курсора или переменной в блоке без , используя системные таблицы?Хотя я понимаю, что могу использовать системные таблицы, чтобы найти эту информацию, она будет намного медленнее.

Что-то вроде,

declare
   my_column_data_type varchar2(30);
begin
  my_column_data_type := all_tables.table_name%type;
  dbms_output.put_line(my_column_data_type);
end;

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

Но у Oracle уже есть вся информация.Если бы я попытался присвоить varchar2 для number, он бы сразу же пожаловался, чтобы он знал, какие типы данных.

И, да, я знаю, что количество версий Oracle смешно, но этосумма, которая у нас есть на данный момент ... 9i скоро умирает в пользу 11, но этот код сразу запустится на 9i, если я смогу найти ответ!Но я включил 11, так как могу ждать лучшего решения, если это будет необходимо,

Ответы [ 2 ]

4 голосов
/ 09 января 2012

Используйте функцию dump и сравните результат с этим кодом.

DUMP возвращает значение VARCHAR2, содержащее код типа данных, длину в байтах и ​​внутреннее представление выражения.

3 голосов
/ 10 января 2012

Звучит так, как будто вы хотите объект с самоописанием.Значение означает программный поиск типа переменной без выбора из некоторого представления метаданных.Просто спросите объект, что вы?

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

В некоторых ситуациях требуются или могут быть полезны слабо типизированные объекты, например, слабо типизированная переменная курсора, которую можно использоватьдля любого запроса.Чрезмерно упрощенный пример:

create or replace procedure get_data(o_cur OUT SYS_REFCURSOR) as
begin
  OPEN o_cur FOR
  -- without changing parameter, this could select from any table
  select * from emp;
end;

Теперь проблема в том, что у вас могут быть ошибки (во время выполнения), если кто-то кодирует курсор для использования с другой таблицей ( Я специально выбрал ужасное имя процедуры).Примерно так:

declare
  l_cur sys_refcursor;
  l_row dept%rowtype;
begin
  get_data(l_cur);
  -- oops, I thought this was dept data when I coded it, Oracle didn't complain at compile time
  LOOP
    fetch l_cur
    into l_row;
    exit when l_cur%notfound;
    -- do something here
  END LOOP;
  close l_cur;
end;

По этой же причине я предпочитаю строго типизированные курсоры и избегаю этой ситуации.

В любом случае, в случае объекта с самоописанием, вы можете использовать SYS.ANYDATAвстроенный тип (аналогично SYS.ANYDATASET для универсальных типов коллекций).Это было введено с 9i я верю.Например, эта процедура использует некоторые данные и логику ветвлений в зависимости от типа:

CREATE OR REPLACE procedure doStuffBasedOnType(i_data in sys.anydata) is
  l_type         SYS.ANYTYPE;
  l_typecode     PLS_INTEGER;
begin
  -- test type
  l_typecode := i_data.GetType (l_type);

  CASE l_typecode
  when Dbms_Types.Typecode_NUMBER then
    -- do something with number
    dbms_output.put_line('You gave me a number');

  when  Dbms_Types.TYPECODE_DATE then
    -- do something with date
    dbms_output.put_line('You gave me a date');

  when  Dbms_Types.TYPECODE_VARCHAR2 then
    -- do something with varchar2
    dbms_output.put_line('You gave me a varchar2');

  else
    -- didn't code for this type...
    dbms_output.put_line('wtf?');

  end case;
end;

Здесь у вас есть программное ветвление в зависимости от типа.И чтобы использовать это:

declare
  l_data sys.anydata;
begin
  l_data := sys.anydata.convertvarchar2('Heres a string');
  doStuffBasedOnType(l_data);
end;

-- output: "You gave me a varchar2"

Надеюсь, что это не слишком долго заставило задуматься;)

...