середа, 23 березня 2016 р.

отслеживание изменений в Oracle. Если интересует дата/время последнего изменения данных

отслеживание изменений в Oracle. Если интересует только дата/время последнего изменения данных —
select max(ora_rowscn), scn_to_timestamp(max(ora_rowscn)) from scott.emp;

Подробнее у Кайта = Finding latest DML time on a table

Работаем с геоданными в Oracle Spatial

Задача: выявить неправильно проставленные КОАТУУ относительно координат.
(к примеру село слилось с городом)

Дано: таблица MOB_STA с перечнем радиостанций, их координатами в полях
longitude и latitude (с типом NUMBER) и с полем CODE_EDRPU - в котором
проставлен КОАТУУ населённого пункта в  границах которого установлена радиостанция.

вторая таблица SETTLEMENT_REGION c перечнем населённых пунктов, КОАТУ и
координатами в поле GEOMETRY, тип поля GEOMETRY. Таблица являеться эталонной.
Эта таблица создалась из ship файла, программы MapInfo, ship файл мы загрузили в Oracle с помощью программы MapBuilder, 
http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index-100641.html


Решение: найдём вхождение координат радиостанций из табл. MOB_STA в границы населённых
пунктов из табл. SETTLEMENT_REGION и сравним КОАТУУ.

== В таблицу MOB_STA нужно добавить поле и назовём его- GEOMETRY, типом поля выберем GEOMETRY, это поле мы потом заполним данными из полей longitude и latitude.

Поехали:

1. Регистрируем в базе таблицу и поле (гео) иначе индекс не создастса

insert into user_sdo_geom_metadata values (
  'MOB_STA',
  'GEOMETRY',
   sdo_dim_array(
   mdsys.sdo_dim_element('X', -180, 180, 0.05),
   mdsys.sdo_dim_element('Y', -90, 90, 0.05)), 8307);


2. Трансформируем кооздинаты в точку и в тип геометрия и заполняем  поле GEOMETRY

declare
begin
for c in(select t.* from MOB_STA t)      ----
loop
update MOB_STA m set m.geometry = sdo_geometry(2001, 8307, sdo_point_type(c.longitude ,c.latitude, null),null,null)
 where m.id = c.id;
end loop;
end;


3. Создаём индекс

create index i_MOB_STA_indx on MOB_STA(geometry) indextype is mdsys.spatial_index;

5. Теперь можно делать выборку

select b.koatuu, b.name_obl, b.join_,b.name_rus,b.codename, c.code, c.address, c.owner_name
   from
  table(sdo_join('settlement_region','GEOMETRY','mob_sta','GEOMETRY','mask=ANYINTERACT')) a,
           settlement_region b,
           mob_sta           c
   where
         a.rowid1 = b.rowid
   and a.rowid2 = c.rowid
   and b.name_obl = 'Житомирська область'
   and b.koatuu <> c.code





Подробно описаны функци Spatial
http://www.oraclegis.com/blog/?p=2622

четвер, 3 березня 2016 р.

Иерархические запросы в ORACLE

Иерархические запросы в ORACLEПечатьE-mail


SELECT level, id, pid, title 
FROM test_table
START WITH pid is null
CONNECT BY PRIOR id = pid;




в Oracle присутствует специфический функционал для работы с данными в виде иерархии
-- connect by ключевой оператор который используется для работы и иерархией в oralce
-- данными где присутствует id и parent_id - ид родителя

Запрос перечисление

-- level является перечислением - цикл по датам
-- таким образом, для перечисления интервала дат
-- следует воспользоваться данным запросом
  select level nnnn 
       from dual
     connect by level <= 10   
      NNNN
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

    

Запрос перечисление по датам

-- простое перечисление
-- специфическая переменная level отражает уровень иерархии ,который в данном запросе условен
 select trunc(sysdate-10-1+level) daten 
       from dual
     connect by level <= (sysdate-(sysdate-10))
      DATEN
    -----
      28.09.2012
      29.09.2012
      30.09.2012
      01.10.2012
      02.10.2012
      03.10.2012
      04.10.2012
      05.10.2012
      06.10.2012
      07.10.2012

    

