Можно ли выполнять update и insert на view и при каких условиях?
Что проверяют
Знаете ли вы, что представление это сохранённый запрос, а не таблица, и понимаете ли, когда СУБД может однозначно перевести изменение в изменение базовой таблицы. Уточняющий вопрос обычно про сложное представление: как всё-таки сделать в него запись.
Как отвечать
Ответ короткий: да, если представление автоматически обновляемое. Если нет, для него пишут триггер INSTEAD OF.
Условия автообновляемости в PostgreSQL конкретные, их полезно назвать:
- в
FROMровно одна таблица или одно тоже обновляемое представление; - нет
DISTINCT,GROUP BY,HAVING,LIMIT,OFFSET,UNION,INTERSECT,EXCEPT, оконных и агрегатных функций; - в списке выборки только ссылки на колонки: вычисляемое выражение делает эту колонку недоступной для записи, остальные писать можно;
- нет общих табличных выражений (
WITH).
Дальше практика:
INSERTчерез представление: колонки базовой таблицы, которых в представлении нет, должны допускатьNULLили иметь значение по умолчанию, иначе вставка упадёт;WITH CHECK OPTION: без него можно вставить или обновить строку так, что она перестанет попадать под условие представления и пропадёт из него.LOCALпроверяет только текущее представление,CASCADEDещё и нижележащие;- сложные случаи: триггер
INSTEAD OF, где вы сами описываете, что делать с каждой таблицей. В Oracle к этому добавляется правило key preserved table. В MySQL представление обновляемо при алгоритмеMERGE, аTEMPTABLEзапись не принимает; - материализованное представление такими командами не меняется, оно пересчитывается через
REFRESH MATERIALIZED VIEW.
Для QA закончите практикой: подготовка тестовых данных, проверка прав на представление отдельно от таблицы, ловушка с исчезающими после обновления строками.
Где спотыкаются
Отвечают «во view писать нельзя». Для простых представлений это неверно почти во всех промышленных СУБД.
Забывают WITH CHECK OPTION, а потом ищут «пропавшую» строку, которая просто вышла за условие представления.
Путают обычное представление с материализованным. Обычное данных не хранит и выполняется при каждом обращении, поэтому запись в него и транслируется в базовую таблицу.