Модераторы: Akella

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Имя таблицы входящим параметром, Передача в проц имени табл вход парам 
V
    Опции темы
Alkor135
Дата 26.5.2009, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Написал процедуру (FireBierd 2.1 доступ из Delphi 2009 через InterBase).
Мне нужно, чтобы она работала получая имя таблицы как входящий параметр.
Вот код, когда я задаю имя таблицы как входящий параметр, процедура не компилится (пробовал и с двоеточием):
Код

SET TERM ^ ;

CREATE OR ALTER PROCEDURE AUDCAD_PROC_END (
    i_pair char(6),
    p_input_date_min date,
    p_input_time_min time,
    p_input_date_max date,
    p_input_time_max time)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_op numeric(6,5),
    p_da_max date,
    p_ti_max time,
    p_cl numeric(6,5),
    p_point integer,
    p_point_mod integer)
as
begin
  p_pair = I_PAIR;

  /* Если даты не существует, то берем следующую дату (в цикле) */
  while (NOT exists (SELECT da FROM I_PAIR WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
  /* Если время нужной даты не существует, то берем следующее время (в цикле) */
  p_ti_min = P_INPUT_TIME_MIN;
  while (NOT exists (SELECT ti FROM I_PAIR WHERE (da = :p_input_date_min) and ti = :p_ti_min))  do
    p_ti_min = p_ti_min + 1;
  /* Если даты не существует, то берем предыдущую дату (в цикле) */
  while (NOT exists (SELECT da FROM I_PAIR WHERE da = :p_input_date_max))  do
    p_input_date_max = p_input_date_max - 1;
  /* Если время нужной даты не существует, то берем предыдущее время (в цикле) */
  p_ti_max = P_INPUT_TIME_MAX;
  while (NOT exists (SELECT ti FROM I_PAIR WHERE (da = :p_input_date_max) and ti = :p_ti_max))  do
    p_ti_max = p_ti_max - 1;

  SELECT da, ti, op
  FROM I_PAIR
  WHERE (da = :p_input_date_min and ti = :p_ti_min)
  INTO p_da_min, p_ti_min, p_op;

  SELECT da, ti, cl
  FROM I_PAIR
  WHERE (da = :p_input_date_max and ti = :p_ti_max)
  INTO p_da_max, p_ti_max, p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end^

SET TERM ; ^

GRANT EXECUTE ON PROCEDURE AUDCAD_PROC_END TO SYSDBA;


А когда задаю имя таблицы явно, все прекрасно компилируется и работает:
Код

SET TERM ^ ;

CREATE OR ALTER PROCEDURE AUDCAD_PROC_END (
    i_pair char(6),
    p_input_date_min date,
    p_input_time_min time,
    p_input_date_max date,
    p_input_time_max time)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_op numeric(6,5),
    p_da_max date,
    p_ti_max time,
    p_cl numeric(6,5),
    p_point integer,
    p_point_mod integer)
as
begin
  p_pair = I_PAIR;

  /* Если даты не существует, то берем следующую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
  /* Если время нужной даты не существует, то берем следующее время (в цикле) */
  p_ti_min = P_INPUT_TIME_MIN;
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_min) and ti = :p_ti_min))  do
    p_ti_min = p_ti_min + 1;
  /* Если даты не существует, то берем предыдущую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_max))  do
    p_input_date_max = p_input_date_max - 1;
  /* Если время нужной даты не существует, то берем предыдущее время (в цикле) */
  p_ti_max = P_INPUT_TIME_MAX;
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_max) and ti = :p_ti_max))  do
    p_ti_max = p_ti_max - 1;

  SELECT da, ti, op
  FROM audcad
  WHERE (da = :p_input_date_min and ti = :p_ti_min)
  INTO p_da_min, p_ti_min, p_op;

  SELECT da, ti, cl
  FROM audcad
  WHERE (da = :p_input_date_max and ti = :p_ti_max)
  INTO p_da_max, p_ti_max, p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end^

SET TERM ; ^

GRANT SELECT ON AUDCAD TO PROCEDURE AUDCAD_PROC_END;

GRANT EXECUTE ON PROCEDURE AUDCAD_PROC_END TO SYSDBA;


Подскажите как в процедуру передать имя таблицы как входящий параметр?

Это сообщение отредактировал(а) Alkor135 - 27.5.2009, 00:45
PM MAIL   Вверх
Akella
Дата 26.5.2009, 22:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Пока не могу сообразить. Но, наверное, придётся использовать execute statement

