Oracle DB, Oracle APEX, Linux etc.

пятница, 29 октября 2010 г.

Oracle SQL Developer: ORA-12705

Честно говоря, я лично не сталкивался с этой ошибкой. Под Debian GNU/Linux мне достаточно было указать соответствующие NLS-настройки в Tools->Preferences->Database->NLS:


С учётом моей локали, больше ничего не потребовалось.

suppler@dark-place:~$ locale
LANG=ru_UA.UTF-8
LC_CTYPE="ru_UA.UTF-8"
LC_NUMERIC="ru_UA.UTF-8"
LC_TIME="ru_UA.UTF-8"
LC_COLLATE="ru_UA.UTF-8"
LC_MONETARY="ru_UA.UTF-8"
LC_MESSAGES="ru_UA.UTF-8"
LC_PAPER="ru_UA.UTF-8"
LC_NAME="ru_UA.UTF-8"
LC_ADDRESS="ru_UA.UTF-8"
LC_TELEPHONE="ru_UA.UTF-8"
LC_MEASUREMENT="ru_UA.UTF-8"
LC_IDENTIFICATION="ru_UA.UTF-8"
LC_ALL=

Тем не менее, есть один проверенный способ. Необходимо добавить в один из конфигурационных файлов SQL Developer опции с явным указанием языка и страны. Например, в <sqldeveloper_root_dir>/sqldeveloper/bin/sqldeveloper.conf:

AddVMOption -Duser.language=en
AddVMOption -Duser.country=US

Надеюсь, эта заметка вместе с другой сэкономит кое-кому время.
Читать далее

четверг, 21 октября 2010 г.

Oracle APEX: Кому дать привилегии?

В ситуации, когда приложение работает с несколькими схемами БД, часто возникает вопрос: какому пользователю дать привилегии на запрос/DML/выполнение, чтобы приложение спокойно могло обращаться к объектам этих схем? Ответ прост: дайте привилегии пользователю-владельцу схемы разбора приложения (aka parsing schema). Вы можете узнать имя пользователя, зайдя в Application->Edit Application Properties и глянув на Name->Parsing Schema. Также можно выполнить запрос:
select owner from apex_applications where application_id = :p_your_app_id;
Это тот пользователь, от имени которого выполняются все операторы и PL/SQL-блоки в Вашем приложении, так что именно ему требуется права на всё, с чем работает приложение.

Кое-кто предпочитает дать привилегии всем, дав их роли PUBLIC, но на мой взгляд, простота часто не стоит безопасности. Лучше пожертвовать временем и дать привилегии тем, кому они действительно нужны, чем пожертвовать безопасностью.

Если кто-то заинтересовался, как же в сессии пользователя ANONYMOUS/APEX_PUBLIC_USER выполняются операторы и PL/SQL-код с правами пользователя-владельца схемы разбора, то можно поискать в Сети информацию про недокументированный пакет DBMS_SYS_SQL.

Надеюсь, что вопрос исчерпан. Удачи!
Читать далее

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

Небольшое обновление в блоге

Я обновил Syntax Highlighter до версии 3.0.83, так что теперь, чтобы выделить текст в блоке с кодом, достаточно двойного щелчка по нему. Спасибо Алексу Горбачёву за этот замечательный проект!
Читать далее

воскресенье, 17 октября 2010 г.

Oracle: С опозданием о паре вещей...

0. Oracle SQL Developer 3.0 EA1 вполне себе доступен для скачивания. Список новых возможностей можно посмотреть здесь.
1. Oracle SQL Developer Data Modeler теперь бесплатен! Версию 3.0 EA1 можно скачать здесь.

Я знаю, что это не новости, но тем не менее, вести приятные. Как компенсация - интересный слух с OOW 2010: общественности стало известно, что работы над Oracle XE 11g уже ведутся, и что допустимый объём пользовательских данных поднимут с 4 до 10 ГБ...
Читать далее

четверг, 14 октября 2010 г.

Oracle APEX: Почему возникла ошибка 404?

The requested URL /pls/apex/wwv_flow.accept was not found on this server.

Знакомо? Что-то произошло, но что именно - расскажет лог HTTP-сервера. А что, если к нему нет доступа в эти моменты, или нет времени, чтобы добираться к файлу error_log.xxxxx? Не проблема! Всё, что нужно - добавить следующее в dads.conf/marvel.conf в <Location /pls/apex>:

