Форум программистов, компьютерный форум, киберфорум
Oracle
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.96/25: Рейтинг темы: голосов - 25, средняя оценка - 4.96
0 / 0 / 0
Регистрация: 24.12.2015
Сообщений: 12

Триггер AFTER LOGON

25.12.2015, 09:30. Показов 5309. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, у меня проблема с запуском процедуры test_maile (отправка почты с уведомлением о событии с учетом условия) из триггера.
Создал триггер его код:

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE OR REPLACE TRIGGER test_log
AFTER LOGON ON DATABASE
 
DECLARE
count_proc NUMBER;
BEGIN
 
SELECT COUNT(*) INTO count_proc FROM v$process;
IF count_proc = 64 --лимит кол-во занятых процессов представление v$process
 
THEN CALL test_maile
END IF;
 
END;
но вот компилятор говорит, что ему не нравится test_maile
я конечно понимаю, что для вызова процедуры нужно что-то дописать еще, а что не знаю, может кто подскажет?

PS: версия Oracle 11g

Добавлено через 8 часов 29 минут
Ситуация такая написал триггер LOGON, который срабатывает когда кто-то входит в БД и при определенных условиях отправляет письмо, но кол-во писем растет одно, второе и т.д. при любых действиях пользователя (запросы и т.п.)

Хотелось бы так ... пользователь зашел в систему триггер отработал ОДИН РАЗ т.е. отправил только ОДНО письмо и игнорировал дальнейшие действия пользователя и так далее зашел второй пользователь еще письмо .....
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE OR REPLACE TRIGGER test_log
AFTER LOGON ON DATABASE
 
DECLARE
count_proc NUMBER;
BEGIN
 
SELECT COUNT(*) INTO count_proc FROM v$sessoins;
IF count_proc = 64 --лимит сессий
 
THEN test_maile;
END IF;
END;
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.12.2015, 09:30
Ответы с готовыми решениями:

Триггер, вызывающий процедуру, в которой выполняется select к этой таблице (откуда был вызван триггер)
есть тригерр create or replace trigger quickstart.quickstart.ACRIONS_COMMIT_TR after update on quickstart.actions for each...

