Ошибка "Format '%s' invalid or incompatible with argume

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

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

Ошибка "Format '%s' invalid or incompatible with argume

Сообщение stepan96 » 25 ноя 2006, 23:51

Здравствуйте!

Преамбула. Некая учетная система переводится с MS SQL на Firebird. Одна из подсистем -это подсистема управления пользователями и группами пользователей.
Каждый пользователь системы может состоять в нескольких группах, и , соответственно, в каждой группе может быть несколько пользователей.
Реализовано это (тривиально) с помощью трех таблиц (отношение многие ко многим):
1. USERS
ID - Уникальный идентификатор
FLAG_ACTIVE - Признак активного пользователя (подробнее ниже)
EXPIRED - Срок работы пользователя (так же подробнее ниже)
...

2. GROUPS
ID - Уникальный идентификатор
FLAG_ACTIVE - Признак активной группы (так же подробнее ниже)
...

3. USERS_GROUPS
GROUP_ID - ID группы
USER_ID - ID пользователя

Для возможности операции блокировки работы пользователя (например, при уходе пользователя системы в отпуск и т.д.) в таблице USERS было заведено поле FLAG_ACTIVE (Домен BOOLEAN). Если данное поле равно нулю, пользователь в систему зайти не может. Поле EXPIRED служит для определения срока работы временного пользователя (для постоянного это поле содержит NULL). В момент, когда значение поля EXPIRED становится меньше или равным текущей дате, поле FLAG_ACTIVE Обращается в ноль и пользователь блокируется.
Поле FLAG_ACTIVE таблицы GROUPS по аналогии служит для блокировки целой группы пользователей, но блокироваться должны только те пользователи, группы, в которые они входят, являются заблокированными. Прошу прощения, если это несколько сумбурно, попробую объяснить на примере:
В системе существуют следующие группы:
  1. 1. Администраторы
    2. Руководители
    3. Временные работники
Пользователи:
  1. 1. Иванов
    2. Петров
    3. Сидоров
Пользователь Иванов входит во все три группы, Петров - группы Руководители и Временные работники, Сидоров - только Временные работники.
При блокировке группы Временные работники должен блокироваться только пользователь Сидоров, т.к. все его группы (в данном случае одна) являются заблокированными.

Теперь переходим к написанию ХП:

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

CREATE PROCEDURE CHECK_USERS
AS
DECLARE VARIABLE USER_ID BIGINT;
DECLARE VARIABLE COUNT_RECORDS BIGINT;
BEGIN
  /* 
    Блокируем временных пользователей, у которых истек срок работы
  */
  UPDATE
    USERS
  SET
    FLAG_ACTIVE = 0
  WHERE
    (EXPIRED IS NOT NULL) AND
    (EXPIRED <= CURRENT_DATE) AND
    (FLAG_ACTIVE = 1);

  /*
    Отбираем тех пользователей, которые входят в заблокированные
    группы
  */
  FOR SELECT DISTINCT
    USERS.ID
  FROM
    USERS,
    GROUPS,
    USERS_GROUPS
  WHERE
    (GROUPS.FLAG_ACTIVE = 0) AND
    (USERS.FLAG_ACTIVE = 1) AND
    (GROUPS.ID = USERS_GROUPS.GROUP_ID) AND
    (USERS.ID = USERS_GROUPS.USER_ID)
  INTO
    :USER_ID
  DO
  BEGIN
    /*
      Для каждого полученного пользователя находим количество
      активных групп, в которые он входит.
    */
    SELECT
      count(*)
    FROM
      USERS,
      GROUPS,
      USERS_GROUPS
    WHERE
      (GROUPS.FLAG_ACTIVE = 1) AND
      (GROUPS.ID = USERS_GROUPS.GROUP_ID) AND
      (USERS.ID = USERS_GROUPS.USER_ID) AND
      (USERS.ID = :USER_ID)
    INTO
      :COUNT_RECORDS;
      
    /*
      Если количество равно нулю - блокируем пользователя
    */
    IF (COUNT_RECORDS = 0) THEN
      UPDATE
        USERS
      SET
        FLAG_ACTIVE = 0
      WHERE
        ID = :USER_ID;
  END
END
При попытке запуска ХП (проверяю через SQL Manager for Interbase and Firebird, сайт: http://www.sqlmanager.net/ru/products/ibfb/manager) возникает следующая ошибка:
Format '%s' invalid or incompatible with argument
Коллеги, помогите пожалуйста победить ее, или хотя бы укажите в каком направлении носом рыть. Пытался через гуглу поискать, но то ли у меня руки из жопы растут, то ли одно из двух.

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

Сообщение kdv » 26 ноя 2006, 00:03

слишком длинная прелюдия. а так...

1. с bigint для идентификаторов ты переборщил. можно было обойтись INT.
2. в чем запускаешь процедуру? может проще прямо из sql вызвать Execute procedure ... ? в приложении та же ошибка возникает?

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

Сообщение stepan96 » 26 ноя 2006, 00:15

kdv писал(а):слишком длинная прелюдия. а так...
:-) Люблю тщательность. Был случай (лет 5-6 назад): описал проблему без прелюдии, долго пытались решить проблему, а когда спросили, что именно должно делаться, то оказалось, что эту проблему можно решить простой переработкой схемы. С тех пор всегда описываю, что я хочу получить, а уж потом как я себе представляю реализацию. Народ гораздо умнее меня - может быть и подскажет более эффективный путь решения проблемы.
kdv писал(а):1. с bigint для идентификаторов ты переборщил. можно было обойтись INT.
Вообщето на идентификаторы у меня отдельный домен заведен. :-) Я думаю для данной задачи это некретично.
kdv писал(а):2. в чем запускаешь процедуру? может проще прямо из sql вызвать Execute procedure ... ? в приложении та же ошибка возникает?
Проверяю эту процедуру из SQL менеджера. В приложении возникает та же ошибка. ХП не запускается. Поэтому и написал.

Может быть критично то, что тестирую я это на Firebird Embedded?

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

Сообщение kdv » 26 ноя 2006, 12:05

Может быть критично то, что тестирую я это на Firebird Embedded?
тестировать надо на обычном сервере. кроме того, проверь, правильный ли у тебя firebird.msg - сообщение какое-то левое на самом деле.

и еще - по ходу.
SELECT DISTINCT
USERS.ID
FROM
USERS,
GROUPS,
USERS_GROUPS
WHERE
(GROUPS.FLAG_ACTIVE = 0) AND
(USERS.FLAG_ACTIVE = 1) AND
(GROUPS.ID = USERS_GROUPS.GROUP_ID) AND
(USERS.ID = USERS_GROUPS.USER_ID)
лучше так не писать. используй алиасы явно сразу в from
SELECT DISTINCT
U.ID
FROM
USERS U,
GROUPS G,
USERS_GROUPS UG
WHERE
(G.FLAG_ACTIVE = 0) AND
(U.FLAG_ACTIVE = 1) AND
(G.ID = UG.GROUP_ID) AND
(U.ID = UG.USER_ID)

Ответить