Архив

Публикации с меткой ‘SQL’

SYS_CONTEXT

15 Февраль 2012 Нет комментариев

Стандартная функция SYS_CONTEXT служит для получения атрибутов контекста.
Пример использования SYS_CONTEXT для получения общей информации:

select SYS_CONTEXT('USERENV', 'TERMINAL') terminal
      ,SYS_CONTEXT('USERENV', 'LANGUAGE') language
      ,SYS_CONTEXT('USERENV', 'LANG') lang     
      ,SYS_CONTEXT('USERENV', 'SESSIONID') sessionid
      ,SYS_CONTEXT('USERENV', 'INSTANCE') instance
      ,SYS_CONTEXT('USERENV', 'ENTRYID') entryid
      ,SYS_CONTEXT('USERENV', 'ISDBA') isdba
      ,SYS_CONTEXT('USERENV', 'NLS_TERRITORY') nls_territory
      ,SYS_CONTEXT('USERENV', 'NLS_CURRENCY') nls_currency
      ,SYS_CONTEXT('USERENV', 'NLS_CALENDAR') nls_calendar
      ,SYS_CONTEXT('USERENV', 'NLS_DATE_FORMAT') nls_date_format
      ,SYS_CONTEXT('USERENV', 'NLS_DATE_LANGUAGE') nls_date_language
      ,SYS_CONTEXT('USERENV', 'NLS_SORT') nls_sort
      ,SYS_CONTEXT('USERENV', 'CURRENT_USER') current_user
      ,SYS_CONTEXT('USERENV', 'CURRENT_USERID') current_userid
      ,SYS_CONTEXT('USERENV', 'CURRENT_SCHEMAID' ) current_schemaid
      ,SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA' ) current_schema
      ,SYS_CONTEXT('USERENV', 'SESSION_USER') session_user
      ,SYS_CONTEXT('USERENV', 'SESSION_USERID') session_userid
      ,SYS_CONTEXT('USERENV', 'PROXY_USER') proxy_user
      ,SYS_CONTEXT('USERENV', 'PROXY_USERID') proxy_userid
      ,SYS_CONTEXT('USERENV', 'DB_DOMAIN') db_domain
      ,SYS_CONTEXT('USERENV', 'DB_NAME') db_name
      ,SYS_CONTEXT('USERENV', 'HOST') host
      ,SYS_CONTEXT('USERENV', 'OS_USER') os_user
      ,SYS_CONTEXT('USERENV', 'EXTERNAL_NAME') external_name
      ,SYS_CONTEXT('USERENV', 'IP_ADDRESS') ip_address
      ,SYS_CONTEXT('USERENV', 'NETWORK_PROTOCOL') network_protocol
      ,SYS_CONTEXT('USERENV', 'BG_JOB_ID') bg_job_id
      ,SYS_CONTEXT('USERENV', 'FG_JOB_ID') fg_job_id
      ,SYS_CONTEXT('USERENV', 'AUTHENTICATION_TYPE') authentication_type
      ,SYS_CONTEXT('USERENV', 'AUTHENTICATION_DATA') authentication_data
      ,SYS_CONTEXT('USERENV', 'CURRENT_SQL') current_sql
      ,SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') client_identifier
      ,SYS_CONTEXT('USERENV', 'GLOBAL_CONTEXT_MEMORY') global_context_memory
from dual

Oracle® Database SQL Language Reference
11g Release 2 (11.2): Table 5-11 Predefined Parameters of Namespace USERENV

Список группы запросов для параллельных программ

10 Январь 2012 Нет комментариев

Простой, но довольно полезный запрос для определения группы запросов параллельной программы.

select  rg.request_group_name
      , rg.description
      , cp.concurrent_program_name
      , cp.user_concurrent_program_name
  from fnd_request_group_units    rgu
     , fnd_concurrent_programs_vl cp
     , fnd_request_groups         rg
 where 1=1
       -- rg
       and rg.request_group_id=rgu.request_group_id
       -- cp
       and cp.concurrent_program_id=rgu.request_unit_id
       and cp.application_id=rgu.unit_application_id
       and cp.concurrent_program_name like 'XX%'
order by rg.request_group_name, cp.concurrent_program_name

Иерархия организаций

28 Октябрь 2011 Нет комментариев

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

 SELECT LPAD(' ', 10 * (LEVEL - 1)) || org.name hierarchy,
       org.organization_id
  FROM hr_all_organization_units org, per_org_structure_elements pose
 WHERE 1 = 1
   AND org.organization_id = pose.organization_id_child
   AND pose.org_structure_version_id = &p_structure_version_id
