Oracle Apex - обновление представления с помощью триггера вместо - PullRequest
1 голос
/ 09 февраля 2012

Apex начинающий здесь. У меня есть представление в моей базе данных Oracle в виде:

create or replace view vw_awkward_view as
select unique tab1.some_column1,
  tab2.some_column1,
  tab2.some_column2,
  tab2.some_column3
from table_1 tab1,
 table_2 tab2
WHERE ....

Мне нужно предложение «unique» для «tab1.some_column1», потому что в его основной таблице много записей. Мне также нужно включить 'tab1.some_column1' в моем представлении, потому что остальные данные не имеют большого смысла без них.

В Apex я хочу создать отчет для этого представления с формой для его редактирования (только обновление). Мне не нужно редактировать tab1.some_column1. Только другие столбцы в представлении должны быть доступны для редактирования. Обычно я могу добиться этого, используя триггер «вместо», но это не представляется возможным, если представление содержит предложение «отличный», «уникальный» или «группировать по».

Если я пытаюсь обновить строку в этом представлении, я получаю следующую ошибку:

ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.

Как мне избежать этой ошибки? Я хочу, чтобы мой триггер «вместо» включился и выполнил обновление, и мне не нужно редактировать столбец с предложением «уникальный», поэтому я думаю, что это должно быть возможно сделать.

Ответы [ 3 ]

2 голосов
/ 13 февраля 2012

Надеюсь, я в правильном направлении вашего вопроса здесь;)

Ваш запрос может быть выполнен с помощью чего-то вроде:

select a.some_column1, tab2.some_column1, tab2.some_column2, tab2.some_column3 
  from table_2 tab2 
  join (select distinct some_column1 from table_1) a
    on tab2.column_in_tab1 = a.some_column1

Причина, по которой вы получаете ORA-02014ошибка из-за автоматически сгенерированного ApplyMRU процесса.Этот процесс попытается заблокировать измененную строку (строки):

begin
   for r in (select ... 
               from vw_awkward_view 
              where <your first defined PK column>= 'value for PK1' 
                for update nowait)
   loop
      null;
   end loop;
end;

Это облом и означает, что вы не сможете использовать сгенерированный процесс. Вам придется написать собственный процесс, который выполняет обновление .

Для этого вам придется использовать массивы F ## в apex_application .Если это звучит совершенно незнакомо, взгляните на: Пользовательский процесс отправки и при использовании массивов apex_application .

Кроме того, вот какдля апекса с 2004 года от самого Oracle.Он по-прежнему использует много ссылок htmldb, но суть его в этом.

(было бы неплохо использовать интерфейс apex_item для создания вашей формы и иметь контроль над тем, что генерируется икакой массив он принимает.)

То, что сводится к следующему: переберите массив, содержащий ваши элементы, и сделайте UPDATE ваше представление с представленными значениями.

Конечно, вынет блокировки таким образом, ни способ предотвратить ненужные обновления. Блокировку вы можете сделать самостоятельно , например, с помощью метода select for update.Вам придется заблокировать правильные строки в таблицах, которые вы хотите изменить, прежде чем обновлять их.Если блокировка не удалась, ваш процесс должен завершиться неудачей.

Что касается истории «потерянных обновлений» : здесь вам нужно проверить контрольные суммы MD5.Контрольная сумма генерируется из редактируемых столбцов в вашей форме и помещается в HTML-код.При отправке эта контрольная сумма затем сравнивается с вновь созданной контрольной суммой из тех же столбцов, но со значениями из базы данных на момент отправки.Если контрольные суммы различаются, это означает, что запись изменилась между загрузкой страницы и отправкой страницы.Ваш процесс должен потерпеть неудачу, потому что запись была изменена, и вы не хотите, чтобы они были перезаписаны.(если вы идете по apex_item пути, то не забудьте включить MD5_CHECKSUM (или MD5_HIDDEN).

Важное замечание: контрольные суммы, генерируемые с использованием apex_item или простостандартная функциональность формы создает строку для хэширования. Как вы можете видеть в apex_item.md5_hidden , контрольные суммы генерируются с помощью DBMS_OBFUSCATION_TOOLKIT.MD5. Вы можете получить контрольную сумму значений в БД двумя способами: wwv_flow_item.md5 или с использованием dbms_obfuscation. Однако в документации не упоминается следующее: Обсуждение OTN Apex по контрольным суммам MD5 . Каналы добавляются в сгенерированные контрольные суммы! Не забывайте об этом, иначевзорвать тебе в лицо, и ты будешь думать о том, что, черт возьми, с ним не так.

Пример:

select utl_raw.cast_to_raw(dbms_obfuscation_toolkit.md5(input_string=>
         "COLUMN1"    ||'|'||
         "COLUMN2"    ||'|'||
         "COLUMN5"    ||'|'||
         "COLUMN7"    ||'|'||
         "COLUMN10"   ||'|'||
         "COLUMN12"   ||'|'||
         "COLUMN14"   ||
         '|||||||||||||||||||||||||||||||||||||||||||'
      )) md5
from some_table

Чтобы получить контрольную сумму ряда some_table таблица, где столбцы 1, 2, 5, 7, 10, 12, 14 доступны для редактирования!

В конце концов, вот как это должно быть структурировано:

  1. цикл по массиву
  2. генерирует контрольную сумму длятекущее значение редактируемых столбцов из базы данных
  3. сравните эту контрольную сумму с отправленной контрольной суммой (apex_application.g_fcs, если сгенерировано), если контрольные суммы совпадают, продолжите обновление.Если это не так, сбой процесса здесь.
  4. заблокируйте правильные записи для обновления.Укажите nowait, и его блокировка не удастся. Сбой процесса
  5. Обновите представление с использованием отправленных значений.Ваш вместо триггера сработает.Убедитесь, что вы используете правильные значения для своего оператора обновления, так что будет обновляться только эта одна запись

Не совершать промежуточные.Это либо все, либо ничего.

Я почти чувствую, что ушел за борт, и может показаться, что все это немного, но, когда вы знаете подводные камни, на самом деле не так сложно вытащить этот обычай.процесс выключен!Мне было очень интересно играть с ним: p

2 голосов
/ 09 февраля 2012

Я думаю, что вы должны быть в состоянии удалить "уникальный".
если tab2.some_column1, tab2.some_column2, tab2.some_column3 не являются уникальными , то как вы хотите обновить их?
если они уникальны , то весь результат: tab1.some_column1, tab2.some_column1, tab2.some_column2, tab2.some_column3 уникален.

Когда вы указываете в SQL-запросе «уникальный» или «отдельный», он относится ко всем столбцам, а не только к «tab1.some_column1»

0 голосов
/ 06 марта 2012

Ответ Тома - правильный способ решения этой проблемы, но я думаю, что излишне для вас, если я правильно понимаю.

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

...