metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-02-01 07:11 pm

Запросы к БД, опечатки и строгая типизация

Неоднократно читал истории, типа этой, когда из-за мелкой опечатки убивалась целая таблица данных.

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

Кстати, в этом плане полезен Firebird - там разработчики стараются жостко следовать стандартам, вплоть до того, что ломают обратную совместимость при переходе между версиями, если этого требует кошеризация.
Я вот жалею, что у меня почти нет опыта работы с Postgresql и Oracle - было бы очень интересно сравнить подходы на этот счет в разных серверах, а не только Firebird с MSSQL.

[identity profile] guamoka.livejournal.com 2010-02-01 07:37 pm (UTC)(link)
Недавно довелось подменять под Hibernate Oracle на hsqldb, ибо индусы хотели, чтобы было энтерпрайзно, но оно там нафиг не упало. Обнаружилась любопытная (общеизвестная) вещь, что Oracle хранить пустые строки как null (а на проверку на нулл была завязана ветвистая логика) :) Вот тебе и типизация.

[identity profile] metaclass.livejournal.com 2010-02-01 07:44 pm (UTC)(link)
Вот таких вот тонких заморочек в разных серверах просто горы, что и удивляет. Скорее всего, когда-то давно забили на нормальное проектирование, а потом просто решили не ломать совместимость.

[identity profile] volodymir-k.livejournal.com 2010-02-02 12:23 am (UTC)(link)
Никаких заморочек нет. Оракл принял свое решение в 1985, а потребовалось стандартизировать в 1992 году, и очевидно, что им важнее существующие покупатели, чем стандарт. У Микрософта и во многих других есть режим ANSI strict и т.д. Вроде у Оракла тоже должно быть.

Условие, кстати, MySQL специфичное, это чистая бага, потому что MySQL вообще-то опен сурс поделие и никому ничего не обещало. Исправить раз плюнуть, это можете сделать даже Вы.

[identity profile] http://users.livejournal.com/_windwalker_/ 2010-02-01 08:09 pm (UTC)(link)
на первый взгляд выглядит как bullshit, ибо id в where не определено, и там должен быть search condition, который вычисляется как true, false or unknown.

Которое, в свою очередь вычисляется через предикат:
<predicate> ::=
<comparison predicate>
| <between predicate>
| <in predicate>
| <like predicate>
| <null predicate>
| <quantified comparison predicate>
| <exists predicate>
| <unique predicate>
| <match predicate>
| <overlaps predicate>

Где я никак в упор не вижу id - 1. Т.е. это либо криворукость самописного парсера SQL, либо навороченность админки 1ц, либо навороченность диалекта SQL от MYSQL.


[identity profile] inhate.livejournal.com 2010-02-02 06:01 am (UTC)(link)
А где там написано хоть слово про MySQL ?

[identity profile] http://users.livejournal.com/_windwalker_/ 2010-02-02 10:29 am (UTC)(link)
ну вот именно в мускуле я сталкивался с вопиющими странностями парсера SQL

[identity profile] vromanov.livejournal.com 2010-02-01 08:35 pm (UTC)(link)
Для таких кейзов должно заводится ограничение, что пользователь X не может в одном запросе модифицировать (удалять, вставлять, итд) больше чем Y строк. И то гда таких глубых ошибок будет меньше

[identity profile] metaclass.livejournal.com 2010-02-01 09:02 pm (UTC)(link)
Ух ты ёпт, какая классная идея, если такое запилить на уровень описания таблицы, как констрейнт с автоматическим rollback - это ж спасение.
Если действительно нужно обновить всех, проблемы отключить констрейнт при наличии прав обычно нету.

