2010-09-22 5 views
4

Как я могу получить эквивалент триггера «on commit» после вставки некоторых строк в таблицу?Oracle: имитация триггера «после фиксации»

После ввода нескольких строк в таблицу, я хотел бы отправить сообщение внешнему процессу, что есть строки, готовые к обработке. Использование триггера уровня инструкции вызывает одно сообщение для каждой вставки, и я хотел бы отправить только одно сообщение, в котором говорится: «Есть строки, которые нужно обработать».

+1

Почему вы не используете очереди? Смотрите: http://download.oracle.com/docs/cd/B10500_01/appdev.920/a96587/qintro.htm –

+0

обнаружено 3 проблемы для нас с очередями: (1) требуемые приложения для ссылки в времени выполнения oracle, (2) время ожидания больше, чем нам понравилось, и (3) не масштабирование для вычисления размера фермы. –

+0

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

ответ

3

Как вам необходимо вызвать внешний процесс , взглянуть на DBMS_ALERT вместо DBMS_JOB.

Внешний процесс активно прослушивает предупреждение, вызывая хранимую процедуру. Хранимая процедура вернется сразу же после того, как сигнал будет сигнализирован и передан.

Обратите внимание, что DBMS_ALERT является устройством сериализации. Таким образом, несколько сеансов, сигнализирующих одно и то же имя предупреждения, будут блокироваться так же, как они обновляют одну и ту же строку в таблице.

+2

Это правильный ответ, поскольку он позволяет коалесцировать несколько вставок. Из документа Oracle Doc: «Оповещения могут сигнализироваться чаще, чем вызовы ожидания соответствующего приложения. В таких случаях старые предупреждения отбрасываются. Приложение всегда получает последнее предупреждение (на основе времени фиксации транзакции)». –

7

Создайте работу. Фактически это не будет передаваться до тех пор, пока не произойдет фиксация. (Примечание: DBMS_SCHEDULER, как правило, лучше, чем DBMS_JOB, но в этом случае вы должны использовать старый пакет dbms_job.)

declare 
    jobnumber number; 
begin 
    dbms_job.submit(job => jobnumber, what => 'insert into test values(''there are rows to process'');'); 
    --do some work here... 
    commit; 
end; 
/
+0

+1: простой, эффективный. –

+0

Есть ли способ, которым я могу использовать это для слияния вставок? Я хотел бы обработать несколько вставок, а затем сделать один шаг «он готов». –

+0

Как выполняется работа? В одной транзакции, которую вы контролируете (через хранимую процедуру или что-то еще), или просто простое заявление о вставке пользователей? Будет ли срабатывание триггера на уровне таблицы? –

1

Вы можете установить флаг, чтобы сказать «Я послал сообщение». Чтобы убедиться, что вы «перезагрузки» флаг на фиксации, используйте dbms_transaction.local_transaction_id, то вы можете просто сделать

IF v_flag IS NULL OR dbms_transaction.local_transaction_id != v_flag THEN 
    v_flag := dbms_transaction.local_transaction_id; 
    generate message 
END IF;