-- START WITH org.organization_id =
CONNECT BY PRIOR pose.organization_id_child = pose.organization_id_parent
 ORDER SIBLINGS BY org.location_id, pose.organization_id_child;

Замена N-ного символа в строке

28 Октябрь 2011 2 comments

Для замены N-ного символа в строке, можно обойтись и без SUBSTR — использовать REGEXP_REPLACE.

select regexp_replace('208010100000','.','X', 5, 1) as res from dual
union all
select regexp_replace('208010100000','.','X', 2, 1) as res from dual;

RES
------------
2080X0100000
2X8010100000

Функция LISTAGG (объединение строк)

20 Сентябрь 2011 18 comments

LISTAGG упорядочивает данные, объединенные в группы конструкцией ORDER BY, затем соединяет указаный столбец measure_expr.

1) Как одиночная агрегатная функция, LISTAGG обрабатывает все строки и возвращает одно значение.

2) Как групповая агрегатная функция, LISTAGG обрабатывает и возвращает данные для каждой группы определенной в GROUP BY.

3) Как аналитическая функция, LISTAGG обрабатывает данные разбитые на блоки, задаваемые одним или несколькими выражениями query_partition_clause.

Пример агрегатной функции

SQL> select deptno, LISTAGG(t.ename, ', ') WITHIN GROUP (order by t.empno) as ename_list
  2  from scott.emp t
  3  group by deptno;

DEPTNO ENAME_LIST
------ --------------------------------------------------------------------------------
    10 CLARK, KING, MILLER
    20 SMITH, JONES, SCOTT, ADAMS, FORD, SMIT2
    30 ALLEN, WARD, MARTIN, BLAKE, TURNER, JAMES

Пример аналитической функции

SQL> select deptno,
  2         ename,
  3         job,
  4         hiredate, listagg(t.ename, ', ') 
  6           WITHIN GROUP(order by t.empno) over(partition by deptno) as ename_list
  7  from scott.emp t
  8  where hiredate > to_date('01-01-1982','dd-mm-yyyy');

DEPTNO ENAME      JOB       HIREDATE    ENAME_LIST
------ ---------- --------- ----------- -----------------------
    10 MILLER     CLERK     23.01.1982  MILLER
    20 SCOTT      ANALYST   09.12.1982  SCOTT, ADAMS, SMIT2
    20 ADAMS      CLERK     12.01.1983  SCOTT, ADAMS, SMIT2
    20 SMIT2      CLERK     25.07.2011  SCOTT, ADAMS, SMIT2

Oracle Database SQL Language Reference 11g Release 2 : LISTAGG

Функции для работы с коллекциями

19 Сентябрь 2011 Нет комментариев

Рассмотрим функции для работы с nested tables и varrays (11G)

Сделаем nested tables для примеров:

create or replace type test_number_table as table of number(20);

CARDINALITY

CARDINALITY возвращает число элеметов в nested table. Тип возращаемого значения NUMBER.
Если вложенная таблица пустая или is null, тогда CARDINALITY вернет NULL.

SQL> select CARDINALITY(test_number_table(1,2,3,4,5,1,2)) as t_cardinality from dual;

T_CARDINALITY
-------------
            7

Читать дальше про “Функции для работы с коллекциями” »

Скрипт копирования аттачмент функции

8 Сентябрь 2011 Нет комментариев


Если, при кастомизации стандартной формы OEBS, возникает необходимость сохранить функциональность аттачментов, то реализовать это поможет следующий скрипт:

Читать дальше про “Скрипт копирования аттачмент функции” »

Поиск значения по всем таблицам

7 Сентябрь 2011 19 comments

Поиск значения по всем таблицам

Вариант1:

DECLARE
  match_count   INTEGER;
  query_str     VARCHAR2(400);
  l_owner       VARCHAR2(10)  := 'SCOTT';
  l_search_text VARCHAR2(100) := '10';
