тригер №2
BEFORE INSERT ON м_персонал
FOR EACH ROW
DECLARE cur INTEGER;
BEGIN
UPDATE м_персонал
SET сумма_очков=(SELECT SUM(результат_очки) FROM т_результат
where код_людей=м_персонал.код_людей);
END ochki;
в принципе работает правдо он не обрабатывает последнее поле таблицы куда я пишу... ине это не ясно... думаю это загадка природы
------------
м_персонал(главная)
------------
Код_сезона
Код_команды
Сумма_очков
Колво_очков
код_людей
-------------
Т_Результат(ассоц)
-----------------
Код_Результат(p)
Код_Людей(o)
Код_Сезона(o)
Код_Трассы(o)
Результат_Очки
Код_Команды(o)
колво_очков это сумма очков двух пилотов этой команды... я в принципе написал ниже приведу код, но он ругается на мой синтаксис
If код_команды=1 THEN
UPDATE м_персонал
SET колво_очков=(SELECT SUM(сумма_очков) FROM м_персонал
where код команды=1);
END IF;
здесь я для теста делаю 1 команду...
а вообще в сишке примерно бы выглядело так
for (int i=1; i<=10; i++)
{
if (текущее поле.код_команды=i){
{изменение поля:UPDATE м_персонал
SET колво_очков=(SELECT SUM
(сумма_очков)FROM м_персонал
where код команды=i);
}
}
но как это здесь организовать? как можно узнать какое поле он щас обрабатывает с тем чтобы получить код команды и взять сумму очков тока тех пилотов которые относяться к этой команде.
надеюсь вопрос понятен
}
но как это здесь организовать? как можно узнать какое поле он щас обрабатывает с тем чтобы получить код команды и взять сумму очков тока тех пилотов которые относяться к этой команде.
Для доступа к факту изменения отдельного ПОЛЯ таблицы существует полный синтаксис создания триггера:
create or replace trigger <имя> <before/after> <действие> of <поле> on <имя таблицы> {for each row}
Но тебе, похоже, надо не это. Для доступа к предыдущим и новым значениям полей в триггерах сущестствуют предопределенные переменные OLD и NEW. Они имеют тип %ROWTYPE таблицы, для которой созданы. Соответственно, синтаксис для доступа к полям будет :NEW.CODE, :OLD.NAME и т. п. OLD и NEW определены не во всех типах триггеров, и не везде доступны для чтения и записи.
Надеюсь, верно понял по синтаксису, что используется БД Oracle.
надеюсь вопрос понятен
Кстати, мне непонятно упорное использование триггеров. Если только это не студенческая лаба по триггерам, в Oracle лучше использовать GROUP BY вьюшки.
Могу помочь с проектированием, если надо.
я могу выложить инфологическую модель, саму базу(CREATE TABLE), значения, и тригеры... если это конечно интересно, а информация по гонкам Ф1(статистика на этот сезон).
И опять про тригеры
CREATE OR REPLACE TRIGGER kolpost
AFTER INSERT ON м_автомобиль
FOR EACH ROW
DECLARE ALFA INTEGER;
BEGIN
IF (: old.код_мотора=: old.код_подвески) then
ALFA:=1;
END IF;
IF (: old.код_мотора<>: old.код_подвески) then
ALFA:=2;
END IF;
IF (ALFA=1) THEN UPDATE м_автомобиль SET колво_поставщиков=3;END IF;
IF (ALFA=2) THEN UPDATE м_автомобиль SET колво_поставщиков=4;END IF;
END kolpost;
/
на первый взгляд тригер должен работать но он в поля пишет нолики, тоесть ALFA похоже не получает никакого значения! тоесть код мотора ни равен, ни не равен :)
можете объяснить почему
и если еще вас не утомил почему в тригере:
CREATE OR REPLACE TRIGGER ochki
BEFORE INSERT ON м_персонал
FOR EACH ROW
DECLARE cur INTEGER;
BEGIN
UPDATE м_персонал
SET сумма_очков=(SELECT SUM(результат_очки) FROM т_результат
where код_людей=м_персонал.код_людей);
END;
/
делается все хорошо но кроме последней строки(записиси в таблице) ???
на первый взгляд тригер должен работать но он в поля пишет нолики, тоесть ALFA похоже не получает никакого значения! тоесть код мотора ни равен, ни не равен :)
можете объяснить почему
Есть одно значение, которое не равно даже самой себе. Это NULL. В триггере ON INSERT значение :new не определено и принимается за NULL.
Кроме этого, не проще написать
IF (: old.код_мотора=: old.код_подвески) then
:new.колво_поставщиков=3;
ELSE
:new.колво_поставщиков=4;
END IF;
потому что, это триггер BEFORE INSERT, последней строки еще нет.
Есть одно значение, которое не равно даже самой себе. Это NULL. В триггере ON INSERT значение :new не определено и принимается за NULL.
Кроме этого, не проще написать
IF (: old.код_мотора=: old.код_подвески) then
:new.колво_поставщиков=3;
ELSE
:new.колво_поставщиков=4;
END IF;потому что, это триггер BEFORE INSERT, последней строки еще нет.
ага, а если поставить AFTER INSERT то выдает ошибку:
insert into м_персонал values (55,1,0,0,2)
*
ORA-04091: таблица STUD.М_ПЕРСОНАЛ изменяется, триггер/функция может не заметить это :))
ORA-06512: на "STUD.OCHKI", line 3
ORA-04088: ошибка во время выполнения триггера 'STUD.OCHKI'
и так с обоими тригерами
CREATE OR REPLACE TRIGGER ochki
AFTER INSERT ON м_персонал
FOR EACH ROW
DECLARE cur INTEGER;
BEGIN
UPDATE м_персонал
SET сумма_очков=(SELECT SUM(результат_очки) FROM т_результат
where код_людей=м_персонал.код_людей);
--IF м_персонал.код_команды = 1 THEN cur=0;END IF;
UPDATE м_персонал
SET колво_очков=(SELECT SUM(сумма_очков) FROM м_персонал
where код_людей=1 or код_людей=2);
END ochki;
/
CREATE OR REPLACE TRIGGER kolpost
AFTER INSERT ON м_автомобиль
FOR EACH ROW
DECLARE ALFA INTEGER;
BEGIN
IF (:old.код_мотора=:old.код_подвески) then
UPDATE м_автомобиль
set колво_поставщиков=3;
ELSE
UPDATE м_автомобиль
set колво_поставщиков=3;
END IF;
END kolpost;
/
вот почему это так не понятно... ведь мы редактируем инфу в этом же триггере! как он может заметить то что в нем же и происходит???
Первый триггер(kolpost) можно было оставить и как BEFORE INSERT, только вместо : old нужно использовать :new
Второй тоже(ochki),
:new.колво_очков=(SELECT SUM(результат_очки) FROM т_результат
where код_людей=:new.код_людей);
А это непонятно
UPDATE м_персонал
SET колво_очков=(SELECT SUM(сумма_очков) FROM м_персонал
where код_людей=1 or код_людей=2);
Думаю, что TRIGGER ochki нужно бы ставить на т_результат, а не на м_персонал. И не только на событие INSERT, но и на DELETE и UPDATE.
CREATE OR REPLACE TRIGGER kolpost
AFTER INSERT ON м_автомобиль
FOR EACH ROW
...
UPDATE м_автомобиль
set колво_поставщиков=3;
END IF;
END kolpost;
/
В триггерах FOR EACH ROW нельзя изменять таблицу, на которую создан триггер. Это нарушает правило транзакционной целостности Oracle, и будет вызывать ошибки в работе.
Вместо этого надо пользоваться переменной NEW в соответствующем типе триггера, где она доступна для записи. В таблицу в этом случае будет записано значение, измененное триггером.
BEFORE INSERT ON м_персонал
FOR EACH ROW
DECLARE cur INTEGER;
BEGIN
:new.сумма_очков:=(SELECT SUM(результат_очки) FROM т_результат
where код_людей=:new.код_людей);
END ochki;
/
// Предупреждение: Тригер создан с ошибками во время компиляции(если после сумма_очков убрать (":") таже самая ошибка, че он бесится?
--пока не придумал как сделать
--IF м_персонал.код_команды = 1 THEN cur=0;END IF;
--:new.колво_очков=(SELECT SUM(сумма_очков) FROM м_персонал
--where код_команды=cur);
здесь нужно взять все поля из м_персонала код_команды которых равен заданому
тоесть там 10 команда и допустим для каждого 5 человек персонал
и каждый зарабатывает очки... мне нужно их просуммировать... как вы думаете это лучше организовать через цикл по-другому никак?
where код_людей = :new.код_людей;
может так пройдет?
Что касается суммирование очков команды...
Не лучше ввести для этой цели еще одну таблицу?
Кроме этого суммируются очки для всех сезонов.
Тригеры доделаны, создал новую таблицу как советовали, ну и действительно строчечку в скрипте поменял
вот итоговые мучения если кому интересно:
CREATE OR REPLACE TRIGGER ochki
BEFORE INSERT ON м_персонал
FOR EACH ROW
BEGIN
SELECT SUM(результат_очки) INTO :new.сумма_очков FROM т_результат
where код_людей = :new.код_людей;
END ochki;
/
CREATE OR REPLACE TRIGGER ochkikom
BEFORE INSERT ON с_статистика
FOR EACH ROW
BEGIN
SELECT SUM(сумма_очков) INTO :new.колво_очков FROM м_персонал
where :new.код_команды = код_команды;
END ochkikom;
/
CREATE OR REPLACE TRIGGER kolpost
BEFORE INSERT ON м_автомобиль
FOR EACH ROW
DECLARE ALFA INTEGER;
BEGIN
IF (:old.код_мотора=:old.код_подвески) then
:new.колво_поставщиков:=3;
ELSE
:new.колво_поставщиков:=4;
END IF;
END kolpost;
/