powered by simpleCommunicator - 2.0.47     © 2025 Programmizd 02
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
9 сообщений из 9, страница 1 из 1
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32112744
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет. Не подскажите - есть ли такая возможность в АСА ?

Для тех кто не знает, что такое inline-udf поясню:
Это пользовательские функции, написанная на TSQL, которые возвращают набор данных. Фактически это параметризированный вьювер получается. Вид такой функции:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
create function fn_Table1
(@id int)
returns table
as
  return
    select *
    from Table1
    where id = @id


А применяется удобно:
Код: plaintext
1.
2.
3.
select *
from Table2 t2
  inner join dbo.fn_Table1( 1 ) t1 on t1.id = t2.id


Причем MSSQL и делать то ничего не приходится - он просто текст запроса функции вытаскивает, вместо параметров значения подставляет и в запрос, где используется просто его подзапросом впихивает. Потом соотвествующе спокойно на него план может построить. Вроде ничего сложного нет, а удобно.

Есть ли аналог такого в ASA и если нет, то как обойти отсуствие этой возможности. С MSSQL 2000 будет перегоняться в АСА крупный проект, там вся БД на этих UDF завязана.

Сенкс за внимание :)
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32113079
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну во-первых согласно MS inline UDF вовсе не обязана возвращать набор данных и более того, такое поведение скорее исключение, чем правило, во всяком случае микрософт его почти не упоминает
(см. напр. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsqlpro01/html/sql01l1.asp),
так что звиняйте дядьку, формулируйте проблему почетче в следующий раз.

А во-вторых ты же сам себе и ответил:

>Причем MSSQL и делать то ничего не приходится - он просто текст запроса функции вытаскивает, вместо параметров значения подставляет и в запрос, где используется просто его подзапросом впихивает.

Ну так и положи текст запроса в виде подзапроса в явном виде. А если этот подзапрос вдруг зависит от параметра, который вычисляются сложным образом и чистым SQL-ем не обойтись, то напиши функцию, которая производит это вычисение и возвращает искомый параметр и вызови ее в этом подзапросе. Причем даже выдумывать ничего не надо, ибо это сложное вычисление уже наверняка есть в MSSQL-ном варианте функции.

На всякий случай: caйбейзовские сохраненки могут возвращать множество, но их нельзя вызывать в запросе.

А интерестно, кстати, что вставит MSSQL в качестве подзапроса, если подзапрос вычисляется функцией (например так: IF @id=1 then return запрос_1 else return запрос_2 endif) и плюс зависит от параметров, которые тоже заранее неизвестны.
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32113199
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таааак - видно, что народ MSSQL 2000 не юзал. Если сравнить такие функции с view, то согласитесь что не всегда с помощью view можно впихнуть select, особенно когда он четко ориентирован на определенные параметры. Я не имею ввиду примитив типа "select * from Table where Field = @Value", речь идет о запросах с подзапросами, частенько содержащими агрегатные операции, в которых не возможно вернуть все множество вариантов, т.е. идет обработка по четко заданным параметрам. В качестве примера могу подкинуть такое:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
select i.CalcAlgorithmImplement_id, o.TypeCalcObject_id, a.CalcObject_id, i.CalcAlgorithm_id, c.CalcDate
  from CalcAlgorithmImplement i
    inner join CalcAlgorithm a on i.CalcAlgorithm_id = a.CalcAlgorithm_id
    inner join CalcObject o on a.CalcObject_id = o.CalcObject_id
    inner join
     (select ci.CalcAlgorithm_id, ci.CalcDate, Max(ci.SaveDate) as MaxSaveDate
      from CalcAlgorithmImplement ci
        inner join
         (select CalcAlgorithm_id, Max(CalcDate) as MaxCalcDate
          from CalcAlgorithmImplement
          where CalcDate <= @CalcAlgorithm_CalcDate and
                SaveDate <= @CalcAlgorithm_SaveDate
          group by CalcAlgorithm_id) as s on ci.CalcAlgorithm_id = s.CalcAlgorithm_id and
                                             ci.CalcDate = s.MaxCalcDate
      where ci.SaveDate <= @CalcAlgorithm_SaveDate
      group by ci.CalcAlgorithm_id, ci.CalcDate) as c on i.CalcAlgorithm_id = c.CalcAlgorithm_id and
                                                         i.CalcDate = c.CalcDate and
                                                         i.SaveDate = c.MaxSaveDate


Как видно из этого запроса, с таблицы, в которой хранится история данных с помощью двух дат - CalcDate (расчетный месяц) и SaveDate (месяц актуальности информации, т.е. ввода в действие), view на такой запрос не напишешь. С другой стороны каждый раз совать его в запросы ХП, тригера и клиента печально - получение текущей информации на указанный период времени с помощью этого запроса используется очень во многих местах проекта и согласитесь если что, легче его поменять в одном месте.

По поводу вопроса насчет условий - все просто. У MSSQL 2000 есть 2 типа функций, возвращающих набор данных. Inline смахивает на параметризированный вьювер и кроме наличия параметров ничем от него больше не отличается. Еще есть table-функции. Т.е. в такой функции указывается, что будет возвращена таблица, ей указывается внутреннее для функции имя и описывается ее структура. В тексте функции вы можете писать любой код и вгонять любые данные через insert в эту таблицу. Далее она используется в FROM запросов наравне с таблицами и вьюверами.

На этом можно наверное тему прикрывать и завязывать с просветительской работой. Я нашел аналог inline-udf функций, немного правда не оттуда, откуда ожидал, но вариант рабочий - благодаря тому, что Sybase поддерживает область видимости переменных, то в принципе никто не запрещает в вьюверах использовать переменные, типа того:
Код: plaintext
1.
2.
3.
4.
5.
create view TestParameterView
as
  select *
  from Table1
  where Field1 = @Value


Прекрасно компилится, потом можно использовать так:

Код: plaintext
1.
2.
3.
4.
5.
declare @Value int
set @Value =  1 

select *
from v_TestParameterView


Получается почти что тоже самое, что мне и требовалось. В кач-ве недостатков такого метода по сравнению с inline udf функций можно отнести написание лишнего кода по обьявлению переменных, которые будут потом использоваться во вьювере, отсуствие контроля отсутствия переменных при компиляции и необходимостью делать для каждого вьювера уникальные имена используемых им переменных, чтобы не было случайных пересечений.

Всем большое сенкс за внимание к этой теме :)
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32113227
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
О, мосье понимает толк в извращениях! К тому же мосье не читает ответы на свои же вопросы, я уж не говорю чтении чего-нибудь более фундаментального, Дейта, например. На всякий случай: вью на такой запрос пишется довольно просто (это я по поводу: "Как видно из этого запроса, ...view на такой запрос не напишешь.").
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32113584
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не понимаю я - вроде как описываю проблему, и Вы вроде как даете ответ, только вот не в тему. Или может подробнее напишите, что в Вашем ответе может помочь для решения моей проблемы ? Чтение книжек - это круто, но проблемы не снимает. Возврат набора данных их ХП это тоже круто, но как Вы сами изволили заметить, в отличие от Interbase ни Sybase, ни MSSQL ХП в запросах в разделе FROM не может использовать ХП. Я пишу, что вся БД, переводимая с MSSQ 2000 утыкана в ХП и клиенте обращениям к таким UDF, Вы же мне предлагаете перелопатить все ХП (а их не 10 штук) и везде вставить текст запроса функции в виде подзапроса. Я пишу, что сам запрос функции основан на скалярных параметрах и смысла без них не имеет, поэтому это нельзя перегнать во вьювер, Вы мне рассказываете как легко создать скалярную UDF функцию для вычисления параметра (интересно что можно расчитать в параметр CalcDate, содержащую просто требуемый расчетный месяц). И наконец - сударь, если Вы уж такой проф, то почему бы Вам просто не привести текст такого вьювера, который обходя условие ограничения по параметрам мог бы легко возвращать то, что мне нужно ? Буду только благодарен, если Вы соизволите хотя бы примерно намекнуть, как будет выглядеть скрипт запроса вьювера. А то пока что то только все слова ... :)
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32113982
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я погорячился, приношу извинения, твое решение очень даже ничего, только уж очень не по-реляционному. К тому же оно есть классический пример плясок с бубном. Но если принять во внимание, что нужно минимизировать работу по миграции, а не абстрактную правильность или там еще что, то оно наверное оптимально. Буду использовать при случае.

Насчет сохраненок имелось в виду, что сохраненка, возвращающая рекордсет и есть параметризованый вью, в принципе решающий проблему. Недостаток - должна быть последней в цепочке (т.к. нельзя вызывать из SQL запроса), достоинство - более читаемая программа, больше возможностей по вычислению (например можно вернуть разные рекордсеты). А то получается гремучая смесь процедурно-декларативного (или какого там) стиля с кучей ограничений к тому-же.

А вот насчет чтения книжек, эт ты зря, оно как раз снимает многие проблемы. Например возникающие из-за вольного использования терминологии.
Во-первых уже говорилось, что MSSQL inline UDF не обязана возвращать рекорд сет. Функция, возвращающая скалярный тип тоже, согласно MS терминологии, называется inline UDF. Следовательно на вопрос "Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000" нужно отвечать "да". Это явилось источником первоначального непонимания.
Во-вторых то, что ты называешь запросы с подзапросами, таковыми также не являются. Тут ИМХО, особо не претендую, но разница думаю видна из примера. Твой пример в принципе просто сокращенная (часто более удобная) запись последовательности операторов: create view x as ....; select .... from x, ...;, но "x" не есть подзапрос. А с подзапросами твой пример будет выглядеть примерно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
create view x as (
  select i.CalcAlgorithmImplement_id, o.TypeCalcObject_id, a.CalcObject_id, i.CalcAlgorithm_id,
         (select ci.CalcDate
            from CalcAlgorithmImplement ci
            where c.CalcAlgorithm_id = i.CalcAlgorithm_id
              and c.CalcDate = i.CalcDate
              and i.SaveDate = (select max(ci.SaveDate)
                                 from CalcAlgorithmImplement ci
                                 where ci.SaveDate <= i.SaveDate
                                   and ci.CalcDate = (select max(Max(CalcDate))
                                                         from from CalcAlgorithmImplement s
                                                         where ci.CalcAlgorithm_id = s.CalcAlgorithm_id
                                                           and CalcDate <= i.CalcDate
                                                           and SaveDate <= ci.SaveDate    
                                                     )
                               )
         ) as CalcDate,
         i.CalcDate as CalcAlgorithm_CalcDate, i.SaveDate as CalcAlgorithm_SaveDate
    from CalcAlgorithmImplement i
      inner join CalcAlgorithm a on i.CalcAlgorithm_id = a.CalcAlgorithm_id
      inner join CalcObject o on a.CalcObject_id = o.CalcObject_id;
  );


Вызов:
select * from x where CalcAlgorithm_CalcDate<=@CalcAlgorithm_CalcDate and CalcAlgorithm_SaveDate<=@CalcAlgorithm_SaveDate

Синтаксис и пр. я не проверял, так что в случае обнаружения ошибок прошу воспринимать его как намек.
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32114209
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большое сенкс за идею насчет вьювера :) Кое где можно будет этим воспользоваться. Насчет терминологии признаю - хромаю на обе ноги. Буду исправляться, а то получается, что практический опыт наработок есть, а обьяснить, что это - не могу :)
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32115215
c127
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тут еще мысль посетила. Самая большая проблема с этими subqueries ИМХО это что они не могут возварщать больше одного поля. Т.е. нельзя написать что-то типа:
Код: plaintext
1.
2.
select (select f1,f2 from t2 where t2.x=t1.x), ....
  from t1;

Поэтому, если нужно вернуть два и больше полей, приходится копировать подзапрос, что не есть хорошо, например в случае изменений кода подзапроса.

Но если f1 и f2 одного типа, то можно определить функцию (примерно):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
create function f(i int, x1 ...) returns int
begin
  declare v1, v2 int;
  select f1,f2 into v1,v2 from t2 where t2.x=x1;
  if (i= 1 ) then return v1;
  else            return v2;
end;

и вызывать:
Код: plaintext
1.
2.
select f( 1 ,t1.x), f( 2 ,t1.x), ....
  from t1;

Я так никогда не делал, но должно сработать. К тому же согласно сайбейзу, начиная с 8-й версии ASA кеширует результаы функций и не выполняет их повторно, если это возможно. Так что производительность сильно пострадать не должна.
...
Рейтинг: 0 / 0
Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
    #32115398
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я добил таки эти "параметризированные" вьюверы до нужной кондиции :)

Смысл какой - в принципе все они служат для возврата текущей версии информации на указанный период, т.е. получается что значения их параметров должны быть одинаковыми в одном запросе, потому как например запрос, в котором соединены 2 вьювера - ставок и договоров будет иметь смысл только при их параметрах, указывающих на один период. Согласно этой концепции (во всяком случае в переводимой моей БД это подтверждается) я поступил хитро - накатал процедуру, стартующую при запуске сессии, в которой сразу создаются и инициализируются значениями по умолчанию глобальные сессионные переменные, на которые и будут ссылаться параметризированные вьювера. Так же я снес свои функции, которые возвращали наиболее часто используемые значения параметров конфигурации и настроек с таблицы конфигурации и сделал в той процедуре их описание и инициализацию. Для читабельности принял для таких переменных следующую нотификацию:

@@ConfigVar - глобальная переменная конфигурации (например @@CalcDate - тек. расчетный месяц, @@CalcDateYear - первый день текущего расчетного года)

$Param - параметр, используемый в вьюверах (например $SaveDate - дата актуальности информации, $CalcDate - расчетный месяц)

В принципе работа получается терпимой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
   -- устанавливаем параметры 
 

   -- Параметр "расчетный месяц" в какое то значение:
 
  set $CalcDate = '20020101';
   -- Параметр "дата актуальности" в тек. расч. месяц
 
  set $SaveDate = @@CalcDate;

   -- Получаем список тек. открытых договоров и их действующих ставок
 
  select c.*, s.*
  from pv_Contract_Open c
    inner join pv_pv_Contract_Salary s on s.Contract_id = c.Contract_id


Еще что в этом решении очень порадовало - так как переменные параметры инициализируются по умолчанию и существуют в кажой сессии, то получается, что я легко могу выполнять запросы в ISQL без описания и инициализации параметров, и спокойно смотреть данные на такой вьювер прямо из Central во вкладке Data. Очень помогает отладке :)

Пока это все мои "извращения" с бедным Sybase. Буду надеятся, что не сильно шокирую публику такими "решениями". Но с другой стороны, если Sybase предоставляет такие возможности, пусть и в другом контексте использования, то для оптимального решения задачи перевода БД грех ими не воспользоваться :)
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Есть ли в ASA 8 аналог inline UDF-функций MSSQL 2000 ?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]