EXECUTE STATEMENT в ХП

Модераторы: kdv, CyberMax

Ответить
stepan96
Сообщения: 12
Зарегистрирован: 15 сен 2005, 11:52

EXECUTE STATEMENT в ХП

Сообщение stepan96 » 12 дек 2006, 12:10

Добрый день!

Преамбула описана в http://forum.ibase.ru/phpBB2/viewtopic.php?t=2931.

Хранимая процедура GET_GROUP должна возвратить параметры группы пользователей (с этим проблем нет, код тривиальный, указывать не буду), а так же временную таблицу нижеуказанной структуры:

ID BIGINT,
FLAG_SYSTEM BOOLEAN,
FLAG_ACTIVE BOOLEAN,
NAME D_TITLE,
LOGIN D_TITLE,
FLAG BOOLEAN

Примечание1: BOOLEAN - Домен
Примесание2: D_TITLE - Домен VARCHAR(50) CHARACTER SET NONE

Эта таблица содержит список всех пользователей системы, и у тех пользователей, которые входят в запрашиваемую группу поле FLAG должно содержать 1.

Объясню для чего это.
Отступление1: разработка ведется в BDS 2006, используются компоненты FIBPlus, EhLib.
Форма редактирования группы содержит вкладку "Пользователи", на которой есть DBGridEh. Этот грид используется для отображения вышеуказанной временной таблицы для удобства определения списка пользователей, входящих в группу (Т.е. пользователь просто щелкает по чекбоку "FLAG").

Для определения признака вхождения пользователя в группу используется ХП USER_IN_GROUP:

Код: Выделить всё

CREATE PROCEDURE USER_IN_GROUP(
  GROUP_ID BIGINT,
  USER_ID BIGINT)
RETURNS(
  FLAG SMALLINT)
AS
BEGIN
  SELECT
    COUNT(*)
  FROM
    USERS_GROUPS UG
  WHERE
    (UG.USER_ID = :USER_ID) AND
    (UG.GROUP_ID = :GROUP_ID)
  INTO
    :FLAG;

  SUSPEND;
END
И, заполнение этой таблицы происходит следующим образом:

Код: Выделить всё

  QUERY = 'CREATE TABLE ' || TABLE_NAME || '(ID BIGINT, FLAG_SYSTEM BOOLEAN, FLAG_ACTIVE BOOLEAN, NAME D_TITLE, LOGIN D_TITLE, FLAG BOOLEAN)';
  EXECUTE STATEMENT QUERY;
  FOR SELECT
    ID
  FROM
    USERS
  INTO
    :USER_ID
  DO
  BEGIN
    USER_ID_STR = CAST(USER_ID AS VARCHAR(10));
    QUERY = 'INSERT INTO ' || TABLE_NAME || '(ID, FLAG_SYSTEM, FLAG_ACTIVE, NAME, LOGIN, FLAG) SELECT ID, FLAG_SYSTEM, FLAG_ACTIVE, NAME, LOGIN, USERINGROUP.FLAG FLAG FROM USERS, USER_IN_GROUP(' || USER_ID_STR || ', ' || GROUP_ID_STR || ') USERINGROUP WHERE ID = ' || USER_ID_STR;
    EXECUTE STATEMENT QUERY;
  END
Примечание3. TABLE_NAME - имя временной таблицы, генерируется уникальным образом для каждого вызова ХП.
Загвоздка вот в чем:
По отдельности код работает (проверяю в менеджере), т.е. если я отдельно создаю таблицу, а затем помещаю данные.
А в самой процедуре возникает ошибка в момент занесения данных: таблица TABLE_NAME Не существует.
Коментарю код занесения данных, запускаю процедуру, таблица создается.
Запускаю некоментаренную процедуру - возникает вышеуказанная ошибка.
Получается, что на момент занесения данных процедура не видит таблицы? Или что? Я что-то совсем запутался.
Люди добрые укажите в каком направлении рыть?
Спасибо заранее

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 12 дек 2006, 13:10

Создавать объекты метаданных и использовать их в одной транзакции нельзя. Так что забудь о такой схеме.

Временные таблицы имитируются не так. Посмотри в разделе документации (не помню, где, лень искать), что-то было.