Logon from PL/SQL developer
запущен oracle database express edition, надо залогиниться с PL/SQL developer. Последний кроме логина и пароля просит еще БД (название...

Проблема при создании Logon триггера
Добрый день, Возникла проблема при создании Logon триггера. Ситуация такая, есть схема в Oracle, надо чтобы при подключении к ней...

7
765 / 666 / 194
Регистрация: 24.11.2015
Сообщений: 2,163
26.12.2015, 14:10
Ну, во-первых, как это ни смешно, я бы сделал триггер не AFTER LOGON, а BEFORE_LOGON.
Нельзя делать такой триггер. Какие-то смутные воспоминания были, но оказались ошибочными. Если разберусь - напишу.

Во-вторых, я не понимаю, что такое v$sessoins. Я так полагаю, что это либо опечатка, либо какой-то синоним системной вьюхи sys.v_$SESSION. Если так, то нужно какое-то ограничивающее условие, исключающее серверные процессы, ну например WHERE audsid>0 . В противном случае Ваше условие =64 просто смешное. Ну еще можно добавить and username not like 'SYS%'. Но это если очень хочется.

Наконец, не понимаю, почему условие выбрано в виде IF count_proc = 64 . Я бы, как минимум, написал IF count_proc >= 64

Добавлено через 11 минут
Кстати, а как у Вас организована отправка почты в процедуре test_maile? Может там вшит какой-то определенный юзер, Вы например, и Вы получаете почту в ответ на любой заход любого другого юзера?
Может сделать эту процедуру с параметром, типа procedure test_maile(p_user in varchar2); и вызывать как-то так:
test_maile(user);

Добавлено через 1 час 30 минут
Короче говоря, было у меня какое-то кратковременное помрачение рассудка.
Сделал я на рабочей базе (чтобы много сессий было) дополнительный триггер AFTER LOGON ON DATABASE и еще один дополнительный триггер BEFORE LOGOFF ON DATABASE, все равно у нас есть такие. Имитировал работу Вашего триггера, но только не отправляю почту, а пишу в протокольную таблицу. Триггер отрабатывает только один раз и делает в протокольной таблице ровно одну запись на каждую сессию.
Мне кажется, Ваши проблемы лежат в процедуре test_maile, посмотрите ее внимательно или выложите текст в тему.
0
0 / 0 / 0
Регистрация: 24.12.2015
Сообщений: 12
28.12.2015, 01:39  [ТС]
1. представление v$sessions показывает кто в данный момент сидит в базе (это долга история там очень много нюансов с использованным ПО) и потому очень важно какое кол-во сессий.

2.

3. вот текст процедуры maile:

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
CREATE OR REPLACE PROCEDURE test_maile IS
 
--DECLARE
 
 
    subject VARCHAR2(60) := 'TEST TRIGGER'; -- Заголовок письма
    message VARCHAR2(60) := 'USER IN DB'; -- Содержимое письма
    mailhost VARCHAR2(30) := 'НЕКИЙ сервер';   -- сервер почты smtp.что-то.ru
    sender VARCHAR2(30) := 'учетка'; -- отправитель <кто-то@ххх.ru>
    recipient VARCHAR2(255) := 'учетка'; -- получатель <кто-то@ххх.ru>
    mail_conn utl_smtp.connection;
 
BEGIN
 
    mail_conn := utl_smtp.open_connection(mailhost, 25);
    utl_smtp.helo(mail_conn, mailhost);
    utl_smtp.mail(mail_conn, sender);
    utl_smtp.rcpt(mail_conn, recipient);
    utl_smtp.open_data(mail_conn );
    utl_smtp.write_data(mail_conn,'Date: ' || to_char(sysdate,'dd Mon yy hh24:mi:ss','NLS_DATE_LANGUAGE = AMERICAN')||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'From: ' || sender||CHR(13)||CHR(10));
    utl_smtp.write_raw_data(mail_conn, utl_raw.cast_to_raw('Subject: '||NVL(subject,'(no subject)')||CHR(13)||CHR(10)));
    utl_smtp.write_data(mail_conn,'MIME-Version: 1.0' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'Content-Type: text/plain; charset="windows-1251"' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'Content-Transfer-Encoding: 8bit' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'To: '||recipient||CHR(13)||CHR(10));
    utl_smtp.write_raw_data(mail_conn,utl_raw.cast_to_raw(CHR(13)||CHR(10)|| message));
    utl_smtp.close_data(mail_conn );
    utl_smtp.quit(mail_conn);
 
EXCEPTION
WHEN OTHERS THEN
    utl_smtp.quit(mail_conn);
END;
Добавлено через 1 минуту
вдогонку пункт 2 IF count_proc = 64 это как пример
0
765 / 666 / 194
Регистрация: 24.11.2015
Сообщений: 2,163
28.12.2015, 11:12
Добавьте такие строки, и Вы ув'идете, что письма приходят из разных сессий.
SQL
1
2
3
4
5
6
7
8
9
.....
BEGIN
 
    message:=message||'   sid='||sys_context('USERENV','SID');  -- кажется только начиная с Oracle11
    message:=message||'   audsid='||sys_context('USERENV','SESSIONID');
    message:=message||'   user='||USER;
 
    mail_conn := utl_smtp.open_connection(mailhost, 25);
......
И из каждой по одному разу.
0
0 / 0 / 0
Регистрация: 24.12.2015
Сообщений: 12
29.12.2015, 02:56  [ТС]
Добавил messages вниз кода вверх, но результат, что на каждый чих сессии(ий) письма приходят, а не так зашел в базу пользователь одно письмо
Походу что то не так или в коде триггера или в коде процедуры....


SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
BEGIN
 
    message:=message||'   sid='||sys_context('USERENV','SID');  -- кажется только начиная с Oracle11
    message:=message||'   audsid='||sys_context('USERENV','SESSIONID');
    message:=message||'   user='||USER;
 
 
    mail_conn := utl_smtp.open_connection(mailhost, 25);
    utl_smtp.helo(mail_conn, mailhost);
    utl_smtp.mail(mail_conn, sender);
    utl_smtp.rcpt(mail_conn, recipient);
    utl_smtp.open_data(mail_conn );
    utl_smtp.write_data(mail_conn,'Date: ' || to_char(sysdate,'dd Mon yy hh24:mi:ss','NLS_DATE_LANGUAGE = AMERICAN')||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'From: ' || sender||CHR(13)||CHR(10));
    utl_smtp.write_raw_data(mail_conn, utl_raw.cast_to_raw('Subject: '||NVL(subject,'(no subject)')||CHR(13)||CHR(10)));
    utl_smtp.write_data(mail_conn,'MIME-Version: 1.0' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'Content-Type: text/plain; charset="windows-1251"' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'Content-Transfer-Encoding: 8bit' ||CHR(13)||CHR(10));
    utl_smtp.write_data(mail_conn,'To: '||recipient||CHR(13)||CHR(10));
    utl_smtp.write_raw_data(mail_conn,utl_raw.cast_to_raw(CHR(13)||CHR(10)|| message));
    utl_smtp.close_data(mail_conn );
    utl_smtp.quit(mail_conn);
 
    
EXCEPTION
WHEN OTHERS THEN
    utl_smtp.quit(mail_conn);
END;
0
765 / 666 / 194
Регистрация: 24.11.2015
Сообщений: 2,163
29.12.2015, 10:40
Вопросы:
1) Уточните, у Вас триггер на схему или на базу? От имени какого пользователя создан триггер AFTER LOGON ON DATABASE? Нужно, чтобы был от имени SYS, но не знаю, как у Вас с правами
2) Приходят ли несколько писем из одной сесии? Если есть два письма из одной сесии, попробуйте приложить к сообщениню. Текста с message будет достаточно
3) Есть ли у Вас возможность организовать вместо писем протоколирование в автономных транзакциях? Если будете заниматься, могу прислать код простенького пакета. Желательно сделать протокол, скинуть его, например в Excel и потом тоже приложить
4) Нет ли в базе случайно нескольких аналогичных триггеров? Вас небось там много вокруг нее пасется
5) Что означает фраза
Цитата Сообщение от alc_alc Посмотреть сообщение
а не так зашел в базу пользователь одно письмо
. Подробнее, пожалуйста. Что такое "так" и "не так"?
0
0 / 0 / 0
Регистрация: 24.12.2015
Сообщений: 12
30.12.2015, 01:11  [ТС]
1. на базу триггер создан в sys
2. да приходят, текст письма прост в нем указана инфа о пользователе (sid, имя)
3. возможности нет, но могу сказать, что когда я создал табличку табличку в которую по идеи должно записываться лишь одна строчка с инфой о сессии, то в таблицу постоянно при каждом selecte заливаются данные
4. аналогичных триггеров в БД отсутствую
5. фраза значит - результат работы триггера - одна сессия (SID) -> только одно письмо

