Search
Write a publication
Pull to refresh

Comments 12

Лично меня обескуражило то, что автор делает insert в view
Прошу прощения, а для чего updatable VIEW нужны, не для этого ли?
Для этого. Но факт того, что меня это обескуражило, остаётся фактом :) Давненько я с mysql не работал :))
Вообще, наверное, это нужно было постить в Q&A
Поясните?)
Баг, я думаю, заслуживает места в постах, а не в Q&A)

P.S. Если интересно, в итоге пришлось отказаться от использования WITH CASCADED CHECK OPTION, т.к. с UPDATE'ом такой же случай нештатного поведения случился.
Поэтому теперь в итоге за целостность в базе отвечают только InnoDB-шные CONSTRAINT'ы.
Я думаю обновляемые предсьавления нужны не для одновременного обновления нескольких таблиц одним запросом. Они необхожимы, например, что бы разграничить права на обновление полей одной таблицы.
У вас второй вариант инсерта не отличается от третьего. Это так и задумано? А если инсертить во view, но поставить b_id в 0, то вставляется?

dev.mysql.com/doc/refman/5.5/en/view-updatability.html:
The WITH CHECK OPTION clause can be given for an updatable view to prevent inserts or updates to rows except those for which the WHERE clause in the select_statement is true.

И тут, похоже, проблема заключается в том, что в момент проверки значение b_id пустое.

Кстати, не боитесь наинсертить в таблицы A и B записей с пустыми полями name? В вашем примере смысла вставлять именно во view ну совсем никакого. Или у вас глупый ORM и он по-другому не умеет?
Вы хотели сказать, первый не отличается от третьего?
Да, так и было задумано, чтобы показать принципиальное различие в поведении драйвера в ситуации, когда мы вставляем первую запись и когда мы вставляем запись тем же запросом в уже «проинициализированную» таблицу, приведённую (казалось бы!) к начальному состоянию.

Явное прописывание 0 в `b_id` ничего не меняет в поведении драйвера.

INSERT с пустыми полями `name` делаю чисто для экономии места при демонстрации.
ORM CodeIgniter'а, которым я пользуюсь, делает разницу между "" и NULL.
Это он в Ваших терминах умный или глупый?
Или я не понял Вашего вопроса?
Увидел большую С в середине запроса, действительно. Рекомендую делать иллюстрации более иллюстративными :) а именно — называть похожие сущности более разными именами, чтобы не вводить читателей в заблуждение.

Про инсерты в view: вы с какой именно целью во view делаете инсерты? Из вашего примера не видно ни одного плюса. Вы хотите заполнять сразу 3 таблицы за 1 запрос? Но зачем, если там 3 разные сущности?
ToSHiC, ограничение, запрещающее одновременное изменение нескольких таблиц, описано в оф.документации по VIEW.

Изначально я перечислил три потенциальных плюса использования updatable VIEW:
1-2. Выделение набора строк, меньших чем одна таблица.
Например, можно дать пользователю права на updatable VIEW WITH CASCADED|LOCAL CHECK OPTION, содержащее часть её строк, выделенных некоторым WHERE-фильтром. В таком случае пользователь будет иметь права отображать и изменять только «свои» строки, а также, что гораздо вкуснее, не сможет вставить «не свою» строку. (Также это дополнительная логика верификации обновляемых/вставляемых данных.)
Правда, не могу навскидку назвать ни одного примера, как это использовать, да и от WITH CASCADED CHECK OPTION пришлось отказаться, поэтому первые два плюса в статье не видны.
0. Отсутствие необходимости таскать с собой кучу JOIN'ов в php-коде.
Вот это главный и единственный плюс, который я знаю, как использовать.

P.S. Кстати, любопытно. Как Вы считаете: где лучше хранить логику верификации и валидации данных: на стороне СУБД или на стороне веб-сервера?
Вообще говоря, в доке написано про one-to-one relationship between the rows in the view and the rows in the underlying table. В комментариях есть фраза «For a multiple-table updatable view, INSERT can work if it inserts into a single table.», но это тоже не запрет, а описание поведения.

Про пункты 1-2, я это понимаю. Но вы в начале статьи подобные требования не упоминали, так что я их не рассматривал.

Про ваш пункт 0 — так ваш ORM позволяет делать селекты из view, а инсертить при этом непосредственно в таблицу? Вы в этом случае не будете таскать с собой джоины, и при этом правильно инсертить будете.

В нормальном продукте логика верификации должна быть как в приложении (в рамках фильтрации поступивших от пользователя данных), так и в БД, если она в принципе это позволяет, и если производительность БД позволяет это делать. Фича практически любой взрослой SQL базы данных заключается в том, что она может поддерживать целостность данных в связанных таблицах, другое дело, что многие про это не хотят думать.
Спасибо за мысль. Действительно, можно делать селекты из представления, а вставлять в таблицу. Как-то не подумал.

Что же касается обеспечения и поддержания целостности данных средствами БД, то InnoDB в этом смысле очень мощный движок. Единственное, что меня смущает — то, что при попытке совершить запрос к БД, пытающийся нарушить целостность, вернётся 500-я ошибка. (1. Прав ли я в том, что это неизбежное поведение, и при попытке некорректного запроса возврат страницы со статусом 500 произойдёт обязательно?)

Здесь есть два аспекта: проблема с человекоудобностью и проблема безопасности.
Проблема с человекоудобностью: при попытке отправки некорректных данных из формы вместо описания ошибки будет возвращаться тупо «HTTP 500» — может быть решена и во фронтенде (проверка регэкспами при автоматической отправке; если человек отправляет руками через консоль или адресную строку, то он, наверное, не нуждается в описании ошибки.)
Security issue: информация о том, на какие запросы к БД сервер «ругается», может дать злоумышленнику некоторое знание об архитектуре БД — может быть решена только в бэкенде.

Таким образом, хоть использование средств БД для поддержания целостности и необходимо в качестве страховки, но от полной валидации и верификации данных в бэкенде никуда не деться. Security in depths и всё такое. 2. Так?
1. Какую ошибку вернуть — это целиком и полностью на вашей совести. Можно и что нибудь из 4хх кодов подобрать ( en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error ), и в теле присовокуплять, почему именно ошибка. Отправлять наружу тексты SQL ошибок, конечно же, не стоит.

2. Да. Клиент всегда может прислать любую ересь. Более того, клиент может прислать правильный запрос, который стал не валиден из-за действий других клиентов или программ. Например, пытается забронировать билет, а они все только что кончились. С точки зрения клиента и фронта — полностью валидная операция, с точки зрения БД и бэкэнда — уже не валидная.
Sign up to leave a comment.

Articles