[identity profile] gds.livejournal.com 2010-02-01 08:47 pm (UTC)(link)
конкретно в оракле -- "id - 1234" не является валидным условием, но не помню сходу, чтобы так ошибался.
и в случаях, когда пишу на pl/sql и нет гарантий того, что update/delete исполнится без промашек в where, вручную проверяю количество задетых строк, типа "assert(sql%rowcount <= 1)". Сложностей мало, но неинформативный ассерт лучше, чем ошибка в логике.
А про то, что в оракле NULL эквивалентен пустой строке -- о да. Уже долго шлю лучи рака яичек тому, кто принял это решение.

[identity profile] ennor.livejournal.com 2010-02-01 08:57 pm (UTC)(link)
Ну че, update без where - классика. Думаю, каждый, кто правил базы ручками, проходил через это :)

А вообще да, выглядит сомнительно. MSSQL такое не пропустит, насколько я помню; более того, там вообще СУБД не указана...

[identity profile] metaclass.livejournal.com 2010-02-01 09:07 pm (UTC)(link)
Я вот еще не знаю, как разные сервера относятся к тому, что where с условием на поле с датой напутать с типом данных или форматом даты.

[identity profile] ennor.livejournal.com 2010-02-01 11:50 pm (UTC)(link)
Ой, ну это вообще притча во языцех. Классический способ здорово подгадить жизнь не очень квалифицированной команде после твоего ухода:
set language english;
select min(ShipDate), max(ShipDate), count(*)
from AdventureWorks.Sales.SalesOrderHeader
where shipdate between '2004-07-05' and '2004-08-05';

----------------------- ----------------------- -----------
2004-07-05 00:00:00.000 2004-08-05 00:00:00.000 1121

set language russian;
select min(ShipDate), max(ShipDate), count(*)
from sales.SalesOrderHeader
where shipdate between '2004-07-05' and '2004-08-05';

----------------------- ----------------------- -----------
2004-05-07 00:00:00.000 2004-05-08 00:00:00.000 350
Мало кто полностью инициализирует все свойства соединения с БД сразу после его создания, обычно остается куча дефолтов из свойств логина или базы. Дефолтовый язык директорского логина поменять - и привет :)

Но вообще, конечно - параметризация спасет мир. Осталось только заставить этот мир ею пользоваться, пока он нахрен не вымер.

[identity profile] metaclass.livejournal.com 2010-02-02 07:35 am (UTC)(link)
Параметры да, это правильное решение.
Кстати, MSSQL умеет при парсинге запроса возвращать список и типы параметров?
А то я с ним иначе как через ADO.NET не работал, а там такое вообще не предусмотрено - список параметров заполнять исключительно ручками.

[identity profile] ennor.livejournal.com 2010-02-02 08:40 am (UTC)(link)
Да, конечно. Даже из старого древнего ADO, когда используешь OLEDB-провайдер, он все сам находит и автоматом заполняет коллекцию параметров.
Правда, когда потом смотришь в профайлер, что же там реально бегает, то становится слегка нехорошо...

[identity profile] aamonster.livejournal.com 2010-02-02 07:19 am (UTC)(link)
Хороший подход в плане обратной совместимости - кошерная реализация новой версии + адаптер для старой. Но на это никогда нет времени :-(

[identity profile] demon-gloom.livejournal.com 2010-02-02 10:27 am (UTC)(link)
Cинтаксис, даже самый кошерный все не спасет. Нужно просто что бы программа перед выполнением запроса запроса проводила анализ кол-ва строк затрагиваемых изменением, и на основе обьема изменений требовала вводить капчу из того же квери. Самое главное при этом - подсветка слов в запросе разным цветом. И что бы символы -+,= отличались друг от друга цветом.

Типа если у меня в базе миллион строк, а квери затрагивает одну, то пускать без капчи. А если 500 тыщ, то раза два должно спросить.

[identity profile] volodymir-k.livejournal.com 2010-02-04 11:51 am (UTC)(link)
В мускуле есть режим "безопасной работы", когда делит без условия и что-то ещё отрубается. Только его включить надо, а мы ж все крутые и верим в себя.