![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ограничение на поле
}|{yk © (2004-03-31 13:19:00)Как сделать ограничение на поле? Оно может принимать или значение из таблицы, или -1 (для дерева). В констрейнт не получается - нельзя подзапросы писать, с вьюхой связать тоже нельзя. А вообще как-то реализовывать можно? Можно конечно триггер написать, но это как-то неправильно...
}|{yk (2004-03-31 16:16:00) [21]наверно в 9 можно exists использовать в pl/sql. А в 8 нельзя
Курдль (2004-03-31 16:14:00) [22]
> Johnmen © (31.03.04 16:00) [21]
> >Курдль © (31.03.04 15:48) [19]
>
> Как выглядит источник ошибки ?
ОК! Для установления истины не поленился модифицировать код [8] по Вашим рекомендациям.
create or replace trigger TSK_GROUP_LOOP
before insert or update on PR_TASKS
for each row
-- when (NEW.TSK_ID_PR is not null)
declare
ex_GROUP_LOOP EXCEPTION;
begin
if exists
(select 1
from PR_TASKS T
where T.TSK_ID = :NEW.TSK_ID
and rownum = 1
start with T.TSK_ID = :NEW.TSK_ID_PR
connect by prior T.TSK_ID_PR = T.TSK_ID;
)
then RAISE ex_GROUP_LOOP;
end if;
EXCEPTION
WHEN ex_GROUP_LOOP THEN
Raise_application_error(-20103, 'Ïîïûòêà "êîëüöåâîé ãðóïïèðîâêè"');
WHEN OTHERS then
Raise_application_error(-20002, SQLERRM);
end TSK_GROUP_LOOP;
PL/SQL Developer отругался на нее, как было указано в [19]
Johnmen (2004-03-31 16:00:00) [23]>Курдль © (31.03.04 15:48) [19]
Как выглядит источник ошибки ?
}|{yk (2004-03-31 15:58:00) [24]PLS-00204 function or pseudo-column 'exists' may be used inside a SQL statement only
Cause: A pseudocolumn or proscribed function was used in a procedural statement. The SQL pseudocolumns (CURRVAL, LEVEL, NEXTVAL, ROWID, ROWNUM) can be used only in SQL statements. Likewise, certain functions such as DECODE, DUMP, and VSIZE and the SQL group functions (AVG, MIN, MAX, COUNT, SUM, STDDEV, VARIANCE) can be used only in SQL statements.
Action: Remove the pseudocolumn reference or function call from the procedural statement. Or, replace the procedural statement with a SELECT INTO statement; for example, replace:bonus := DECODE(rating, 1, 5000, 2, 2500, ...); with the following statement: SELECT DECODE(rating, 1, 5000, 2, 2500, ...) INTO bonus FROM dual;
Курдль (2004-03-31 15:48:00) [25]
> Точно ? Проверено ? А если ошибка, то какая ?
В случае замены в коде [8] на if exists ошибка следующая:
"Неверная переменная привязки:
start with T.TSK_ID = :NEW.TSK_ID_PR"
Johnmen (2004-03-31 15:10:00) [26]>}|{yk © (31.03.04 14:44) [16]
>Нет, в триггерах так нельзя
>Exists можно использовать только в предложениях SQL
Точно ? Проверено ? А если ошибка, то какая ?
DenK_vrtz (2004-03-31 14:56:00) [27]Чтобы не мучали проблемы мутации можно написать view и триггер к нему
}|{yk (2004-03-31 14:44:00) [28]2Johnmen © (31.03.04 14:20) [14]
Нет, в триггерах так нельзя
Exists можно использовать только в предложениях SQL
Курдль (2004-03-31 14:34:00) [29]
> А зачем
> and rownum = 1 ?
> Кстати, а что select 1 from ... будет быстрее для случая
> определения существования чем select count(*) from ?
Объединяя 2 вопроса.
1. Это чтобы запрос сдох сам по себе после того, как на первой же строке стало ясно, что "тест положительный".
2.count(*)будет упорно пересчитывать все записи
3. Не помню, почему было отказано в применении конструкцииif exists .... :)
Johnmen (2004-03-31 14:20:00) [30]>}|{yk © (31.03.04 14:08) [12]
>Кстати, а что select 1 from ... будет быстрее для случая >определения существования чем select count(*) from ?
Наиболее быстро
IF EXISTS(SELECT 1 FROM line)
THEN
}|{yk (2004-03-31 14:15:00) [31]Окончательный триггер таков
CREATE OR REPLACE TRIGGER APP_LINE_REPORT_TRG
BEFORE
INSERT OR UPDATE
ON APP_LINE_REPORT
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
col NUMBER;
vr_is_exists INTEGER;
ex_group_loop EXCEPTION;
ex_unknown_ident EXCEPTION;
BEGIN
SELECT COUNT (*)
INTO col
FROM line a
WHERE a.mem_id = :NEW.mem_pid;
IF (col = 0)
THEN
IF (:NEW.mem_pid -1)
THEN
RAISE ex_unknown_ident;
END IF;
END IF;
SELECT 1
INTO vr_is_exists
FROM app_line_report t
WHERE t.mem_id = :NEW.mem_id AND ROWNUM = 1
START WITH t.mem_id = :NEW.mem_pid
CONNECT BY PRIOR t.mem_pid = t.mem_id;
IF vr_is_exists IS NOT NULL
THEN
RAISE ex_group_loop;
END IF;
EXCEPTION
WHEN ex_group_loop
THEN
raise_application_error (-20101,
'Îøèáêà: "ïîïûòêà êîëüöåâîé ãðóïïèðîâêè"'
);
WHEN ex_unknown_ident
THEN
raise_application_error (-20102, 'Îøèáêà: Íåèçâåñòíûé èäåíòèôèêàòîð!');
END app_line_report_trg;
/
}|{yk (2004-03-31 14:08:00) [32]Кстати, а что select 1 from ... будет быстрее для случая определения существования чем select count(*) from ?
}|{yk (2004-03-31 14:04:00) [33]А зачем
and rownum = 1 ?
Спасибо за код
Курдль (2004-03-31 13:57:00) [34]Ну и как, скушало? :)
}|{yk (2004-03-31 13:56:00) [35]Вобщем вот так решил
CREATE OR REPLACE TRIGGER app_line_report_trg
BEFORE INSERT OR UPDATE
ON app_line_report
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
col NUMBER;
BEGIN
SELECT COUNT (*)
INTO col
FROM line a
WHERE a.mem_id = :NEW.mem_pid;
IF (col = 0)
THEN
IF (:NEW.mem_pid -1)
THEN
raise_application_error (-20501, 'Íåèçâåñòíûé èäåíòèôèêàòîð!');
END IF;
END IF;
END;
Курдль (2004-03-31 13:47:00) [36]Рабочий пример похожего триггера (оракл 9)
create or replace trigger TSK_GROUP_LOOP
before insert or update on PR_TASKS
for each row
-- when (NEW.TSK_ID_PR is not null)
declare
vr_IS_EXISTS INTEGER;
ex_GROUP_LOOP EXCEPTION;
begin
select 1 into vr_IS_EXISTS
from PR_TASKS T
where T.TSK_ID = :NEW.TSK_ID
and rownum = 1
start with T.TSK_ID = :NEW.TSK_ID_PR
connect by prior T.TSK_ID_PR = T.TSK_ID;
if vr_IS_EXISTS is not Null
then RAISE ex_GROUP_LOOP;
end if;
EXCEPTION
WHEN ex_GROUP_LOOP THEN
Raise_application_error(-20103, 'Ошибка: "попытка кольцевой группировки"');
WHEN OTHERS then
Raise_application_error(-20002, SQLERRM);
end TSK_GROUP_LOOP;
Vlad (2004-03-31 13:33:00) [37]
> Курдль © (31.03.04 13:30) [5]
> ! Никакой мутации не будет.
А что, разве мутация возникает только при записи ? :-)
> }|{yk © (31.03.04 13:26) [4]
Вобще, достаточно неплохая практика - делать все изменения в базе через ХП. Это поможет и мутации избежать.
Johnmen (2004-03-31 13:31:00) [38]>В констрейнт не получается - нельзя подзапросы писать
А как пробовал, что не получилось ?
>просто так вызовет мутацию таблицы. Или я не прав?
Мутацию можно отключить.
Все верно сказали про триггеры. Более того и констрейнты тоже реализуются через триггеры, системные.
Курдль (2004-03-31 13:30:00) [39]
> вызовет мутацию таблицы
Вы же не будете писать, а только контролировать! Никакой мутации не будет.
А насчет "муторно" - 3 строки текста :)
}|{yk (2004-03-31 13:26:00) [40]Oracle 8.1.7
Просто each row триггер писать на insert/update в Oracle муторно, просто так вызовет мутацию таблицы. Или я не прав?