То, как вы сейчас работаете со сценарием 1, не очень хорошо. Вы не только делаете два запроса, когда одного будет достаточно, но, как указал Эрик, это открывает возможность изменения данных между двумя запросами (если только вы не используете транзакцию только для чтения или сериализуемую транзакцию).
Учитывая, что вы говорите, что в этом случае данные будут находиться точно в одной из трех таблиц, как насчет этого?
SELECT data
INTO v_data FROM
(SELECT data FROM table1
UNION ALL
SELECT data FROM table2
UNION ALL
SELECT data FROM table3
)
Еще один «трюк», который вы можете использовать, чтобы избежать написания нескольких обработчиков без данных, будет:
SELECT MIN(data) INTO v_data FROM table1;
IF v_data IS NOT NULL THEN
return v_data;
END IF;
SELECT MIN(data) INTO v_data FROM table2;
...etc...
но я не вижу никакой причины, которая лучше, чем наличие трех обработчиков исключений.
Для вашего второго сценария, я думаю, вы имеете в виду, что в обеих таблицах могут быть данные, и вы хотите использовать данные из таблицы1, если они есть, в противном случае используйте данные из таблицы 2. Опять же, вы можете сделать это за один раз. запрос:
SELECT data
INTO v_data FROM
(SELECT data FROM
(SELECT 1 sort_key, data FROM table1
UNION ALL
SELECT 2 sort_key, data FROM table2
)
ORDER BY sort_key ASC
)
WHERE ROWNUM = 1