...
 PlsqlErrorStyle  DebugStyle
 ...

И Вы получите подробное описание ошибки вместо невразумительной Error 404.

А что делать, если Вы используете EPG? Настраивать его DAD через соответствующий пакет, конечно:

exec dbms_epg.set_dad_attribute('APEX', 'error-style', 'DebugStyle');

Выполните вышеуказанный блок от пользователя SYS или другого, у которого есть роль XDBADMIN. И дело в шляпе.
Читать далее

воскресенье, 3 октября 2010 г.

Oracle Materialized Views: DBMS_MVIEW.EXPLAIN_MVIEW с человеческим лицом

Хочу упомянуть одну полезную функцию, которую я нашёл на SQL Snippets. Она автоматизирует весь тот процесс, который обычно выполняется при экспериментах с материализованными представлениями: вызов DBMS_MVIEW.EXPLAIN_MVIEW, вывод информации на экран, очистка MV_CAPABILITIES_TABLE. Теперь достаточно просто вызвать эту функцию в запросе, указав текст или имя материализованного представления:
SQL> set long 5000
SQL> select my_mv_capabilities(q'[select mgr, count(*) from emp group by mgr]', 'REFRESH') from dual;

MY_MV_CAPABILITIES(Q'[SELECTMGR,COUNT(*)FROMEMPGROUPBYMGR]','REFRESH')
--------------------------------------------------------------------------------

Capable of:

  REFRESH_COMPLETE

Not Capable of:

  REFRESH_FAST

  REFRESH_FAST_AFTER_INSERT
    HES.EMP

MY_MV_CAPABILITIES(Q'[SELECTMGR,COUNT(*)FROMEMPGROUPBYMGR]','REFRESH')
--------------------------------------------------------------------------------
    таблица подробных данных не содержит журнал материализованного
    представления

  REFRESH_FAST_AFTER_ONETAB_DML
    см. причину отключения REFRESH_FAST_AFTER_INSERT

  REFRESH_FAST_AFTER_ANY_DML
    см. причину отключения REFRESH_FAST_AFTER_ONETAB_DML

Текст самой функции ниже:
create or replace function my_mv_capabilities
(
  p_mv                       in  varchar2 ,
  p_capability_name_filter   in  varchar2 default '%' ,
  p_include_pct_capabilities in  varchar2 default 'N' ,
  p_linesize                 in  number   default 80
)
  return clob
as
  --------------------------------------------------------------------------------
  -- From http://www.sqlsnippets.com/en/topic-12884.html
  --
  -- Parameters:
  --
  --   p_mv
  --     o this value is passed to DBMS_MVIEW.EXPLAIN_MVIEW's "mv" parameter
  --     o it can contain either a query, CREATE MATERIALIZED VIEW command text,
  --       or a materialized view name
  --
  --   p_capability_name_filter
  --     o use either REFRESH, REWRITE, PCT, or the default
  --
  --   p_include_pct_capabilities
  --     Y - capabilities like REFRESH_FAST_PCT are included in the report
  --     N - capabilities like REFRESH_FAST_PCT are not included in the report
  --
  --   p_linesize
  --     o the maximum size allowed for any line in the report output
  --     o data that is longer than this value will be word wrapped
  --
  -- Typical Usage:
  --
  --   set long 5000
  --   select my_mv_capabilities( 'MV_NAME' ) as mv_report from dual ;
  --
  --   o the value 5000 is arbitraty; any value big enough to contain the
  --     report output will do
  --
  --------------------------------------------------------------------------------

  pragma autonomous_transaction ;

  v_nl constant char(1) := unistr( '\000A' ); -- new line

  v_previous_possible char(1) := 'X' ;

  v_capabilities sys.ExplainMVArrayType ;

  v_output clob ;