BEGIN
  FOR t IN (select table_name, column_name FROM all_tab_columns a
            where owner = l_owner
                  and a.data_type in ('NUMBER', 'VARCHAR2')
            )
  LOOP
    begin
      match_count := 0;
      query_str   := 'SELECT COUNT(*) FROM ' ||l_owner||'.'|| t.table_name ||
                     ' WHERE to_char(' || t.column_name || ') = :1';
      EXECUTE IMMEDIATE query_str
        INTO match_count
        USING l_search_text;
      IF match_count > 0 THEN
        dbms_output.put_line(l_owner||'.'||t.table_name || ' ' || t.column_name || ' ' || match_count);
        dbms_output.put_line('  SELECT t.'|| t.column_name || ', t.* from '||l_owner||'.'|| t.table_name||' t where to_char(' || t.column_name || ') = '''||l_search_text||'''');
        dbms_output.put_line('');
      END IF;
    exception
     when others then
       dbms_output.put_line(t.table_name||'.'||t.column_name||' : '||SQLERRM||' : '||SQLCODE);
       dbms_output.put_line(query_str);
       dbms_output.put_line('');
       /*raise*/
    end;
  END LOOP;
END;

Вариант2:

--SET SERVEROUTPUT ON SIZE 1000000
DECLARE
  TYPE tab_columns_rec_type IS RECORD (
    table_name   all_tab_columns.table_name%type
   ,column_name  all_tab_columns.column_name%type
   ,data_type    all_tab_columns.data_type%type
  );
  type tab_columns_tab_type is table of tab_columns_rec_type index by binary_integer;
  l_tab_columns_rec tab_columns_tab_type;
 
  match_count   INTEGER;
  query_str     VARCHAR2(400);
  l_owner       VARCHAR2(10)  := 'SCOTT';
  l_search_text VARCHAR2(100) := '10'; -- % добавляем здесь, если ищем не по точному вхождению
  l_number      NUMBER;
  is_number     NUMBER(1);
  l_str_length  NUMBER;
  /*
  l_mode:
  1 - NUMBER и VARCHAR2
  2 - only NUMBER
  3 - only VARCHAR2
  */
  l_mode NUMBER := 1;
  -- При каком количестве найденные совпадений
  -- прекращать поиск
  l_found_count  NUMBER := 1; 
  l_exists_count NUMBER;
BEGIN
 
  l_str_length := length(l_search_text);
 
  begin
    l_number := to_number(l_search_text);
    is_number := 1;
  exception
    when VALUE_ERROR then
      is_number := 0;
  end;
 
  if (l_mode = 1 and is_number = 1) then
    select table_name, column_name, data_type
      bulk collect into l_tab_columns_rec
    FROM all_tab_columns a
    where owner = l_owner
          and a.data_length >= l_str_length
          and ( a.data_type = 'VARCHAR2' or a.data_type = 'NUMBER' );
  elsif (l_mode = 2 and is_number = 1) then
    select table_name, column_name, data_type
      bulk collect into l_tab_columns_rec
    FROM all_tab_columns a
    where owner = l_owner
          and a.data_length >= l_str_length
          and a.data_type = 'NUMBER';
  else
    select table_name, column_name, data_type
      bulk collect into l_tab_columns_rec
    FROM all_tab_columns a
    where owner = l_owner
          and a.data_length >= l_str_length
          and a.data_type = 'VARCHAR2';
  end if;
  l_exists_count := 0;
  if NOT (l_tab_columns_rec is null or l_tab_columns_rec.count = 0) then
    for j in l_tab_columns_rec.first..l_tab_columns_rec.last
    LOOP
        begin
          match_count := 0;
          if (l_tab_columns_rec(j).data_type = 'VARCHAR2') then
            query_str   := 'SELECT count(*) FROM ' ||l_owner||'.'|| l_tab_columns_rec(j).table_name ||
                           ' WHERE rownum = 1 and to_char(' || l_tab_columns_rec(j).column_name || ') = :1';
            EXECUTE IMMEDIATE query_str
              INTO match_count
              USING l_search_text;
          elsif (l_tab_columns_rec(j).data_type = 'NUMBER') then
            query_str   := 'SELECT count(*) FROM ' ||l_owner||'.'|| l_tab_columns_rec(j).table_name ||
                           ' WHERE rownum = 1 and ' || l_tab_columns_rec(j).column_name || ' = :1';
            EXECUTE IMMEDIATE query_str
              INTO match_count
              USING l_number;
          end if;
 
          IF match_count > 0 THEN
            l_exists_count := l_exists_count + 1;
            dbms_output.put_line(l_tab_columns_rec(j).data_type||' '||l_owner||'.'||l_tab_columns_rec(j).table_name || ' ' || l_tab_columns_rec(j).column_name );
            dbms_output.put_line('  SELECT t.'|| l_tab_columns_rec(j).column_name || ', t.* from '||l_owner||'.'|| l_tab_columns_rec(j).table_name||' t where to_char(' || l_tab_columns_rec(j).column_name || ') like '''||l_search_text||'''');
            dbms_output.put_line('');
            if (l_exists_count = l_found_count) then
              exit;
            end if;
          END IF;
        exception
         when others then
           dbms_output.put_line(l_tab_columns_rec(j).table_name||'.'||l_tab_columns_rec(j).column_name||' : '||SQLERRM||' : '||SQLCODE);
           dbms_output.put_line(query_str);
           dbms_output.put_line('');
           /*raise*/
        end;
      END LOOP;
  end if;
 
END;
Categories: oracle, SQL Tags: , ,

Жадная и ленивая квантификация в регулярных выражениях

16 Август 2011 Нет комментариев

GREEDY AND LAZY IN REGEXP

Квантификация — поиск последовательностей;
Определяет, сколько раз предшествующее выражение может встречаться.

Квантификатор может относиться более чем к одному символу в регулярном выражении, только если это символьный класс или группа.



Таблица 2: Квантификаторы и операторы повтора

Квантификатор Описание Пример
* Встречается 0 и более раз REGEXP_REPLACE(str, ’11*’, ‘1’)
Результат:
test11 => test1
11123345 => 123345
? Встречается 0 или 1 раз
+ Встречается 1 и более раз REGEXP_LIKE(str,’5+’)
Результат:
test11 => false
11123345 => true
{m} Встречается ровно m раз REGEXP_LIKE(str,’3{2}’)
Результат:
test11 => false
11123345 => true
{m,} Встречается по крайней мере m раз
{m, n} Встречается по крайней мере m раз, но не более n раз


Жадная квантификация — это стремление захватить максимально длинную строку, которая соответствует шаблону.

SQL> with t as (
  2   select '<div><img src="http://apps-oracle.ru/logo2.png" alt=""/></div>' str from dual
  3  )
  4  select regexp_substr(str,'<.*>') as res from t;

RES
--------------------------------------------------------------
<div><img src="http://apps-oracle.ru/logo2.png" alt=""/></div>


Ленивая квантификация — это стремление захватить максимально короткую строку, которая соответствует шаблону. Поддерживается с версии 10gR2.

SQL> with t as (
  2   select '<div><img src="http://apps-oracle.ru/logo2.png" alt=""/></div>' str from dual
  3  )
  4  select regexp_substr(str,'<.*?>') as res from t;

RES
-----
<div>



Жадный Ленивый
* *?
+ +?
{n,} {n,}?




Result Cache

SQL Query Result Cache

Возможности Query Result Cache

  • Позволяет кэшировать результаты запросов, подзапросов.
  • Кэш совместно используется SQL операторами и сессиями пользователей.
  • Значительное ускорение операций чтения
  • Кэш обновляется при изменении таблиц, из которых получен кэшируемый результат
  • Result Cache для параметризованного запроса может переиспользоваться если запрос выполняется с теми же параметрами
  • Добавление RESULT_CACHE во вложенные представления отключает оптимизацию между внешним и вложенным представлением в целях максимального повторного использования результата из кэша

Кэширование отключено в случае

  • Временные или dictionary-таблицы
  • Недетерминированные PL/SQL функции
  • Использование CURRVAL и NEXTVAL
  • Недетерминированные SQL функции: sysdate, current_date и др.
  • Запрос основанный на согласованном чтение данных, которые старше чем последняя сохраненная версия, не будет кешироваться


Для явного указания, что запрос необходимо кэшировать используем хинт result_cache.

select /*+ RESULT_CACHE */
       p.prod_category,
       sum(s.amount_sold) revenue
  from products p, sales s
 where s.prod_id = p.prod_id
       and s.time_id between to_date('01-JAN-2006', 'dd-MON-yyyy')
                             to_date('31-DEC-2006', 'dd-MON-yyyy')
 group by rollup(p.prod_category);

------------------------------------------------------------------
| Id  | Operation                   | Name                       |
------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                            |
|   1 |  RESULT CACHE               | fz6cm4jbpcwh48wcyk60m7qypu |
|   2 |   SORT GROUP BY ROLLUP      |                            |
|*  3 |    HASH JOIN                |                            |
|   4 |     PARTITION RANGE ITERATOR|                            |
|*  5 |      TABLE ACCESS FULL      | SALES                      |
|   6 |     VIEW                    | index$_join$_001           |
|*  7 |      HASH JOIN              |                            |
|   8 |       INDEX FAST FULL SCAN  | PRODUCTS_PK                |
|   9 |       INDEX FAST FULL SCAN  | PRODUCTS_PROD_CAT_IX       |
------------------------------------------------------------------

Читать дальше про “Result Cache” »

Categories: SQL Tags: ,