Добавлено через 3 минуты и 59 секунд
Примеры>>

Добавлено через 5 минут и 43 секунды
Кстати, источник:
Цитата

Источник

($firebird)/doc/sql.extensions/README.execute_statement.txt

($firebird)/doc/sql.extensions/README.execute_statement2.txt


PM MAIL   Вверх
Alkor135
Дата 27.5.2009, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Akella @ 26.5.2009,  22:37)
Пока не могу сообразить. Но, наверное, придётся использовать execute statement

Добавлено @ 22:41
Примеры>>

Добавлено @ 22:43
Кстати, источник:
Цитата

Источник

($firebird)/doc/sql.extensions/README.execute_statement.txt

($firebird)/doc/sql.extensions/README.execute_statement2.txt


Спасибо, буду разбираться.
PM MAIL   Вверх
Deniz
Дата 27.5.2009, 06:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Alkor135, опиши задачу, может обойдемся без execute statement


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Alkor135
Дата 27.5.2009, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Deniz @ 27.5.2009,  06:39)
Alkor135, опиши задачу, может обойдемся без execute statement

У меня есть 27 таблиц. Делаю выборку и получаю 27 строк, сортирую их по 7 полю и оставляю только 14 строк, т.е. остаются строки только из тех таблиц из которых нужно делать сдедующие выборки. Т.к. выборка у меня в StringGrid, беру и присваиваю значения ячеек с именами таблиц, созданным переменным. Вот теперь эти переменные мне и нужно передать как входные параметры в процедуру, где эти входные параметры будут стоять на месте имени таблицы.

По большому счету, нужно из выборки из 27 таблиц определить с какими 14 в дальнейшем работать (это уже реализовано).
Теперь нужно сформировать запрос к этим 14 таблицам. Процедуру написать легко если изначально знать имена всех 14 таблиц, но набор будет меняться в зависимости от даты выборки 27 таблиц.

Не знаю, понятно ли объяснил.

Есть мыслишка как это в Delphi сделать, т.е. значеня переменных вставлять в Query запрос. 
PM MAIL   Вверх
Deniz
Дата 28.5.2009, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(Alkor135 @  27.5.2009,  22:26 Найти цитируемый пост)
Не знаю, понятно ли объяснил.
я не понял  smile 
Посмотрев на код типа
Код
while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
понятно, что SQL не знаешь.
Если задать дату, больше которой нет в таблице, будет как в анекдоте: "Ну у Вас и запросы - сказала база данных и повисла."
Это реализовывается 1 запросом:
Код
SELECT min(da) FROM audcad WHERE da >= :p_input_date_min into :p_input_date_min;
аналогично для времени и для max.
Опять же зачем хранить отдельно date и time, есть же timestamp?

Это сообщение отредактировал(а) Deniz - 28.5.2009, 09:00


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Alkor135
Дата 28.5.2009, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Deniz @ 28.5.2009,  08:33)
Цитата(Alkor135 @  27.5.2009,  22:26 Найти цитируемый пост)
Не знаю, понятно ли объяснил.
я не понял  smile 
Посмотрев на код типа
Код
while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
понятно, что SQL не знаешь.
Если задать дату, больше которой нет в таблице, будет как в анекдоте: "Ну у Вас и запросы - сказала база данных и повисла."
Это реализовывается 1 запросом:
Код
SELECT min(da) FROM audcad WHERE da >= :p_input_date_min into :p_input_date_min;
аналогично для времени и для max.
Опять же зачем хранить отдельно date и time, есть же timestamp?

То, что я только начал изучать SQL - это правда.
А вот то, что я не пробовал min и max - это не правда.
У меня сделано 27 вот таких поцедуд (к каждой таблице):
Код

CREATE PROCEDURE AUDCAD_PROCEDURE_RANGE (
    p_input_date date)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_da_max date,
    p_ti_max time,
    p_op numeric(6,5),
    p_cl numeric(6,5),
    p_point numeric(6,1),
    p_point_mod numeric(6,1))
as
begin
/******************************************************************************/
/*                 Расчет AUDCAD для таблицы ранжирования                     */
/******************************************************************************/
   p_pair = 'AUDCAD';
