Преамбула. Некая учетная система переводится с 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. Администраторы
2. Руководители
3. Временные работники
- 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
Format '%s' invalid or incompatible with argument
Коллеги, помогите пожалуйста победить ее, или хотя бы укажите в каком направлении носом рыть. Пытался через гуглу поискать, но то ли у меня руки из жопы растут, то ли одно из двух.