Либо, вот сырой совет:
Таблица существует всегда, и она одна

Код: Выделить всё

create table TempTable(
session_id integer,
ID BIGINT, 
FLAG_SYSTEM BOOLEAN, 
...)
Генератором или ещё как-нибудь у тебя должно быть получено уникальное SESSION_ID, с которым ты и работаешь в этой таблице, чтобы не пересекаться с конкурентами, не забыв за собой почистить там всё.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 12 дек 2006, 14:03

А на кой здесь вообще временная таблица? Лично я бы вернул этот список прямо из ХП, и пусть он отображается себе в гриде. У нас тут процедуры покруче чем в MS, так что вышеописанная логика делается на счет "раз" безо всяких извращений.

stepan96
Сообщения: 12
Зарегистрирован: 15 сен 2005, 11:52

Сообщение stepan96 » 24 янв 2007, 09:41

Dimitry Sibiryakov писал(а):А на кой здесь вообще временная таблица? Лично я бы вернул этот список прямо из ХП, и пусть он отображается себе в гриде. У нас тут процедуры покруче чем в MS, так что вышеописанная логика делается на счет "раз" безо всяких извращений.
Проблема в том, что эти данные (а конкретно поле "FLAG") может изменяться. Если вернуть список напрямую из ХП, то данный набор данных определяется в клиенте как read only.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 24 янв 2007, 10:04

stepan96 писал(а):Если вернуть список напрямую из ХП, то данный набор данных определяется в клиенте как read only.
Уууу... Это вы, батенька, просто не умеете пользоваться компонентами доступа. Читайте на www.ibase.ru статью про IBX.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 24 янв 2007, 10:26

Если вернуть список напрямую из ХП, то данный набор данных определяется в клиенте как read only.
select вообще по определению read-only. с помощью SQL можно ЧИТАТЬ данные (select), и ИЗМЕНЯТЬ их (insert/update/delete).

stepan96
Сообщения: 12
Зарегистрирован: 15 сен 2005, 11:52

Сообщение stepan96 » 24 янв 2007, 11:15

Dimitry Sibiryakov писал(а): Уууу... Это вы, батенька, просто не умеете пользоваться компонентами доступа. Читайте на www.ibase.ru статью про IBX.
Не пользуюсь я IBX. Использую FIBPlus.
kdv писал(а):select вообще по определению read-only. с помощью SQL можно ЧИТАТЬ данные (select), и ИЗМЕНЯТЬ их (insert/update/delete).
Когда нибудь надо начинать учиться :-) Поэтому простите за следущий тупой вопрос:
ХП возвращает необходимые мне данные. Тогда запрос выборки выглядит следующим образом:

Код: Выделить всё

SELECT * FROM USERS_IN_GROUP(:USER_ID)
А как должен выглядеть запрос изменения данных? Ведь поля "FLAG" фактически не существует.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 24 янв 2007, 12:18

Не пользуюсь я IBX. Использую FIBPlus.
Да какая разница. Предок у них один и тот же - FIBC.
А как должен выглядеть запрос изменения данных?
Читай про IBX, конкретно - про TIBDataSet. Надеюсь, сам поймешь, как должен выглядеть запрос изменения данных...

stepan96
Сообщения: 12
Зарегистрирован: 15 сен 2005, 11:52

Сообщение stepan96 » 24 янв 2007, 17:45

CyberMax писал(а):Читай про IBX, конкретно - про TIBDataSet. Надеюсь, сам поймешь, как должен выглядеть запрос изменения данных...
Знаешь, видать я тупее, чем думаю. Если имелась в виду вот эта статья, то после ее прочтения я сделал вывод, что мне поможет ХП, которая будет вызываться в момент изменения состояния чекбокса FLAG. Для существующего объекта я приблизительно понимаю, как ее написать, а вот для вновь добавляемого необходимо будет использовать генератор в любом случае: будет ли записан объект или нет. Ведь для изменения информации о составе группы нужно знать ее ID. Не получится ли напрасное использование генератора? Я согласен, что в случае групп и пользователей скорее всего нет, но для некоторых других объектах (отношения так же многие ко многим) такой подход неприемлем, т.к. количество таких записей несравнимо больше.

Ответить