/* Расчет минимальной даты в предыдущей неделе от выбранной даты */
  SELECT MIN(da)
  FROM audcad
  WHERE (EXTRACT (week from da))=EXTRACT (week from cast (:p_input_date as date)-7) AND
        (extract (year from da))=EXTRACT (YEAR from cast (:p_input_date as date)-7)
  INTO :p_da_min;

  SELECT MIN(ti)
  FROM audcad
  WHERE da = :p_da_min
  INTO :p_ti_min;

  SELECT MAX(da)
  FROM audcad
  WHERE (EXTRACT (week from da))=EXTRACT (week from cast (:p_input_date as date)-7) and
        (extract (year from da))=EXTRACT (YEAR from cast (:p_input_date as date)-7)
  INTO :p_da_max;

  SELECT MAX(ti)
  FROM audcad
  WHERE da = :p_da_max
  INTO :p_ti_max;

  SELECT op
  FROM audcad
  where (da = :p_da_min and ti = :p_ti_min)
  into :P_OP;

  SELECT cl
  FROM audcad
  where (da = :p_da_max and ti = :p_ti_max)
  into :p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end


И она, которая получает результат из всех 27:
Код

CREATE PROCEDURE SVOD_PROCEDURE_RANGE (
    p_input_date date)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_da_max date,
    p_ti_max time,
    p_op numeric(8,5),
    p_cl numeric(8,5),
    p_point numeric(6,1),
    p_point_mod numeric(6,1))
as
begin
  execute procedure audcad_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure audchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod);
  suspend;

  execute procedure audjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure audnzd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure audusd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure cadchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure cadjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure chfjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure euraud_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure eurcad_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure eurchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure eurgbp_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure eurjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;
  /* --------- */
  execute procedure eurnzd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure eurusd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure gbpaud_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure gbpcad_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure gbpchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure gbpjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure gbpusd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure nzdcad_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure nzdchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure nzdjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure nzdusd_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure usdcad_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure usdchf_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;

  execute procedure usdjpy_procedure_range(:P_INPUT_DATE)
    returning_values (:p_pair, :P_DA_MIN, :P_TI_MIN, :P_DA_MAX, :P_TI_MAX, :P_OP, :P_CL, :P_POINT, :p_point_mod); /**/
  suspend;
end


Так вок: сейчас у меня все прекрасно работает и сводную таблицу я получаю за 3 секунды.
Когда пользовался min и max, сводная таблица получалась за 40 секунд.
Поэтому я отказался от использования min и max.
PM MAIL   Вверх
Alkor135
Дата 28.5.2009, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Ну вот, вспомнил Deniz анекдот, у меня прога и повисла.
Вот такую хранимую процедуру в БД:
Код

SET TERM ^ ;

CREATE OR ALTER PROCEDURE AUDCAD_PROC_END (
    p_input_date_min date,
    p_input_time_min time,
    p_input_date_max date,
    p_input_time_max time)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_op numeric(6,5),
    p_da_max date,
    p_ti_max time,
    p_cl numeric(6,5),
    p_point integer,
    p_point_mod integer)
as
begin
  p_pair = 'AUDCAD';

  /* Если даты не существует, то берем следующую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
  /* Если время нужной даты не существует, то берем следующее время (в цикле) */
  p_ti_min = P_INPUT_TIME_MIN;
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_min) and ti = :p_ti_min))  do
    p_ti_min = p_ti_min + 1;
  /* Если даты не существует, то берем предыдущую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_max))  do
    p_input_date_max = p_input_date_max - 1;
  /* Если время нужной даты не существует, то берем предыдущее время (в цикле) */
  p_ti_max = P_INPUT_TIME_MAX;
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_max) and ti = :p_ti_max))  do
    p_ti_max = p_ti_max - 1;

  SELECT da, ti, op
  FROM audcad
  WHERE (da = :p_input_date_min and ti = :p_ti_min)
  INTO p_da_min, p_ti_min, p_op;

  SELECT da, ti, cl
  FROM audcad
  WHERE (da = :p_input_date_max and ti = :p_ti_max)
  INTO p_da_max, p_ti_max, p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end^

SET TERM ; ^

GRANT SELECT ON AUDCAD TO PROCEDURE AUDCAD_PROC_END;

GRANT EXECUTE ON PROCEDURE AUDCAD_PROC_END TO SYSDBA;


при этом все прекрасно работает 
user posted image

Я загружаю в StringGrid вот такой процедурой из Delphi:
Код

// Процедура получения конечной таблицы
procedure TForm1.SVOD_END();
var
  i : Integer;
  P_INPUT_DATE_MIN, P_INPUT_DATE_MAX : String;
  P_INPUT_TIME_MIN, P_INPUT_TIME_MAX : String;
