суббота, 21 ноября 2009 г.

Про дизайн команды SQL WHERE

Встретил на bash-е:
“DileSoft: У команды UPDATE есть одна серьезная дизайнерская ошибка. Если скомандовать UPDATE table SET field=value, изменятся все строки в таблице table. Чтобы изменились не все, следует добавить WHERE. Это провоцирует серьезные проблемы, когда, забыв о WHERE, можно порушить огромное количество данных.

urandom: У дверей есть серьезная дизайнерская ошибка. Если прищемить яйца дверью, то яйца отвалятся.”
Мне очевидно, что комада WHERE спроектирована плохо, потому что синтаксис команды не защищает пользователя от ошибки (дает zero fool proof). Понятно, что “исторически сложилось”, “уже не поменять” и т.п. Я сейчас о другом.

Представьте, что было бы, если бы в интернет магазине вы забыли бы положить товар к корзину и оформили бы заказ, а вам в результате прислали бы все товары из магазина (и соответствующий счет).

С одной стороны, мы можем написать в help-е сайта, о том, что отсутствие товаров в корзине подразумевает выбор всех товаров, но с точки зрения нормального человека это нонсенс. И сколько было человеко-часов потрачено на исправления ошибок с пустым where – могу себе представить.

Думаю, что гораздо разумнее было бы задизайнить WHERE clause следующим образом:

1) Пустое WHERE возвращает пустор набор элементов;
2) WHERE с фильром ограничивает возвращаемые данные этим фильтром;
3) Специальное сочетание “WHERE ALL” возвращает весь набор элементов без фильтра.

В этом случае семантика клаузы WHERE была бы максимально приближена к естесственным языкам (что кстати и было одной из целей дизайнеров SQL).

А теперь про “яйца отвалятся”

Оппонент DileSoft-а показывает нам пример обычного, обывательского подхода: “Некто говорит нам что вещь, привычная и принятая в нашем обществе – неправильна –> Стебать этого самого некто”. Классическая травля несогласных в мини-масштабе.

Налицо позиция “то, что принято, оптимум есть”. А это ведь не так (почти всегда). И изменяют мир к лучшему как раз такие, как DileSoft, которые способны заметить и понять, что это не так.

Типа послесловия
Буквально неделю назад мы словили очень похожий баг в нашем продукте – API было спроектировано так, что некая бизнес операция применялась для всех клиентов в случае, когда не был указан фильтр.

В результате, из-за редкой ошибки в коде формирования фильтра (закончилось место на диске) он не был сформирован и вся наша команда получила незабываемые выходные, проведенные под знаком “руками все исправить быстро срочно”.

А вы говорите, WHERE…

8 комментариев:

Гиркин Михаил Вячеславович комментирует...

Позволю себе не согласиться. Вполне нормальный дизайн, который на самом деле ничем не отличается от предлагаемого вами. В конце концов можно просто писать "...WHERE 1=2 OR ..." или подобное.
А тот глюк который вы словили - это уже никак не обходилось с помощью таких ограничений. В этих ситуациях поведение вообще непредсказуемо, и всяческие подобные ухищрения вряд ли дадут что нибудь.
Да и вообще, если где-то создается возможность апдейтнуть (делетнуть) всю таблицу в каком либо, даже редком, случае - это уже не в SQL дело то...

Yury Skaletskiy комментирует...

Здесь именно вопрос в том, как ведет себя команда по умолчанию.

WHERE 1=2 это же явный оксюморон, синтаксическая затычка. Это не естесственно для русского (языка). Вместо того, чтобы сказать "Не выбирай ничего" Вы предлагаете сказать "Выбери все записи, где 1 равен 2".

Именно о том, что затычки необходимы, я и говорю. В идеальном случае затычки бы не понадобились.

Я даэже могу понять, откуда "ноги растут". WHERE используется в SELECT, причем его можно не указывать. В SELECT семантика "нет ограничения WHERE == выбирать все" очень хорошо работает. А вот при обновлениии и удалении строчек -- плохо.

Если бы дизайнеры SQL пошли бы по пути, где пустой WHERE не выбирает ничего, им бы пришлось что то делать с селектом, потому что нельзя, чтобы в разных предложениях WHERE работал бы по разному.

Видимо, сделать неограниченный WHERE им показалось более интересной идеей, чем обязать в SELECT всегда писать WHERE ALL.

Хотя мне кажется, что дописывать к селекту WHERE ALL это не такая уж большая цена за более безопасную семантику языка.

Анонимный комментирует...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

Николай комментирует...

А при чем тут WHERE, собственно? Это UPDATE надо менять, чтобы без условия WHERE запрос не стартовал.

Анонимный комментирует...
Этот комментарий был удален администратором блога.
Yury Skaletskiy комментирует...

Вполне себе вариант - обязать клаузу WHERE для UPDATE, DELETE.

Это создаст некоторую "непохожесть" с командой SELECT, но опять же, по мне всяко лучше чем команда, которая по умолчанию удаляет/обновляет все записи в таблице

NAV!GAT0R комментирует...

интересно =)

a.knyazev комментирует...

Поржал