Pull to refresh

Comments 33

И это не последнее различие, с которым сталкиваются при переходе из одной СУБД в другую. Главное в этом случае — грамотно использовать возможности конкретной СУБД.
Капитан, рад что вы с нами! :)
Далеко не последнее! Но «дьявол кроется в деталях», порой имея в «хозяйстве» обе СУБД, очень трудно бывает переключаться.

Статья — отличная. Все очень прозрачно, понятно и по существу!

сложновато. в Firebird как то понятнее всё:

CREATE PROCEDURE GET_EMPLOYEES(
DEP_ID INTEGER = NULL;
)
RETURNS( --список возвращаемых полей
EMPLOYEE VARCHAR(50);
DEPARTMENT VARCHAR(50);
) AS
BEGIN
FOR SELECT E.empinfo, D.depinfo
FROM T_DEPARTMENTS D
JOIN T_EMPLOYESS E ON E.id_department = D.id
WHERE :DEP_ID IS NULL OR D.ID = :DEP_ID INTO :EMPLOYEE, :DEPARTMENT DO
SUSPEND; -- Это волшебное слово - аналог pipe row
END

SELECT * FROM GET_EMPLOYEES()

UFO just landed and posted this here
1) в принципе характерно для SQL всех разновидностей. Очевидно язык планировался для пользовательского уровня, но для рядовых юзеров он все равно сложен, а для специалистов получился слишком многословным
Я усматриваю в этом преимущества:
1) укрепляются мышцы пальцев;
2) программисту подконтрольны те механизмы, которые в том же MSSQL являются черным ящиком, например sequences.
кстати в MSSQL так и не запилили sequences? Очень нужны. И UPDATE… RETURNING и INSERT… RETURNING

Привык ко всем этим ништякам на Firebird
В 2008 не увидел. Не представляю, как без этого можно строить многопользовательские системы, использующие поля с автоинкрементом. Приходится использовать GUID.
там вроде есть какой-то костыль с возвратом id вставленной строки. Впрочем этот костыль почему-то во многих СУБД встречается и считается нормальным решением.

В Firebird вообще решительно отказались от автоинкрементных полей в пользу SEQUENCE. По-началу кажется дикостью, а потом понимаешь удобство
UFO just landed and posted this here
А если между insert и select @@SCOPE_IDENTITY проскочит транзакция с insert от другого пользователя?
я полагаю это в контексте транзакции должно работать. Иначе бессмысленно
это только в ХП доступно? или в обычном запросе можно?
UFO just landed and posted this here
я чессгря больше в сторону Postgre смотрю. Привычный и знакомый мне Firebird конечно хорош в малом-среднем сегменте, но на больших проектах уже не справляется
pipelined имеет смысл использовать когда весь результирующий набор вы сами формируете. А если необходимо вернуть результат select, то проще использовать курсор.
А ещё при работе с конвейерными (pipelined) функциями нужно иногда помнить про исключение NO_DATA_NEEDED :)
Возвратить таблицу можно еще так:
CREATE OR REPLACE
FUNCTION admin.virtual_date_table(p_num_rows in INTEGER, p_start_date IN DATE, p_end_date IN DATE)
RETURN virtual_date_table_type
IS
l_data virtual_date_table_type := virtual_date_table_type();
l_step NUMBER := 1;
BEGIN
l_step := (p_end_date - p_start_date) / p_num_rows;
FOR i IN 1 .. p_num_rows
LOOP
l_data.extend;
l_data(l_data.count) := p_start_date + i * l_step;
END LOOP;

RETURN l_data;
END;
/


select * from table(virtual_date_table(5, sysdate-5, sysdate))
pipelined экономнее по памяти имхо.
UFO just landed and posted this here
Нет. А что Вас смутило?
UFO just landed and posted this here
У нас речь идет именно о получении набора данных, а не о программном интерфейсе
UFO just landed and posted this here
Вы однозначно не уловили изюминки. Описанный шаблон позволяет вызывать функции выборок однотипно, меняя только название и параметры. Отсюда и логичная модель, когда методы работы с данными инкапсулируются в одном объекте. Или, по Вашему, в клиенте лучше наклепать кучу TADOQuery и TADOStoredProc'ов с жестко прописанными параметрами?
UFO just landed and posted this here
Всё верно, на то он и сервер, чтобы выдавать данные по запросу с параметрами. Выборка данных — задача сервера, и sql код должен быть на сервере. Мне кажется это идеологически правильным.
Кстати, а зачем было в самой функции разделение на два курсора делать?

Ведь можно написать условие в курсоре
where (dep.id = prm_depID or prm_depID is null)

ну, или, развлечения ради,
where nvl(to_char(dep.id), '') LIKE nvl(to_char(prm_depID), '%')
where dep.id = NVL(prm_depID, dep.id)

Без лайков и to_char
Sign up to leave a comment.

Articles