begin
  P_INPUT_DATE_MIN := '02.03.2009';
  P_INPUT_TIME_MIN := '00:00';
  P_INPUT_DATE_MAX := '08.03.2009';
  P_INPUT_TIME_MAX := '23:59';

  P_1 := 'AUDCAD';
  //P_2 := 'AUDCHF';

  i := 1;
  {while i<>2 do
    begin  IBQuery1.Active:=False; }
      IBQuery2.SQL.Clear;
      IBQuery2.SQL.ADD('SELECT p_pair, p_da_min, p_ti_min, p_op, p_da_max, p_ti_max, p_cl, p_point, p_point_mod');
      IBQuery2.SQL.ADD('FROM '+P_1+'_proc_end (:P0, :P1, :P2, :P3)');
      IBQuery2.Params.Items[0].AsString := P_INPUT_DATE_MIN;
      IBQuery2.Params.Items[1].AsString := P_INPUT_TIME_MIN;
      IBQuery2.Params.Items[2].AsString := P_INPUT_DATE_MAX;
      IBQuery2.Params.Items[3].AsString := P_INPUT_TIME_MAX;
      IBQuery2.Active:=True;

        StringGrid2.Cells[0,i] := IBQuery2.Fields.Fields[0].Value;
        StringGrid2.Cells[1,i] := IBQuery2.Fields.Fields[1].Value;
        StringGrid2.Cells[2,i] := IBQuery2.Fields.Fields[2].Value;
        StringGrid2.Cells[3,i] := IBQuery2.Fields.Fields[3].Value;
        StringGrid2.Cells[4,i] := IBQuery2.Fields.Fields[4].Value;
        StringGrid2.Cells[5,i] := IBQuery2.Fields.Fields[5].Value;
        StringGrid2.Cells[6,i] := IBQuery2.Fields.Fields[6].Value;
        StringGrid2.Cells[7,i] := IBQuery2.Fields.Fields[7].Value;
        StringGrid2.Cells[8,i] := IBQuery2.Fields.Fields[8].Value;
    {    IBQuery1.Next();
        StringGrid2.RowCount := i+1;
        i := i+1;
    end;     }
  //SORT(); // Сортирую
end;

И прога виснет.
Может кто может подсказать, где я ошибся?

Это сообщение отредактировал(а) Alkor135 - 28.5.2009, 11:25
PM MAIL   Вверх
Gluttton
Дата 28.5.2009, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 7
Всего: 54



Цитата

И прога виснет.

Сколько по времени выполняется процедура в IBExpert'е?
И скольк по времени программа находиться в "подвешеном" состоянии?
Как вариант диагноз может быть такой:
Поскольку обращение к БД не вынесено в отдельный поток и выполняется за ощутимое (т.е. 1, 2 и более секунд) время, то пользовательский интерфейс клиентской (той которая обращается к БД) программы "подвисает" и приложение "Не отвечает". Но при этом не факт, что оно не работает.

Сам с таким столкнулся и пришлось запрос к БД выносить в отдельный процес - жуть...


--------------------
Слава Україні!
PM MAIL   Вверх
Alkor135
Дата 28.5.2009, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Gluttton @ 28.5.2009,  10:57)
Цитата

И прога виснет.

Сколько по времени выполняется процедура в IBExpert'е?
И скольк по времени программа находиться в "подвешеном" состоянии?
Как вариант диагноз может быть такой:
Поскольку обращение к БД не вынесено в отдельный поток и выполняется за ощутимое (т.е. 1, 2 и более секунд) время, то пользовательский интерфейс клиентской (той которая обращается к БД) программы "подвисает" и приложение "Не отвечает". Но при этом не факт, что оно не работает.

Сам с таким столкнулся и пришлось запрос к БД выносить в отдельный процес - жуть...

В IBExpert процедура обрабатывается за 1-2 секунды.
Когда вызываю из Delphi, то 5 минут ждал, потом надоело и закрыл. Отсюда и вынес вердикт, что она повесилась.
А как вынести в отдельный поток обращение к базе?

Ой, нашел свою ошибочку.  smile 
Орфография хромает.  smile 

Это сообщение отредактировал(а) Alkor135 - 28.5.2009, 11:26
PM MAIL   Вверх
Gluttton
Дата 28.5.2009, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 7
Всего: 54



Цитата

В IBExpert процедура обрабатывается за 1-2 секунды.
Когда вызываю из Delphi, то 5 минут ждал

При одинаковых входящих параметрах (извиняюсь за недоверчивость smile )? 
А вообще к БД обращение проходить нормально, т.е. любой другой запрос выполняется или это пока первый?