Иерархический запрос

-- level яляется перечислением
-- пример иерархического запроса
-- специфическая переменная level отражает уровень иерархии в запросе
-- оператор connect BY отображает условие иерархии в запросе
-- в данном
WITH T AS
(
    SELECT 1 IDNULL parent_id, 'AAAA' lname FROM dual UNION ALL
    SELECT 2 ID1    parent_id, 'BBBB' lname FROM dual UNION ALL
    SELECT 3 ID1    parent_id, 'CCCC' lname FROM dual UNION ALL
    SELECT 5 ID3    parent_id, 'DDDD' lname FROM dual UNION ALL
    SELECT 4 IDNULL parent_id, 'FFFF' lname FROM dual
)
SELECT T.*,level,rpad(' ',(level-1)*4)||lname fstr
  FROM T
 connect BY PRIOR ID = parent_id

ID    PARENT_ID   LNAME LEVEL FSTR
--- ----- --- ----- ---- -----
      2 1  BBBB   1     BBBB
      3     1     CCCC  1     CCCC
      5     3     DDDD  2         DDDD
      5     3     DDDD  1     DDDD
      1           AAAA  1     AAAA
      2     1     BBBB  2         BBBB
      3     1     CCCC  2         CCCC
      5     3     DDDD  3             DDDD
      4           FFFF  1     FFFF

 start WITH

-- пример иерархии , когда выбираем ветку начала иерархии
-- опреатор  start WITH id = 1 отбражает условие выбора начальной ветки иерархии
WITH T AS
(
    SELECT 1 IDNULL parent_id, 'AAAA' lname FROM dual UNION ALL
    SELECT 2 ID1    parent_id, 'BBBB' lname FROM dual UNION ALL
    SELECT 3 ID1    parent_id, 'CCCC' lname FROM dual UNION ALL
    SELECT 5 ID3    parent_id, 'DDDD' lname FROM dual UNION ALL
    SELECT 4 IDNULL parent_id, 'FFFF' lname FROM dual
)
SELECT T.*,level,rpad(' ',(level-1)*4)||lname fstr
  FROM T
 start WITH id = 1
 connect BY PRIOR ID = parent_id

      ID    PARENT_ID   LNAME LEVEL FSTR
      1           AAAA  1     AAAA
      2     1     BBBB  2         BBBB
      3     1     CCCC  2         CCCC
      5     3     DDDD  3             DDDD



 пример иерархии , c сортировкой

-- как видим оператор order by не совсем соответствует нашим требованиям
WITH T AS
(
    SELECT 1 IDNULL parent_id, 'AAAA' lname FROM dual UNION ALL
    SELECT 2 ID1    parent_id, 'BBBB' lname FROM dual UNION ALL
    SELECT 3 ID1    parent_id, 'CCCC' lname FROM dual UNION ALL
    SELECT 5 ID3    parent_id, 'DDDD' lname FROM dual UNION ALL
    SELECT 4 IDNULL parent_id, 'FFFF' lname FROM dual
)
SELECT T.*,level,rpad(' ',(level-1)*4)||lname fstr
  FROM T
 connect BY PRIOR ID = parent_id
 ORDER SIBLINGS  by lname
ORDER SIBLINGS
--коректнее было бы использовать оперетор ORDER SIBLINGS
ID    PARENT_ID   LNAME LEVEL FSTR
      2     1     BBBB  1     BBBB
      3     1     CCCC  1     CCCC
      5     3     DDDD  2         DDDD
      5     3     DDDD  1     DDDD
      1           AAAA  1     AAAA
      2     1     BBBB  2         BBBB
      3     1     CCCC  2         CCCC
      5     3     DDDD  3             DDDD
      4           FFFF  1     FFFF







SELECT LPAD(name,LENGTH(name)+(level-1)*4) AS name 
  FROM my_table
  CONNECT BY PRIOR id = parent_id
  START WITH parent_id IS NULL
После выполнения такого иерархического запроса мы увидим примерно следующую картину:
oracle connect by