Эмулиция функции с side-effect

pizmon
Дата: 22.02.2010 02:14:48
Партия велела портировать простенький кусочек из Firebird на Oracle и MSSQL. MSSQL вижу второй раз в жизни.

Выделяя суть, задача выглядит так: есть таблица t c первичным ключем id. Есть функция f, которая очень долго считает свой результат. По этому результату надо регулярно отбирать/сортировать. Самое плохое, что результат функции зависит от текущей даты. С клиента приходит хитросформированный клиентом по своей механике запрос к вьюхе v, c наложеными сверху условиями на поля из группы "всякое-разное" (что предотвращает пересчет всей таблицы, она большая).

соответвенно, в FB выглядело так (это схема, идея):
create table t(
 id not null integer primary key,
 calcdate date,te 
 calcresult double precision,
 /* всякое-разное */
);

create procedure f(id bigint)
returns (result double precision)
as
begin
  select calcdate, calcresult
    into :calcdate, :result
    from t where id = :id;

  if (calcdate != cast('now' as date)) then
  begin
    
    /* тут черт ногу сломит */
    
    update t set calcresult = :result, calcdate = cast('now' as date) where id = :id;
  end;  
  suspend;
end;

create view v(id, result, /* всякое-разное */)
as
select
  t.id,
  (select result from f(t.id)),
  /* всякое-разное */
from t;

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

На всякий случай: планируется требовать MSSQL не ниже 2005, но если есть решение только для 2008 - буду всё равно очень благода.
aleks2
Дата: 22.02.2010 06:23:04
pizmon,

В MS SQL вам ничего не светит. Учитесь писать ЯВНО запросы.

И, укуси меня пчела, я не понимаю, почему ваш расчет невозможно вынести в ДРУГУЮ функцию и вернуть усе, шо надо...

PS. Есть, канешно, OPENROWSET... но не надо.
Glory
Дата: 22.02.2010 10:42:30
А не проще поставить в расписание задание, которое раз в сутки будет один раз пересчитывать нужный функционал ?
Crimean
Дата: 22.02.2010 10:46:24
Glory
А не проще поставить в расписание задание, которое раз в сутки будет один раз пересчитывать нужный функционал ?


+1

для клиента, подозреваю, при большом объеме данных, большой разницы не будет
pizmon
Дата: 22.02.2010 11:37:04
Ну, нет - так нет. Спасибо, камрады.
Извините за беспокойство.
Тему можно закрывать.
pizmon
Дата: 05.07.2017 16:14:43
Я, конечно, дико извиняюсь, но не произошло ли за эти годы каких-то кардинальных перемен к лучшему? Я слышал, что даже try/catch появился. А с этим - всё никак?
Romka-Fes
Дата: 05.07.2017 22:58:39
pizmon,

А клиент на чём написан? Есть возможность его поправить?
Сделайте всё не в виде функции, в в виде хранимой процедуры, которая вернёт набор данных.
А вот в ней можете творить всё (почти), что позволяет T-SQL.
не?