Цитата

А как вынести в отдельный поток обращение к базе?

Я пишу на CLI\C++ (не советую связываться, если под .NET, то лучше С# сразу брать и не мучаться smile ), так там (в .New Framwork) есть такой компонент backGroundWorker, который в себе это всё дело инкапсулирует... А если нет, то тогда юзать Thread...


--------------------
Слава Україні!
PM MAIL   Вверх
Alkor135
Дата 28.5.2009, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Gluttton @ 28.5.2009,  11:28)
Цитата

В IBExpert процедура обрабатывается за 1-2 секунды.
Когда вызываю из Delphi, то 5 минут ждал

При одинаковых входящих параметрах (извиняюсь за недоверчивость smile )? 
А вообще к БД обращение проходить нормально, т.е. любой другой запрос выполняется или это пока первый?

Цитата

А как вынести в отдельный поток обращение к базе?

Я пишу на CLI\C++ (не советую связываться, если под .NET, то лучше С# сразу брать и не мучаться smile ), так там (в .New Framwork) есть такой компонент backGroundWorker, который в себе это всё дело инкапсулирует... А если нет, то тогда юзать Thread...

Вот-вот, во входящие параметры закралась ошибочка, но теперь то я пост подправил и ее не видно.   smile 

А вообще это мой первый проект по программированию как в Delphi так и в SQL (FireBird).
Delphi мне показался проще чем С++. До сих пор вехать не могу, чтож за классы там такие.
К томуже, примеров для Delphi нашел больше.
Мне вообще советовали на Java писать, говорят кросплатформенная штука, за ней будующее.
PM MAIL   Вверх
Deniz
Дата 28.5.2009, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(Alkor135 @  28.5.2009,  12:17 Найти цитируемый пост)
Так вок: сейчас у меня все прекрасно работает и сводную таблицу я получаю за 3 секунды.
Когда пользовался min и max, сводная таблица получалась за 40 секунд.
Поэтому я отказался от использования min и max. 
не верю (с)
Сравни 2 кода на быстродействие (сделай 2 тестовые процедуры):
Код
while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
и
Код
SELECT min(da) FROM audcad WHERE da >= :p_input_date_min into :p_input_date_min;

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


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Alkor135
Дата 28.5.2009, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.4.2009

Репутация: нет
Всего: нет



Цитата(Deniz @ 28.5.2009,  15:02)
Цитата(Alkor135 @  28.5.2009,  12:17 Найти цитируемый пост)
Так вок: сейчас у меня все прекрасно работает и сводную таблицу я получаю за 3 секунды.
Когда пользовался min и max, сводная таблица получалась за 40 секунд.
Поэтому я отказался от использования min и max. 
не верю (с)
Сравни 2 кода на быстродействие (сделай 2 тестовые процедуры):
Код
while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
и
Код
SELECT min(da) FROM audcad WHERE da >= :p_input_date_min into :p_input_date_min;

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

А FireBird, где-нибудь показывает за какое время он выполнил процедуру?
Я сравнил визуально, моя выполняется за 2 сек., твоя за 3 сек., но я могу быть субективен.

Зато очень сильно отличаюся по скорости две моих других процедуры.
Та что за 2 сек.
Код

SET TERM ^ ;

CREATE OR ALTER PROCEDURE AUDCAD_PROCEDURE (
    p_input_date_min date,
    p_input_date_max date)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_op numeric(6,5),
    p_da_max date,
    p_ti_max time,
    p_cl numeric(6,5),
    p_point numeric(6,1),
    p_point_mod numeric(6,1))
as
begin
/******************************************************************************/
/*                 Расчет AUDCAD для таблицы ранжирования                     */
/******************************************************************************/
  p_pair = 'AUDCAD';

  /* Если даты не существует, то берем следующую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_min))  do
    p_input_date_min = p_input_date_min + 1;
  /* Если время нужной даты не существует, то берем следующее время (в цикле) */
  p_ti_min = '00:00';
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_min) and ti = :p_ti_min))  do
    p_ti_min = p_ti_min + 1;

  /* Если даты не существует, то берем предыдущую дату (в цикле) */
  while (NOT exists (SELECT da FROM audcad WHERE da = :p_input_date_max))  do
    p_input_date_max = p_input_date_max - 1;
  /* Если время нужной даты не существует, то берем предыдущее время (в цикле) */
  p_ti_max = '23:59';
  while (NOT exists (SELECT ti FROM audcad WHERE (da = :p_input_date_max) and ti = :p_ti_max))  do
    p_ti_max = p_ti_max - 1;

  SELECT da, ti, op
  FROM audcad
  WHERE (da = :p_input_date_min and ti = :p_ti_min)
  INTO p_da_min, p_ti_min, p_op;

  SELECT da, ti, cl
  FROM audcad
  WHERE (da = :p_input_date_max and ti = :p_ti_max)
  INTO p_da_max, p_ti_max, p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end^

