Для меня это звучит так, как будто вам нужен снимок уровня трех транзакций, созданный всякий раз, когда вы вносите изменения в любую из этих таблиц.
Наличие триггера уровня строки в каждой из трех таблиц, который вызывает одну упакованную процедуру с идентификатором проекта и, необязательно, идентификатором клиента / задачи.
Упакованная процедура вставляет во все три таблицы истории соответствующий проект, клиента и задачи, для которых еще нет записи истории для этого ключа и транзакции (т. Е. Вам не нужны дубликаты). У вас есть пара вариантов, когда дело доходит до последнего. Вы можете использовать уникальное ограничение и либо BULK выделять и вставлять с FORALL / SAVE EXCEPTIONS, DML logging (EXCEPTIONS INTO) или INSERT ... SELECT ... WHERE NOT EXISTS ...
Вам необходимо отслеживать ваши транзакции. Я предполагаю, что это то, что вы делали с myPackage.GETPROJECTVERSION. Хитрость здесь в том, чтобы увеличивать версии только при наличии новой транзакции. Если, когда вы получаете новый номер версии, вы держите его в переменной уровня pacakge, вы можете легко определить, есть ли у вашей сессии номер версии или нет.
Если в вашем сеансе будет выполняться несколько транзакций, вам необходимо «очистить» номер версии уровня сеанса, если он был частью предыдущей транзакции. Если вы получите DBMS_TRANSACTION.LOCAL_TRANSACTION_ID и сохраните его также на уровне пакета / сеанса, вы сможете определить, участвуете ли вы в новой транзакции или в той же транзакции.