begin

  dbms_mview.explain_mview( mv => p_mv, msg_array => v_capabilities ) ;

  for v_capability in
  (
    select
      capability_name ,
      possible ,
      related_text ,
      msgtxt
    from
      table( v_capabilities )
    where
      capability_name like '%' || upper( p_capability_name_filter ) || '%' and
      not
        ( capability_name like '%PCT%' and
          upper(p_include_pct_capabilities) = 'N'
        )
    order by
      mvowner ,
      mvname ,
      possible desc ,
      seq
  )
  loop

    ------------------------------------------------------------
    -- print section heading
    ------------------------------------------------------------

    if v_capability.possible <> v_previous_possible then

      v_output :=
        v_output
        || v_nl
        || case v_capability.possible
           when 'T' then 'Capable of: '
           when 'Y' then 'Capable of: '
           when 'F' then 'Not Capable of: '
           when 'N' then 'Not Capable of: '
           else v_capability.possible || ':'
           end
        || v_nl
      ;

    end if;

    v_previous_possible := v_capability.possible ;

    ------------------------------------------------------------
    -- print section body
    ------------------------------------------------------------
    declare

      v_indented_line_size varchar2(3) := to_char( p_linesize - 5 );

    begin

      -- print capability name indented 2 spaces

      v_output :=
        v_output
        || v_nl
        || '  '
        || v_capability.capability_name
        || v_nl
      ;

      -- print related text indented 4 spaces and word wrapped

      if v_capability.related_text is not null then

        v_output :=
          v_output
          || regexp_replace
             ( v_capability.related_text || ' '
             , '(.{1,'
                 || v_indented_line_size || '} |.{1,'
                 || v_indented_line_size || '})'
             , '    \1' || v_nl
             )
        ;

      end if;

      -- print message text indented 4 spaces and word wrapped

      if v_capability.msgtxt is not null then

        v_output :=
          v_output
          || regexp_replace
             ( v_capability.msgtxt || ' '
             , '(.{1,'
                 || v_indented_line_size || '} |.{1,'
                 || v_indented_line_size || '})'
             , '    \1' || v_nl
             )
        ;

      end if;

    end;

  end loop;

  commit ;

  return( v_output );

end;
/
Большое спасибо автору этой функции! Она упрощает жизнь.
Читать далее

суббота, 2 октября 2010 г.

Nested Materialized Views: Must contain joins or aggregates. No exclusions...

Data Warehousing Guide говорит нам:

You can create a nested materialized view on materialized views, but all parent and base materialized views must contain joins or aggregates. If the defining queries for a materialized view do not contain joins or aggregates, it cannot be nested.

Как по мне, это условие насчёт обязательности агрегатов или соединения иногда только мешает. Например, у нас есть материализованное представление, необходимо на его основе сделать ещё одно, использующее детерминированные пользовательские функции для расчёта значений столбцов и быстро обновляющееся при фиксации изменений (REFRESH FAST ON COMMIT). Попробуйте этого добиться без агрегатов и соединений в запросе материализованного представления - у Вас ничего не выйдет, как бы Вы не ухищрялись с текстом запроса и журналом материализованного представления!

Решение простое: добавьте соединение с тем же самым материализованным представлением, используя rowid в качестве столбца-соединителя, выполните требования к материализованным представлениям с соединением для быстрого обновления - вуаля! Всё работает.

Тест-кейс:
create materialized view log on emp
  with rowid (empno, mgr, sal)
  including new values;
  
create materialized view mv$sub_sal
  refresh fast on commit
  as
select nvl(mgr, empno) mgr, sum(sal) sal, count(sal) sal_cnt, count(*) row_cnt
  from emp
 group by nvl(mgr, empno);
 
create function test_fu(p_mgr number, p_sal number)
  return number
  deterministic
as
begin
  return p_sal * case when p_sal > 5000 or p_mgr = 7788 then 1.2 else 1 end;
end;
/

alter table mv$sub_sal add constraint mv$sub_sal_pk primary key(mgr);

create materialized view log on mv$sub_sal
  with rowid;
  
create materialized view mv$calc_sub_sal
  refresh fast on commit
  as
select m1.mgr, test_fu(m1.mgr, m1.sal) calc_sal, m1.rowid m1_row_id, m2.rowid m2_row_id
  from mv$sub_sal m1, mv$sub_sal m2
 where m1.rowid = m2.rowid;

Удаление:
drop materialized view mv$calc_sub_sal;
drop materialized view log on mv$sub_sal;
drop function test_fu;
drop materialized view mv$sub_sal;
drop materialized view log on emp;

Читать далее