Создание таблиц Oracle с внешними ключами, которые ссылаются на первичные ключи в материализованных представлениях
У меня есть несколько материализованных представлений в Oracle, которые я могу запросить, чтобы получить информацию.
Теперь я хочу создать несколько таблиц с внешними ключами, ссылающимися на эти MV, и для этого я уже "добавил" соответствующие первичные ключи к MV (как указано в добавлении первичного ключа в представление sql).
Затем, когда я выполняю свой запрос создания таблицы SQL, я получаю ошибку Oracle (ORA-02270): нет соответствующего уникального или первичного ключа для этой ошибки списка столбцов в позиции 0, в самом начале...
Я делаю что-то неправильно? Возможно ли то, что я пытаюсь сделать? Если нет, то как это обычно делается?
1 ответ
При наличии материализованных представлений, на которые ссылаются внешние ключи других таблиц, вы должны принять к сведению метод обновления представлений и его влияние на внешние ключи. Две вещи могут помешать вам обновить ваши материализованные представления:
1) Данные в таблицах, ссылающиеся на ваши представления, могут ссылаться на строки, которые необходимо обновить или удалить. В этом случае вы должны исправить свои данные.
2) Метод обновления ваших просмотров завершен. При полном обновлении Oracle удаляет все данные в ваших таблицах mviews и заново заполняет их, перезапуская их запросы, как вы можете видеть в документации по сайту Oracle - Типы обновления, тогда как при быстром обновлении только различия применяются к вашим таблицам mviews. Быстрое обновление - это постепенное обновление, и оно не будет работать только в том случае, если ваши внешние ключи не учитываются вашими данными.
Теперь, если есть mviews, которые нельзя создать с помощью быстрого обновления (то, что Oracle называет их "сложные запросы"), вы можете изменить ограничения для этих mviews на отложенные, как вы можете видеть здесь.
Таким образом, даже полное обновление будет работать, потому что Oracle проверяет отложенные ограничения только к концу текущей транзакции. Поэтому, пока ваш метод обновления является атомарным, Oracle будет выдавать DELETE, а затем вставлять все строки назад, все в одной транзакции.
Другими словами, в следующей команде для обновления вашего mview оставьте параметр atomic_refresh равным true:
dbms_mview.refresh(LIST=>'MVIEW', METHOD =>'C', ATOMIC_REFRESH => TRUE);
Кстати, значением этого параметра по умолчанию является ИСТИНА, поэтому просто не упоминайте его, и он будет работать.
В документации говорится, что:
Просмотреть ограничения
Oracle не применяет ограничения представления. Однако операции с представлениями подчиняются ограничениям целостности, определенным в базовых базовых таблицах. Это означает, что вы можете применять ограничения для представлений через ограничения для базовых таблиц.
а также:
Ограничения вида являются подмножеством ограничений таблицы и подчиняются следующим ограничениям:
- ...
- Ограничения просмотра поддерживаются только в режиме DISABLE NOVALIDATE. Вы не можете указать любой другой режим. Вы должны указать ключевое слово DISABLE, когда объявляете ограничение представления. Вам не нужно явно указывать NOVALIDATE, так как это значение по умолчанию.
- ...
На практике вышеупомянутое означает, что, хотя ограничения на представления могут быть созданы, они заблокированы и не работают. Так как будто их не было вообще.
Помимо этого, подумайте на мгновение, какой смысл будет иметь ограничение внешнего ключа для таблиц, которое будет относиться к материализованному представлению:
- таблицы всегда "онлайн" и всегда имеют "свежие" данные
- материализованные представления могут содержать устаревшие данные
Представьте себе этот случай: вы вставляете запись X в какую-то таблицу. Эта запись еще не видна в материализованном представлении, потому что представление не обновляется в данный момент. Затем вы пытаетесь вставить запись X в другую таблицу с ограничением внешнего ключа, указывающим на это материализованное представление. Что должна делать база данных? Должна ли база данных отклонять оператор вставки (поскольку на данный момент X еще не виден в представлении и существует внешний ключ)? Если да, то как насчет целостности данных? Может, это должно блокировать и ждать, пока представление обновится? Должно ли это заставить представление начать обновляться или нет в таком случае?
Как видите, в таком случае много вопросов и трудностей в реализации, поэтому Oracle просто не допускает ограничений на представления.