Как получить рекурсивную информацию в Oracle Apex? - PullRequest
0 голосов
/ 06 ноября 2018

В моем приложении Apex есть возможность установить фильтры для создания графика. Пользователь может выбрать несколько систем, если он хочет. Системы создаются как элемент флажка. Источник элемента флажка основан на списке значений, который содержит запрос SQL для извлечения всех систем из моей таблицы базы данных. Вот структура моей таблицы базы данных:

CREATE TABLE system_table (
system_id                  NUMBER(16) NOT NULL,
system_name                VARCHAR2(100 CHAR) NOT NULL,
system_table_uebergeordnet_ID NUMBER(16),
CONSTRAINT system_name_unique UNIQUE(system_name),
CONSTRAINT system_table_pk PRIMARY KEY ( system_id ),
CONSTRAINT system_table_uber_id_fk FOREIGN KEY ( system_table_uebergeordnet_ID )
    REFERENCES system_table ( system_id )   );

Как видно из кода, последний атрибут является рекурсивным отношением. Теперь мне нужно следующее: если пользователь выбирает имя_системы и отправляет страницу, следует выбрать имя системы и все другие системы, которые ссылаются на выбранную систему. Поэтому я создал скрытый элемент с именем System_ID. Перед отправкой страницы я определил динамическое действие, которое подбирает идентификатор выбранного system_name. После отправки страницы моя диаграмма создается, и я проверяю условие в предложении where. Это выглядит так:

where ((instr(':' || upper(:P26_SYSTEMS) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or (instr(':' || upper(:P26_SYSTEMS_ALL) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or (SYSTEM_TABLE.SYSTEM_TABLE_UEBERGEORDNET_ID = :P26_SYSTEM_ID))

Запрос работает до сих пор, но выбирает только выбранное имя_системы, а не системы, которые ссылаются на выбранную систему. Я надеюсь, что смог объяснить проблему, и вы можете понять это. Кто-нибудь из вас знает, что я здесь не так делаю?

Следующий код показывает мой запрос:

select COUNT(TRIGGER_TABLE.DATUM_UHRZEIT) as Anzahl_Trigger,
       TEST.NUMMER as NUMMER
from BRIDGE_SYSTEM_TRIGGER, SYSTEM_TABLE, TRIGGER_TABLE, FAHRT, TEST, MITARBEITER
where BRIDGE_SYSTEM_TRIGGER.SYSTEM_TABLE_SYSTEM_ID = SYSTEM_TABLE.SYSTEM_ID
      and BRIDGE_SYSTEM_TRIGGER.TRIGGER_TABLE_TRIGGER_ID = TRIGGER_TABLE.TRIGGER_ID
      and TRIGGER_TABLE.FAHRT_FAHRT_ID = FAHRT.FAHRT_ID
      and MITARBEITER.NUMMER = FAHRT.MITARBEITER_NUMMER
      and FAHRT.TEST_ID= TEST_ID
      and TRIGGER_TABLE.PRIORITAET = 1
      and ((instr(':' || upper(:P26_TEST) || ':', upper(TEST.TEST_ID)) > 0) or (instr(':' || upper(:P26_TEST_ALL) || ':', upper(TEST.TEST_ID)) > 0))
      and ((instr(':' || upper(:P26_SYSTEMS) || ':',':' || upper(system_table.system_name) ||':') > 0)  or (instr(':' || upper(:P26_SYSTEMS_ALL) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or exists (select child.system_id from system_table child where  instr(':' || upper(:P26_SYSTEMS) ||':',':'|| upper(child.system_name) ||':') > 0 and child.system_table_uebergeordnet_id = system_table.system_id))
      and ((instr(':' || upper(:P26_COUNTRIES) || ':', upper(FAHRT.LAND)) > 0) or (instr(':' || upper(:P26_COUNTRIES_ALL) || ':', upper(FAHRT.LAND)) > 0))
      and ((instr(':' || upper(:P26_FAHRER) || ':', upper(MITARBEITER.QNUMMER)) > 0) or (instr(':' || upper(:P26_FAHRER_ALL) || ':', upper(MITARBEITER.QNUMMER)) > 0))
GROUP BY TEST.NUMMMER
ORDER BY TEST.NUMMER;

Запрос подсчитывает количество триггеров на приоритет, упорядоченных по номерам тестов. Триггеры, которые здесь подразумеваются, не имеют никакого отношения к триггерам sql! Поэтому, пожалуйста, не смущайтесь об этом термине. «Fahrt» принадлежит одному «Test», а «Test» может содержать несколько «Fahrten». Кроме того, каждый «Fahrt» содержит несколько триггеров. Последние четыре, где условия - это упомянутые условия для извлечения информации фильтра, которая была установлена, и учитываются только те триггеры, которые удовлетворяли условиям фильтра.

1 Ответ

0 голосов
/ 06 ноября 2018

Иерархическая структура данных может быть запрошена с использованием иерархического запроса. В Oracle вы можете использовать что-то вроде этого (примечание: не проверено):

select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
           ,':'||upper(system_table.system_name)||':') > 0
or system_table.system_id in (
  select parent.system_id
  from   system_table parent
  start with instr(':'||upper(:P26_SYSTEMS)||':'
                  ,':'||upper(parent.system_name)||':') > 0
  connect by prior parent.system_table_uebergeordnet_id = parent.system_id
)

Этот иерархический запрос начинается с выбранных системных имен и идет вверх по иерархии до их родителей, бабушек и дедушек и т. Д. Полученный набор системных идентификаторов затем используется для фильтрации основной таблицы.

Если вам нужно выбрать дочерних элементов выбранной системы, переключите предложение connect by, например

select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
           ,':'||upper(system_table.system_name)||':') > 0
or system_table.system_id in (
  select parent.system_id
  from   system_table parent
  start with instr(':'||upper(:P26_SYSTEMS)||':'
                  ,':'||upper(parent.system_name)||':') > 0
  connect by prior parent.system_id = parent.system_table_uebergeordnet_id
)

С третьей стороны, если это не многоуровневая иерархия, вы можете упростить запрос, например,

select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
           ,':'||upper(system_table.system_name)||':') > 0
or exists (
  select child.system_id
  from   system_table child
  where  instr(':'||upper(:P26_SYSTEMS)||':'
              ,':'||upper(parent.system_name)||':') > 0
  and    child.system_table_uebergeordnet_id = system_table.system_id
)
...