понедельник, 31 октября 2011 г.

Динамический SQL

    Порой случается, что надо чтобы код выполнял запрос, который заранее точно не известен, для решения таких задач в СУБД Oracle существует 3 способа решения данной задачи.
    Здесь я только перечислю те решения, которыми мне доводилось пользоваться, подробности можно почерпнуть из документации Oracle.

  1. EXECUTE IMMEDIATE
    Наиболее часто используемый мной подход. После имени этой команды подаём строку с SQL запросом, которая немедленно выполняется. Для того, чтобы нас не считали неграмотными программистами используем bind переменные, которы позволяют избежать многократного распарсивания запроса. Также из EXECUTE IMMEDIATE можно возвращать данные при помощи INTO и BULK COLLECT INTO.
    Подробная документация находится по этой ссылке: http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/dynamic.htm#BHCEBBAI
  2. OPEN FOR
    Конструкция, которой я пользуюсь очень редко, т.к. обычно хватает способа под цифрой 1. По сути - это курсор, даже не знаю как его правильно назвать, явным или неявный. Дело заключается в том, что для того, чтобы воспользоваться данной командой необходимо создать курсорную переменную типа REF CURSOR. Далее работаем как и с обычными курсорами.
    Вот пример:
    declare
        type t_cursor REF CURSOR;
        cursor t_sursor;
        num number;
    begin
        OPEN cursor FOR 'select 1 from dual';
        fetch cursor into num;
        close cursor;
    end;
  3. Пакет DBMS_SQL
    Пакет очень мощный, но в тоже время не очевидный, чтобы с ним разобраться рекомендую почитать не только документацию по адресу: http://download.oracle.com/docs/cd/E14072_01/appdev.112/e10577/d_sql.htm , но и сайт на русском языке: http://osql.ru/?p=111
    Рекомендую обратить особое внимание на функции TO_CURSOR_NUMBER и TO_REFCURSOR , они помогают конвертировать курсор из обычного формата в DBMS_SQL формат и обратно.

1 комментарий:

  1. Исправте ошибки в примерах.

    declare
    type t_cursor REF CURSOR;
    cursor t_sursor;
    num number;
    begin
    OPEN cursor FOR 'select 1 from dual';
    fetch cursor into num;
    close cursor;
    end;

    на

    declare
    type t_cursor IS REF CURSOR;
    v_cur t_cursor;
    v_num number;
    begin
    OPEN v_cur FOR 'select 1 from dual';
    loop
    fetch v_cur into v_num;
    exit when v_cur%notfound;
    ... -- Обработка
    end loop;
    close v_cur;
    end;

    ОтветитьУдалить