Может нужно как то глушить работу триггера для sid которые уже проверены так сказать? Но я не знаю как это сделать ...
0
765 / 666 / 194
Регистрация: 24.11.2015
Сообщений: 2,163
30.12.2015, 10:19
Вот мой триггер как есть
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE OR REPLACE TRIGGER LOGON_TEST_AFTER
 AFTER 
 LOGON
 ON DATABASE
DECLARE
    p_spl       NUMBER;
    v_sid       NUMBER;
    v_serial    NUMBER;
    v_audsid    NUMBER;
BEGIN
    v_sid := sys_context('userenv','SID');
    v_audsid := sys_context('userenv','SESSIONID');
    p_spl := utl_agk.ins_log('test_logon_trigger', 
                                    'sid='||v_sid||'   audsid='||v_audsid,
                                    'user='||USER);
    FOR vv IN (SELECT serial# ser FROM sys.v_$session  WHERE sid =v_sid AND audsid=v_audsid)
    LOOP
        utl_agk.upd_log(p_spl, ', serial='||vv.ser);
        sys.DBMS_SESSION.SET_CONTEXT ( 'CLIENTCONTEXT', 'MYLOGONSEQ', TRIM(p_spl));
    END LOOP;
END;
/
utl_agk - это мой пакет, который в автономной транзакции пишет в протокол или корректирует уже имеющуюся запись. SET_CONTEXT я использую для передачи данных в другой свой триггер BEFORE LOGOFF ON DATABASE, но сейчас это неважно. Протокол имеет следующий вид (не все привожу, всех юзеров убрал)
SEQ_LOG DATE_BEG DATE_END PROG PARAM
92078295 30.12.2015 9:45:21 30.12.2015 9:45:22 test_logon_trigger sid=505 audsid=4294967295
92079812 30.12.2015 9:19:28 30.12.2015 9:19:28 test_logon_trigger sid=1040 audsid=301222381
92079811 30.12.2015 9:19:21 30.12.2015 9:19:21 test_logon_trigger sid=1040 audsid=301222380
92079810 30.12.2015 9:19:16 30.12.2015 9:19:16 test_logon_trigger sid=6 audsid=301222379
92079809 30.12.2015 9:19:13 30.12.2015 9:19:13 test_logon_trigger sid=505 audsid=301222378
92079808 30.12.2015 9:19:06 30.12.2015 9:19:06 test_logon_trigger sid=58 audsid=301222377
92079798 30.12.2015 9:19:01 30.12.2015 9:19:01 test_logon_trigger sid=58 audsid=301222374
92079795 30.12.2015 9:19:01 30.12.2015 9:19:09 test_logon_trigger sid=174 audsid=301222373
92079794 30.12.2015 9:19:01 30.12.2015 9:19:05 test_logon_trigger sid=505 audsid=301222372
92079800 30.12.2015 9:19:01 30.12.2015 9:19:01 test_logon_trigger sid=469 audsid=301222376
92079799 30.12.2015 9:19:01 30.12.2015 9:19:01 test_logon_trigger sid=301 audsid=301222375
92079791 30.12.2015 9:18:53 30.12.2015 9:18:53 test_logon_trigger sid=296 audsid=301222371
92079790 30.12.2015 9:18:51 30.12.2015 9:18:55 test_logon_trigger sid=505 audsid=301222370
92079789 30.12.2015 9:18:46 30.12.2015 9:18:46 test_logon_trigger sid=651 audsid=301222369
Естественно, SID повторяется, но для всех повторяющихся SID разные AUDSID, то есть это действительно разные сессии. Ну не может быть такого, чтобы триггер AFTER LOGON ON DATABASE сработал дважды в одной сесии!

Заблокировать отправку письма можно очень легко. Для этого достаточно установить в сесии при отправке письма контекстный параметр в предопределенном контексте 'CLIENTCONTEXT' и в дальнейшем отправлять письмо только если параметр не установлен. Если письма все равно будут приходить, значит сесии разные. Текст триггера такой
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE OR REPLACE TRIGGER test_log
AFTER LOGON ON DATABASE
DECLARE
  count_proc NUMBER;
  v_param     VARCHAR2(10);
BEGIN
  v_param := SYS_CONTEXT('CLIENTCONTEXT', 'LOGONMAILDISABLE');
  SELECT COUNT(*) INTO count_proc FROM v$process;
  -- IF count_proc = 64 --лимит кол-во занятых процессов представление v$process
  -- THEN 
  IF v_param IS NULL THEN
     test_maile;
     sys.DBMS_SESSION.SET_CONTEXT ( 'CLIENTCONTEXT', 'LOGONMAILDISABLE', 'YES');
  END IF;
END;
/
А оракловые администраторы Вашей базы ничего по этому поводу не говорят? У них ведь тоже есть свои возможности, трассировку посмотреть и так далее. Или лениво напрягаться?

Добавлено через 7 минут
Цитата Сообщение от alc_alc Посмотреть сообщение
2. да приходят, текст письма прост в нем указана инфа о пользователе (sid, имя)
А как Вы определяете, что это именно одна сессия? Может, все-таки текст приложите?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.12.2015, 10:19
Помогаю со студенческими работами здесь

Триггер для добавления к строке название таблицы, в которой содержится триггер
Есть таблицы База_Практик. В неё добавляю предприятие, и автоматически нужно добавить это предприятие с именем таблицы База практик в...

Триггер для добавления к строке название таблицы, в которой содержится триггер
Есть таблицы База_Практик. В неё добавляю предприятие, и автоматически нужно добавить это предприятие с именем таблицы База практик в...

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

Т-Триггер на ИЛИ-НЕ элементах и что это за триггер?
Здравствуйте. Нужно построить схему Т-Триггера через ИЛИ-НЕ элементы. Вот сам триггер ...

Secondary Logon
Проблемы с Secondary Logon В списке служб её нет. Я её не сносил. Видимо сборка такая(винды) А для работы postgresql она(служба...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru