powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / with execute block
38 сообщений из 38, показаны все 2 страниц
with execute block
    #38772896
Здравствуйте!

Искал решение одного вопроса и наткнулся на сообщение Влада Хорсуна (правильно перевёл?) о том, что он хотел внести предложение использовать конструкцию execute block в CTE. Однако больше об этом что-то ничего нигде не упоминалось (гугл не нашел).
Вот интересно: в данном направлении есть какие-нибудь движения? Или решили что это пижонство?
...
Рейтинг: 0 / 0
with execute block
    #38772949
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

не видел такого. А для чего это потребовалось. Может есть другие способы решения. Например в тройке внутри EXECUTE BLOCK разрешено в секции DECLARE объявлять локальные подпроцедуры и подфункции.

P.S. В 12 оракле что типа такого есть


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
WITH
  FUNCTION with_function(p_id IN NUMBER) RETURN NUMBER IS
  BEGIN
    RETURN p_id;
  END;
SELECT with_function(id)
FROM   t1
WHERE  rownum = 1
/

WITH_FUNCTION(ID)
-----------------
                1

SQL>
...
Рейтинг: 0 / 0
with execute block
    #38772982
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболевв данном направлении есть какие-нибудь движения?Пока нет
...
Рейтинг: 0 / 0
with execute block
    #38773210
Требовалось сделать выборку из таблиц на основе другой таблицы, и к результату применить группировку с агрегацией. Один из вариантов - дополнительная ХП. Не хотелось её рисовать, но, видимо, никуда не денешься, придёться ;)
...
Рейтинг: 0 / 0
with execute block
    #38773235
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Говнодизайн БД detected.
...
Рейтинг: 0 / 0
with execute block
    #38943259
Возвращаяст к говнодизайну (переделывать никто не даст).

Этот проект - журнал ремонтов оборудования на заводе. Есть таблица ремонтов. Она активно использует справочники и немного уникальной информации, как-то дата проведения ремонта, тип работ и другие мелочи (поля - указатели на соответствующие записи в справочниках). Так-же есть пара вспомогательных таблиц на орбите, данные которых соотносятся с таблицей ремонтов в отношении многие ко многим. Справочник оборудования выполнен в виде дерева вида: ID_оборудования, ID_предка, название_оборудования, другие_мелочи.

Нужно получить аггрегированную информацию (sum, count) из этих орбитальных таблиц причем с ограничением по конкретному оборудованию и конкретному пользователю.

При атаке "в лоб" - вывод данных за месяц по одному параметру производится от 1 минуты до 4, при этом в месяц происходит примерно 700-1000 ремонтов. Это неприемлимо долго. Выяснил, что поиск по оборудованию от корня к листьям в данном случае не подходит. Обратный поиск заметно быстрее, но тогда возникает проблема с аггрегацией данных в рамках одного запроса/одной ХП.

Текущее решение состоит из ХП выдающей промежуточный результат, и SQL запроса, собирающий итог из данных возвращаемых этой ХП. В ХП имеется 2 вложенных for select.

Вопрос: можно ли не прибегая к внешним запросам или ХП, в рамках одной процедуры получить агрегированные данные?
...
Рейтинг: 0 / 0
with execute block
    #38943265
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

ты запросик сюда кинь, может чего и подскажут. Необязательно свой оригинальный запрос. Можно что попроще для примера. В тройке можно попробовать через оконные функции
...
Рейтинг: 0 / 0
with execute block
    #38943285
Переработанный вариант общего итога (без орбитальных таблиц)

Хранимка:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
begin
 v_time1 = iif(i_time_1 is null, '01.01.2000', i_time_1);
 v_time2 = iif(i_time_2 is null, cast(dateadd(day, 1, current_date) as timestamp_info), i_time_2);

 for select et.device_id, sum(coalesce(et.dend - et.dbegin, 0)), count(et.event_id)
       from events_tbl et join users_ref ur using(user_id) join get_shop_childs(:i_dep_id) ds on ur.dep_id = ds.o_dep_id
      where et.dbegin >= :v_time1
        and et.dbegin < :v_time2
      group by 1
       into :v_dev_id, :o_sum_raw_time, :o_count_events
 do
 begin
  o_dev_id = null;
  with recursive dev_table as (
       select dev_id, parent_dev_id, dev_type, dev_name
         from devices_ref
        where dev_id = :v_dev_id
       union all
       select dr.dev_id, dr.parent_dev_id, dr.dev_type, dr.dev_name
         from devices_ref dr join dev_table dt on dr.dev_id = dt.parent_dev_id
  )
  select d.dev_id, trim(decode(d.dev_type, 1, '', dtr.dev_type_name) || ' ' || d.dev_name)
    from dev_table d join dev_type_ref dtr on d.dev_type = dtr.dev_type_id
   where parent_dev_id = :i_device_id
    into :o_dev_id, :o_dev_name;

  if (o_dev_id is not null) then
   suspend;
 end
end



ну и запрос соответствующий
Код: sql
1.
2.
3.
select o_dev_id, o_dev_name, sum(o_sum_raw_time), sum(o_count_events)
from get_device_summary(входные значения ограничения)
group by 1, 2



Хранимка (долгий вариант) для одной из орбитальных таблиц:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
begin
 if (i_time_1 is null) then
  v_time_1 = '01.01.2000';
 else
  v_time_1 = i_time_1;

 if (i_time_2 is null) then
  v_time_2 = dateadd(day, 1, current_date);
 else
  v_time_2 = i_time_2;

 for select zr.zip_id, zr.zip_name, zr.sap_n, uz.zip_sum
       from zip_ref zr, (select z.zip_id, sum(z.zip_count) zip_sum
                           from use_zip z join events_tbl et using(event_id)
                                join users_ref ur using(user_id) join get_shop_childs(:i_dep_id) ds
                                on ur.dep_id = ds.o_dep_id
                                join (with recursive dev_table as (
                                            select dev_id
                                              from devices_ref
                                             where parent_dev_id = :o_dev_id
                                            union all
                                            select dr1.dev_id
                                             from devices_ref dr1 join dev_table dt on dr1.parent_dev_id = dt.dev_id)
                                      select dev_id
                                        from dev_table) gde on et.device_id = gde.o_dev_elem_id
                                       where et.dbegin >= :v_time_1 and et.dbegin < :v_time_2
                         group by 1) uz
      where zr.zip_id = uz.zip_id
       into :o_zip_id, :o_zip_name, :o_sap_no, :o_count
 do
  suspend;
end



сломал уже голову, как можно это переделать чтобы быстро работало.
...
Рейтинг: 0 / 0
with execute block
    #38943366
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

кто тебе мешает считать суммы в самом цикле for select, а потом просто лишний suspend воткнуть

типа такого

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
sum_quantity = 0;
for select id, name, sum(quantity)
     from ....
     group by 1, 2
     into  id, name, quantity
do begin
  sum_quantity = sum_quantity + quantity; 
  suspend;
end
id = null;
name = 'Итого';
quantity = sum_quantity;
suspend;
...
Рейтинг: 0 / 0
with execute block
    #38943377
Симонов Денис,

да собственно, ничего не мешает. Была такая мысль. Вот только не помню, почему не реализовал (отказался). Это наверно от усталости. Надо отпуск брать и в горы уходить на недели две...
...
Рейтинг: 0 / 0
with execute block
    #38943402
Вспомнил почему!

o_dev_id и v_dev_id они разные и o_dev_id не идут подряд. Значит надо организовывать что-то вроде массива, что не есть хорошо. Сервер сам как-то это считает (наверно сортирует результат). Вот и как мне организовать эту сортировку? Там разброс может равновероятным на всем отрезке. И с повторами само собой. В общем не получится внутри второго цикла это считать ибо сортировку не сделать
...
Рейтинг: 0 / 0
with execute block
    #38943413
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

можно сначала загнать предварительные результаты в GTT и затем считать по ней

или в трёшке использовать SUM(PARTITION BY <нужные поля группировки>)
...
Рейтинг: 0 / 0
with execute block
    #38943444
Симонов Денис,

трёшка пока не рассматривается совсем (бета, и переносить проект - отдельный вопрос, возможно получиться и дизайн сменить), а вот насчет GTT - что-то не получается. Мож чего не правильно делал?
Можно пример, стопудово рабочий?
...
Рейтинг: 0 / 0
with execute block
    #38943458
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

а в чём проблема. Создаёшь GTT нужной структуры. GTT создаётся заранее а не динамически в ХП.

Затем делаем так

INSERT INTO MY_GTT(<поля>)
SELECT ... // твой сложный запрос

и далее

SELECT ... FROM MY_GTT // с нужными обработками

тут главный плюс MY_GTT можно соединять много раз и при этом сложный запрос не перевыполняется. Т.е. в данном случае мы используем GTT в качестве материализации того сложного запроса.
...
Рейтинг: 0 / 0
with execute block
    #38943470
Симонов Денис,

А эта GTT создается одна на всех пользюков, или для каждого своя?
...
Рейтинг: 0 / 0
with execute block
    #38943482
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

Одна.
...
Рейтинг: 0 / 0
with execute block
    #38943510
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевА эта GTT создается одна на всех пользюков, или для каждого своя?Метаданные одни на всех, но данные каждые видит строго свои (своей транзакции или своего коннекта, как настроишь).
...
Рейтинг: 0 / 0
with execute block
    #38943623
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВот и как мне организовать эту сортировку?Ты удивишься, но - с ORDER BY
...
Рейтинг: 0 / 0
with execute block
    #38943653
hvladАртемий СоболевВот и как мне организовать эту сортировку?Ты удивишься, но - с ORDER BY
Спасибо, К.О.! Вот может ко всему подскажете, как организовать сортировку на вложенном for select для всего набора? (по входным данным из первого for select)
...
Рейтинг: 0 / 0
with execute block
    #38943698
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВот может ко всему подскажетеЕсли бы в твоём описании можно было хоть что-то понять (меньше чем за полдня и без 100 грамм) - то может и подсказал бы
...
Рейтинг: 0 / 0
with execute block
    #38943727
hvladАртемий СоболевВот может ко всему подскажетеЕсли бы в твоём описании можно было хоть что-то понять (меньше чем за полдня и без 100 грамм) - то может и подсказал бы
Прошу прощения за сумбур в описании. в сообщении 17552771 в первом скрипте видны два цикла. Допустим в первом цикле выходят значения 78, 67, 98, 45... во вложенном втором цикле КАЖДОМУ значению соответствует ровно 1 значение, пусть будет например 1, 7, 14, 7 соответственно. мне нужно сделать сортировку (группирование) значений из внешнего цикла по значениям внутреннего цикла. Как видно, 7 встречается 2 раза, соответственно на выходе должно быть три строки 1, 7, 14. Для семерки должны состоятся суммирования. Вот не выходя за пределы одной ХП и не используя вспомогательную ХП каким образом сделать подсчеты, ну или сортировку для подсчетов вручную.
В свете GTT получается достаточно приемлемый вариант. Только надо озаботиться очисткой и другими безобразиями перед использованием. Но тогда ещё вопрос: кто и когда должен озаботиться удалением этой таблицы?
...
Рейтинг: 0 / 0
with execute block
    #38943735
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболевещё вопрос: кто и когда должен озаботиться удалением этой таблицы?

Никто и никогда. Почитай уже доку.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
with execute block
    #38943752
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевВ свете GTT получается достаточно приемлемый вариант. Только надо озаботиться очисткой и другими безобразиями перед использованием. Но тогда ещё вопрос: кто и когда должен озаботиться удалением этой таблицы?

Ты когда создаешь GTT - указываешь, когда данные в ней должны быть убиты. А дальше сервер сам все сделает.
...
Рейтинг: 0 / 0
with execute block
    #38943952
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевТолько надо озаботиться очисткой и другими безобразиями перед использованием.Доку почитай уже. При старте транзации (или коннекта) таблица всегда чистая.
...
Рейтинг: 0 / 0
with execute block
    #38944143
Dorin Marcoci
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немножко отошли от топика в сторону GTT, но всетаки "with execute block (params)" это будет мощная штука, если будет.
Незнаю если у Артемий прямо "Говнодизайн БД detected" но вот бы мне очень помогла такая конструкция, пока нету collateral joins.
Вот для топика http://www.sql.ru/forum/1152604/mozhno-li-vypolnit-odnim-zaprosom оптимально не обошелся без доп процедуры.
...
Рейтинг: 0 / 0
with execute block
    #38944167
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dorin Marcoci,

ты бы хоть название джойна скопировал, а то народ путаешь. Правильное название LATERAL JOIN.

LATERAL в трешке нет, но зато есть подпроцедуры

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
execute block
returns (
  name varchar(50),
  chestaround numeric(15, 3),
  wristaround numeric(15, 3))
as
  declare procedure subproc(code_horse int)
  returns (
    chestaround numeric(15, 3),
    wristaround numeric(15, 3))
  as
  begin
    select chestaround, wristaround
    from measure
    where code_horse = :code_horse
    order by age desc
    fetch first row only
    into chestaround, wristaround;
    suspend;
  end
begin
  for select
        horse.name,
        m.chestaround,
        m.wristaround
      from horse
      left join subproc(horse.code_horse) m on 1=1
  order by horse.name
  into name, chestaround, wristaround
  do suspend;
end
...
Рейтинг: 0 / 0
with execute block
    #38944179
Dorin Marcoci
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ой, дико извиняюсь, помню что что-то по бокам :)
...
Рейтинг: 0 / 0
with execute block
    #38944185
Объясните пожалуйста, что я делаю не так?
Создал временную таблицу. Select по rdb$relations её отображает. Но при компиляции ХП ругается, что такой таблицы нет. Даже если эту таблицу надо делать каждый раз при подключении пользователя (хотя в доке вроде об этом ни слова, и нет внятной информации как проверить её наличие), компиляция-то всё-равно не идет. Или предлагается заворачивать в строки и использовать execute statment? Но это тоже не логично.
...
Рейтинг: 0 / 0
with execute block
    #38944187
Dorin Marcoci
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисDorin Marcoci,
LATERAL в трешке нет, но зато есть подпроцедуры

так идея была _без_ процедур, нежели с под-процедурами.

хотя под-процедуры тоже отличная штука, если места где нужно агрегировать а потом еще чего-то делать...
...
Рейтинг: 0 / 0
with execute block
    #38944189
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dorin Marcoci,

для этого есть оконные функции SUM(field) OVER(...)
...
Рейтинг: 0 / 0
with execute block
    #38944191
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев

выкладывай скрипт как и что создаёшь. Ты походу динамически её решил создать. Так и не почитал документацию.
http://www.firebirdsql.org/file/documentation/reference_manuals/Firebird_Language_Reference_RUS.pdf
...
Рейтинг: 0 / 0
with execute block
    #38944216
Симонов ДенисАртемий Соболев

выкладывай скрипт как и что создаёшь. Ты походу динамически её решил создать. Так и не почитал документацию.
http://www.firebirdsql.org/file/documentation/reference_manuals/Firebird_Language_Reference_RUS.pdf

Документацию читал, тока ту, что на ангельском. Возможно что-то некорректно перевел. Сейчас изучаю вариант по указанной вами ссылке. По существу ваших негодований могу сказать, что создаю таблицу все-таки не в ХП (об этом очень много писалось как на параллельных ветках, в этой ветке, и других ресурсах сети. Надо быть абсолютным дебилом, чтобы это проигнорировать).
Вопрос остается открытым. Создание GTT - при подключении пользователя. А проверка на наличие уже имеющейся таблицы? Или в случае с GTT игнорируется факт уже существующей таблицы?

И ещё. Тут часто упоминают третью версию Firebird. Есть ли документация на эту волшебную СУБД? Хочется попробовать, и, возможно со временем, на неё перейти.
...
Рейтинг: 0 / 0
with execute block
    #38944223
Сейчас провел небольшой эксперимент:
создал GTT. Не отключаясь первым пользователем, подключился вторым пользователем, проверил - он эту таблицу не видит. При попытке создать такую же таблицу ругань в ответ.

Код: plaintext
1.
2.
3.
unsuccessful metadata update.
STORE RDB$RELATION_FIELDS failed.
attempt to store duplicate value (visible to active transactions) in unique index "RDB$INDEX_15".
Problematic key value is ("RDB$FIELD_NAME" = 'ID', "RDB$RELATION_NAME" = 'COMMON_RESUME_TABLE').
...
Рейтинг: 0 / 0
with execute block
    #38944230
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевДокументацию читал, тока ту, что на ангельском. Возможно что-то некорректно перевел. Сейчас изучаю вариант по указанной вами ссылке. По существу ваших негодований могу сказать, что создаю таблицу все-таки не в ХП (об этом очень много писалось как на параллельных ветках, в этой ветке, и других ресурсах сети. Надо быть абсолютным дебилом, чтобы это проигнорировать).
Вопрос остается открытым. Создание GTT - при подключении пользователя. А проверка на наличие уже имеющейся таблицы? Или в случае с GTT игнорируется факт уже существующей таблицы?

В английской версии написано почти тоже самое что и в русской. Разница лишь в том что пока нет англоязычного варианта который объединил бы весь синтаксис SQL. Есть только LangRef от IB 6 и LangRef Update в котором описаны изменения относительно IB6.

По сути вопроса. Не надо создавать GTT каждый раз при подключении. Надо создать её 1 раз (вообще) и потом использовать как и любую другую таблицу.


Артемий СоболевИ ещё. Тут часто упоминают третью версию Firebird. Есть ли документация на эту волшебную СУБД? Хочется попробовать, и, возможно со временем, на неё перейти.

Есть ReleaseNotes .
Есть так же документация и на русском аналог того что сделано на 2.5. Но поскольку LangRef Update для трешки ещё нет, да и сама она находится в Beta статусе, то эта дока не совсем полная. Возможно множество ошибок и т.д. Впрочем я могу выложить на неё ссылку, если kdv с Ковязиным не будут возражать.
...
Рейтинг: 0 / 0
with execute block
    #38944237
Симонов ДенисЕсть ReleaseNotes .

Этого на данном этапе достаточно, спасибо. Просто иметь представление об этой СУБД.


Один раз создать и потом пользоваться GTT пока не получается. Создаю GTT из под SYSDBA, отключаюсь, подключаюсь снова и этой таблицы нет. И как писал выше, если не отключаюсь одним ползователем, создавшим эту таблицу и подключаюсь другим, то второй не видит её. И создать не может.
...
Рейтинг: 0 / 0
with execute block
    #38944253
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий СоболевОдин раз создать и потом пользоваться GTT пока не получается. Создаю GTT из под SYSDBA, отключаюсь, подключаюсь снова и этой таблицы нет. И как писал выше, если не отключаюсь одним ползователем, создавшим эту таблицу и подключаюсь другим, то второй не видит её. И создать не может.ВСЕ (в том числе ГТТ) метаданные надо создавать монопольно, после коммита и дисконнекта этого коннекта можно поднимать коннекты работающие с данными, тогда все будет работать ГАРАНТИРОВАННО.
...
Рейтинг: 0 / 0
with execute block
    #38944255
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Артемий Соболев,

не ври. Commit делаешь?
...
Рейтинг: 0 / 0
with execute block
    #38944265
Симонов ДенисАртемий Соболев,

не ври. Commit делаешь?

Вот жеж!

Всё-таки устал, надо в отпуск. Спасибо всем, принявшим участие в этой ветке. Стыд и позор на мою голову, что не догадался о таком элементарном действе. Теперь всё как заявлено.

Отдельное спасибо Денису, за терпение и упорность тыканья меня носом в... а так-же за ссылку на полезный документ. Даже два.

У всех прошу прощения за отнятое у вас время.

Мне реально стыдно...
...
Рейтинг: 0 / 0
38 сообщений из 38, показаны все 2 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / with execute block
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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