Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Скудность языка СУБД
в независимости от вставокИ
фулскан
DATEDIFF
возращает разницу между timestamp'ами в любых единицах. Сгородили какую-то хрень в базе, а оказывается MSSQL виноват. Ну нет там Timespan'ов, это не повод изобретать какой-то странный способ их хранения. Сохраняйте два таймстампа — время начала и время окончания, или длительность в секундах. Какие проблемы-то?в interbase/firebird минимум 15 лет уже естьКоллега, 10 лет работал с firebird, и сравнивал с другими диалектами PSQL. Да, он хорош, действительно. Но. Сам по себе firebird все-таки сдает позиции когда большая и сложная БД с большим количеством данных и транзакций. Если точнее — требования к виртуозности разработчика растут экспоненциально с линейным ростом сложности БД.
При использовании динамического SQL со стороны клиентской программы, клиентская программа передаёт СУБД SQL команды в виде строк, предварительно формируемых в коде.
При использовании ХФ SQL код на стороне приложения обычно статический, и выглядит, как простой вызов ХФ, параметры которой передаются не строками, а через placeholders (:variable) через механизм binding.
Изменив текст ХП в файле нужно не забыть изменить его в БД.
различать ситуации когда процедура создаётся, когда обновляется
CREATE OR REPLACE
.когда удаляется
Причём желательно не обновлять процедуры, которые с момента прошлой синхронизации не изменились
А откат в общем случае невозможен — для него общих инструментов не написать.
Как выяснилось это не такая уж проблема — просто храним все удаления в одном файле и прогоняем при каждом запуске инсталлятора.
В pl/sql различать это не требуется — CREATE OR REPLACE.
if OBJECT_ID('myProcedure') is not null
drop procedure [dbo].[myProcedure]
GO
CREATE PROCEDURE [dbo].[myProcedure]
(
...
При использовании ХФ SQL код на стороне приложения обычно статический, и выглядит, как простой вызов ХФ, параметры которой передаются не строками, а через placeholders (:variable) через механизм binding. Конечно это не исключает возможность SQL injection полностью (ведь можно умудриться в ХФ конкатенировать строку, переданную параметром с текстом динамически выполняемого SQL запроса), но значительно уменьшает её вероятность.
create procedure p(inject_me in varchar2)
is
begin
execute immediate inject_me;
end;
SET @updatequery :=CONCAT('UPDATE table.users u set u.STORED=(SELECT COUNT(*) FROM db.local_map_base_',@user_name,' lmb) WHERE u.GUID_USER=?; ');
PREPARE nmut FROM @updatequery;
EXECUTE nmut USING @user_guid;
При использовании динамического SQL со стороны клиентской программы, клиентская программа передаёт СУБД SQL команды в виде строк, предварительно формируемых в коде
У меня вот, например, на реальном проекте в ORM-ке во многих таблицах есть createdby/whem/modifiedby/when, это строчек в 10-20 кода сделано и совершенно прозрачно для прикладного кода — т.е. нельзя забыть заполнить, нельзя заполнить неправильно. В БД можно такое сделать триггерами, но пришлось бы вешать по триггеру на каждую таблицу.
Потом у меня есть слой для прав доступа. Прикладной код может делать любые запросы к БД, но проходя через этот слой на них навешиваются where с фильтрацией, и прикладной код не может достать то, чего не положено текущему юзеру видеть. Это тоже сделано более-менее универсально, и навешивается централизованно. В БД такое тоже можно сделать вьюшками, но опять же надо будет по вьюшке на таблицу.
Также можно делать денормализацию, кэширование, аудит, раскладывание данных по разным базам, всякие push-нотификации. И все это — без вмешательства в прикладной код.Все вышеперечисленное входит в большинство современных промышленных СУБД (в Оракл уж точно).
представьте, например, что ваша база данных служит источником данных больше, чем для одного приложения.
обезопасите себя от разных трактовок одной и той же логики разными программистами
Хранимые функцииКак-то традиционно устоялось «хранимые процедуры»/«stored procedures»
Хранимые функции. За и против