SET TERM ; ^

GRANT SELECT ON AUDCAD TO PROCEDURE AUDCAD_PROCEDURE;

GRANT EXECUTE ON PROCEDURE AUDCAD_PROCEDURE TO PROCEDURE SVOD_PROCEDURE;
GRANT EXECUTE ON PROCEDURE AUDCAD_PROCEDURE TO SYSDBA;


Вторая с min и max выполняется почти 2 мин.:
Код

SET TERM ^ ;

CREATE OR ALTER PROCEDURE AUDCAD_PROCEDURE_RANGE (
    p_input_date date)
returns (
    p_pair char(6),
    p_da_min date,
    p_ti_min time,
    p_da_max date,
    p_ti_max time,
    p_op numeric(6,5),
    p_cl numeric(6,5),
    p_point numeric(6,1),
    p_point_mod numeric(6,1))
as
begin
/******************************************************************************/
/*                 Расчет AUDCAD для таблицы ранжирования                     */
/******************************************************************************/
   p_pair = 'AUDCAD';
/* Расчет минимальной даты в предыдущей неделе от выбранной даты */
  SELECT MIN(da)
  FROM audcad
  WHERE (EXTRACT (week from da))=EXTRACT (week from cast (:p_input_date as date)-7) AND
        (extract (year from da))=EXTRACT (YEAR from cast (:p_input_date as date)-7)
  INTO :p_da_min;

  SELECT MIN(ti)
  FROM audcad
  WHERE da = :p_da_min
  INTO :p_ti_min;

  SELECT MAX(da)
  FROM audcad
  WHERE (EXTRACT (week from da))=EXTRACT (week from cast (:p_input_date as date)-7) and
        (extract (year from da))=EXTRACT (YEAR from cast (:p_input_date as date)-7)
  INTO :p_da_max;

  SELECT MAX(ti)
  FROM audcad
  WHERE da = :p_da_max
  INTO :p_ti_max;

  SELECT op
  FROM audcad
  where (da = :p_da_min and ti = :p_ti_min)
  into :P_OP;

  SELECT cl
  FROM audcad
  where (da = :p_da_max and ti = :p_ti_max)
  into :p_cl;

  /* Разница в пунктах */
  p_point = (p_op - p_cl)* 100000;

  /* Разница в пунктах по модулю */
  if (p_point<0) THEN
    p_point_mod = p_point*(-1);
    else p_point_mod = p_point;

  suspend;
end^

SET TERM ; ^

GRANT SELECT ON AUDCAD TO PROCEDURE AUDCAD_PROCEDURE_RANGE;

GRANT EXECUTE ON PROCEDURE AUDCAD_PROCEDURE_RANGE TO SYSDBA;


Хотя эти процедуры не совсем равнозначны. У первой два входных параметра, а вторая один входной обсчитывает и делает два параметра внутри себя.
Может действительно скорость выполнения не от использования min и max зависит? 
Тогда подскажите отчего она такая разная?
Кстати все таблицы у меня проиндексированы по двум полям (по дате и по времени).


Это сообщение отредактировал(а) Alkor135 - 28.5.2009, 17:06
PM MAIL   Вверх
Gluttton
Дата 28.5.2009, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 7
Всего: 54



Цитата

А FireBird, где-нибудь показывает за какое время он выполнил процедуру?


Ну здрасте, а скриншот ты с чего делал?! Не с IBExpert'а?!
Вот в нём при выполнении запроса в нижней части активного окна появляется Memo-поле, куда выводиться код ошибки, план запроса и время выполнения запроса! smile !


--------------------
Слава Україні!
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Interbase"
Alex

Обязательно указание:

1. Версию InterBase (Firebird, Yaffil)

2. Способа доступа (ADO, BDE, IBX и т.д.)

  • КАК ПРАВИЛЬНО ОФОРМИТЬ КОД - ЗДЕСЬ
  • КАК ПРАВИЛЬНО УКАЗАТЬ ТЕКСТ ОШИБКИ - ЗДЕСЬ
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Firebird, Interbase | Следующая тема »


 




[ Время генерации скрипта: 0.0727 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.