Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

тригер №2

3.9K
04 ноября 2004 года
generalm
28 / / 20.10.2004
CREATE OR REPLACE TRIGGER ochki
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);
}
}
но как это здесь организовать? как можно узнать какое поле он щас обрабатывает с тем чтобы получить код команды и взять сумму очков тока тех пилотов которые относяться к этой команде.

надеюсь вопрос понятен

}
10
04 ноября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by generalm
но как это здесь организовать? как можно узнать какое поле он щас обрабатывает с тем чтобы получить код команды и взять сумму очков тока тех пилотов которые относяться к этой команде.


Для доступа к факту изменения отдельного ПОЛЯ таблицы существует полный синтаксис создания триггера:

create or replace trigger <имя> <before/after> <действие> of <поле> on <имя таблицы> {for each row}

Но тебе, похоже, надо не это. Для доступа к предыдущим и новым значениям полей в триггерах сущестствуют предопределенные переменные OLD и NEW. Они имеют тип %ROWTYPE таблицы, для которой созданы. Соответственно, синтаксис для доступа к полям будет :NEW.CODE, :OLD.NAME и т. п. OLD и NEW определены не во всех типах триггеров, и не везде доступны для чтения и записи.

Надеюсь, верно понял по синтаксису, что используется БД Oracle.

10
04 ноября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by generalm
надеюсь вопрос понятен


Кстати, мне непонятно упорное использование триггеров. Если только это не студенческая лаба по триггерам, в Oracle лучше использовать GROUP BY вьюшки.

Могу помочь с проектированием, если надо.

3.9K
04 ноября 2004 года
generalm
28 / / 20.10.2004
вы правы это студенческая работа проект готов в принципе

я могу выложить инфологическую модель, саму базу(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;
/

делается все хорошо но кроме последней строки(записиси в таблице) ???
368
04 ноября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by generalm
на первый взгляд тригер должен работать но он в поля пишет нолики, тоесть ALFA похоже не получает никакого значения! тоесть код мотора ни равен, ни не равен :)
можете объяснить почему


Есть одно значение, которое не равно даже самой себе. Это NULL. В триггере ON INSERT значение :new не определено и принимается за NULL.

Кроме этого, не проще написать
IF (: old.код_мотора=: old.код_подвески) then
:new.колво_поставщиков=3;
ELSE
:new.колво_поставщиков=4;
END IF;

Цитата:
делается все хорошо но кроме последней строки(записиси в таблице) ???

потому что, это триггер BEFORE INSERT, последней строки еще нет.

3.9K
05 ноября 2004 года
generalm
28 / / 20.10.2004
Цитата:
Originally posted by rostyslav

Есть одно значение, которое не равно даже самой себе. Это 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;
/

вот почему это так не понятно... ведь мы редактируем инфу в этом же триггере! как он может заметить то что в нем же и происходит???

368
05 ноября 2004 года
rostyslav
629 / / 13.07.2004
Может все это потому, что в самом триггере меняешь значение поля. Кроме этого, значение : old не определено и в AFTER INSERT.

Первый триггер(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.
10
05 ноября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by generalm

CREATE OR REPLACE TRIGGER kolpost
AFTER INSERT ON м_автомобиль
FOR EACH ROW
...
UPDATE м_автомобиль
set колво_поставщиков=3;
END IF;
END kolpost;
/


В триггерах FOR EACH ROW нельзя изменять таблицу, на которую создан триггер. Это нарушает правило транзакционной целостности Oracle, и будет вызывать ошибки в работе.

Вместо этого надо пользоваться переменной NEW в соответствующем типе триггера, где она доступна для записи. В таблицу в этом случае будет записано значение, измененное триггером.

3.9K
05 ноября 2004 года
generalm
28 / / 20.10.2004
CREATE OR REPLACE TRIGGER ochki
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 человек персонал
и каждый зарабатывает очки... мне нужно их просуммировать... как вы думаете это лучше организовать через цикл по-другому никак?
368
05 ноября 2004 года
rostyslav
629 / / 13.07.2004
SELECT SUM(результат_очки) INTO :new.сумма_очков FROM т_результат
where код_людей = :new.код_людей;

может так пройдет?

Что касается суммирование очков команды...
Не лучше ввести для этой цели еще одну таблицу?

Кроме этого суммируются очки для всех сезонов.
3.9K
05 ноября 2004 года
generalm
28 / / 20.10.2004
ОГРОМНОЕ ВСЕМ СПАСИБО!

Тригеры доделаны, создал новую таблицу как советовали, ну и действительно строчечку в скрипте поменял

вот итоговые мучения если кому интересно:

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;
/
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог