|
|
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Возник вопрос по поводу работы триггеров уровня строки (row-level triggers). Как известно, в этих BEFORE-триггерах есть возможность обращаться к :NEW и :OLD псевдозаписям. В том числе можно изменить значение поля в :NEW-записи и оно окажется в строке таблицы вместо того, что было предусмотрено UPDATE или INSERT. В меру моего понимания, есть PL/SQL-машина (PVM). И есть SQL движок. Они вместе работают на одном уровне ядра. Уровне выполнения KX. The execution layer (KX). This layer handles the binding and execution of SQL statements and PL/SQL program units. It is also responsible for the execution of recursive calls for trigger execution, and for the execution of SQL statements within PL/SQL program units. Выполняются SQL и PL/SQL полностью раздельно. С переключением контекста SQL-PL/SQL и обратно внутри серверного процесса. Два вопроса: 1) Как заполняется NEW для BEFORE-триггера? В документации есть фраза. When a row-level trigger fires, the PL/SQL runtime system creates and populates the two pseudorecords OLD and NEW. Но ведь триггер срабатывает ДО изменений (которые дает NEW). Причем там вся вот эта кухня с мини-откатами и перезапусками. В статье Сергея Маркеленкова Алгоритм “мини-откатов” в Oracle или еще раз о Write Consistency такая схема: - в режиме согласованного чтения находим строку; - блокируем ее в текущем состоянии; - на ней срабатывает триггер (OLD-то передается в режиме согласованного чтения, а NEW-то откуда?, еще изменения-то не было); - происходит сравнение столбцов из старого (в CR-блоке) и текущего (в CURRENT-блоке) содержимого строки; - и только потом выполняется собственно изменение строки. 2) Как сделанные триггером изменения в NEW окажутся в блоках? В меру моего понимания, это может сделать только SQL. Кто именно его выполнит? Скорее всего, это делает PL/SQL-машина, которая выполнит UPDATE этой строки после окончания срабатывания всех триггеров. Не случайно в псевдозаписях есть столбец с ROWID. А строка заблокирована нами перед срабатыванием первого триггера. Верная гипотеза? Вроде больше некому. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 14:19 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
и тебе привет! я знаю кто ты :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 14:38 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
konaz_714обращаться к :NEW и :OLD псевдозаписям.Это конечный перечень bind-переменных.konaz_7142) Как сделанные триггером изменения в NEW окажутся в блоках? В меру моего понимания, это может сделать только SQL. Кто именно его выполнит? Скорее всего, это делает PL/SQL-машина, которая выполнит UPDATE этой строки после окончания срабатывания всех триггеров. Не случайно в псевдозаписях есть столбец с ROWID. А строка заблокирована нами перед срабатыванием первого триггера. Верная гипотеза? Вроде больше некому.По-твоему получается, что если триггеров нет, то изменения никогда не попадут в блоки ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 14:39 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
1) Погодите, какие связываемые переменные в строчном триггере? На каждой строке? Чьи они тогда, для какого предложения SQL? Связываемые переменные, в меру моего понимания, у того SQL, который вызвал срабатывание были, а могли и не быть. 2) Если триггера нет, то и NEW нет и изменения делает просто сам UPDATE. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 14:59 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
konaz_714Связываемые переменные, в меру моего понимания, у того SQL, который вызвал срабатывание были, а могли и не быть.Триггер - это рекурсивный SQL. konaz_7142) Если триггера нет, то и NEW нет и изменения делает просто сам UPDATE.Щаз. Два разных механизма? - Кому это надо сопровождать? Ты вообще уверен, что понимаешь основы, чтобы лезть в дебри? Да и зачем туда лезть? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 15:29 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
konaz_714Погодите, какие связываемые переменные в строчном триггере?Триггер - рекурсивный вызов PL/SQL и NEW/OLD выступает в роли интерфейса передачи параметров туда. Элементарный пример как триггеры работают при рестарте смотри тут . Про уровни и вызовы - полная каша. Если интересна последователось вызовов - воспользуйся инструментарием из ссылок wurdu в твоем предыдудем топике. Кроме того, куча профайлеров на сайте Подера. Из встроенных средст - PL/SQL tracing & dbms_hprof, но не дает такой детализации. В чем вообще цель изысканий? Конкурента Ораклу пишешь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2016, 16:22 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
ElicТриггер - это рекурсивный SQL. dbms_photoshop Триггер - рекурсивный вызов PL/SQL Вы что ребят сговорились? Рекурсия это описание себя в себе. Что-то типа: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. А запуск чего-то по событию, называется триггер, а не рекурсия. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 09:23 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 09:39 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудров, Рекурсивные вызовы . Но не рекурсивный SQL. P.S. Назвать :NEW и :OLD обращением к вызывающему оператору. Ладно пусть будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 09:46 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньева не рекурсия.RTFM ORA-00604 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 09:57 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньева не рекурсия. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Код: 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. 35. 36. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 10:08 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Elic, Заметь. Ты вызвал SQL машину из SQL машины (через триггер). Это рекурсия. тут Оракул считает именно их Код: plsql 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. Вызов PL/SQL машины из SQL (собственно триггер). За рекурсию не считается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 10:18 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
konaz_714Но ведь триггер срабатывает ДО изменений (которые дает NEW). Собственно, проблема в попытках привнести человечески язык в программирование. В конце концов это приводит к непониманию того, что реально происходит. На данную проблему надо смотреть проще. Оба вида триггеров срабатывают после наступления события (изменения) просто те которые before срабатывают гарантированно раньше тех, которые after (в пределах одного и того же типа порядок не гарантирован). А то, что по английски эта фраза значит совсем другое - так забей на английский, ты не с англичанином общаешся, а с компьютером. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 10:38 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевОба вида триггеров срабатывают после наступления события (изменения) просто те которые before срабатывают гарантированно раньше тех, которые after Серьезно?! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 10:52 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous, Не не серьезно. Только вот иначе непонятно, что такое :new.value если его еще нет и откуда RDMS его берет если событие еще не наступило? Да и триггер должен сработать на событие, а его еще нет. Так логический ряд выглядит так событие->вычисление того, что должно поменяться и на что должно поменяться->before триггера->финализация записи->after триггера. Поэтому в after и стоит запрет на изменения, потому что это те триггера в которых известно чему будет равно значение после операции (или изменения строки), а before триггера видят только промежуточный итог. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 11:19 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевandrey_anonymous, Не не серьезно. Только вот иначе непонятно, что такое :new.value если его еще нет и откуда RDMS его берет если событие еще не наступило? Если бы мсье задался вопросом про :old в before-триггере - я бы еще как-то понял сомнения, но :new - это уже перебор. :new - это переданные в insert/update данные, предназначенные для ЗАНЕСЕНИЯ в таблицу. Они пришли извне и могут быть скорректированы триггером. К примеру, для delete вы в этом :new ничего не найдете. :old - это то, содержалось в (уже обнаруженной к моменту срабатывания строчного триггера) строке до выполнения изменений. В случае insert никакого :old, понятно, не будет. Перед физическим изменением строки :new и :old уже известны однозначно и определенно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 11:26 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous:new - это переданные в insert/update данные, предназначенные для ЗАНЕСЕНИЯ в таблицу. Скорее текущее состояние. Ибо триггеров может быть чуть больше чем один. Код: plsql 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. Считать ли что update начался когда определились с тем что и на что менять или, когда изменили значение в блоке - уже вопрос физической реализации (собственно если бы не было изменений, то и не замечал бы oracle, что таблица мутировала). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 12:03 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевСкорее текущее состояние. Ибо триггеров может быть чуть больше чем один Нет. Именно то, что пришло на вход триггеру. Рассматривайте before-триггер как фильтр. Несколько триггеров - цепочка фильтров. И все станет просто. Сергей АрсеньевСчитать ли что update начался когда определились с тем что и на что менять или, когда изменили значение в блоке - уже вопрос физической реализации (собственно если бы не было изменений, то и не замечал бы oracle, что таблица мутировала). Нет. Это в первую голову вопрос логической организации процесса. Рассмотрите, к примеру, вариант с наличием ограничений уникальности или check-constraint на обновляемых полях. А до кучи - процесс обновления/удаления первичного/уникального ключа при наличии дочерних записей при различных вариантах декларации связи (ON DELETE CASCADE/SET NULL). Вопрос о "мутации таблицы" тоже не столько вопрос физической реализации, сколько логический вопрос о том, с какими записями и в каком виде будет работать строчный триггер, вызванный посреди процесса модификации неизвестного триггеру количества строк в неопределенном порядке . Весь exception - чтобы не порушить принцип атомарности, а не ограничение реализации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 13:24 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
andrey_anonymousВопрос о "мутации таблицы" тоже не столько вопрос физической реализации, сколько логический вопрос о том, с какими записями и в каком виде будет работать строчный триггер, вызванный посреди процесса модификации неизвестного триггеру количества строк в неопределенном порядке . Весь exception - чтобы не порушить принцип атомарности, а не ограничение реализации. Вот в том и дело, что процесс начат и не закончен. Даже если мы имеем дело всего с одной строкой. Если рассматривать before триггер именно, как, сработавший до начала операции, то никакой мутации бы быть не должно - ибо до изменений то нет. Но он срабатывает именно в процессе, когда результат неизвестен. И чтобы выходцы из TSQL (и прочие) не наваяли несуразного и присутствует exception. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 17:30 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевЕсли рассматривать before триггер именно, как, сработавший до начала операции, то никакой мутации бы быть не должно - ибо до изменений то нет. Но он срабатывает именно в процессе, когда результат неизвестен. И чтобы выходцы из TSQL (и прочие) не наваяли несуразного и присутствует exception. Вы точно хорошо помните как и при каких условиях срабатывает "мутация"? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 17:44 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous, При попытке из row level триггера узнать содержимое изменяемых строк. В силу того, что триггер написан на PL читать содержимое блока он не может, он запускает новый sql. который срабатывает на другой scn. А значение на этот scn в рамках этой же транзакции СУБД определить не может. Ибо действия в пределах одной операции Оракул помечать разными моментами времени не хочет - накладно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 18:44 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевВ силу того, что триггер написан на PL читать содержимое блока он не может, он запускает новый sql. который срабатывает на другой scn. А значение на этот scn в рамках этой же транзакции СУБД определить не может. Ибо действия в пределах одной операции Оракул помечать разными моментами времени не хочет - накладно.Пошёл откровенный бред... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 18:57 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевandrey_anonymous:new - это переданные в insert/update данные, предназначенные для ЗАНЕСЕНИЯ в таблицу. Скорее текущее состояние. Ибо триггеров может быть чуть больше чем один. Код: plsql 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. Считать ли что update начался когда определились с тем что и на что менять или, когда изменили значение в блоке - уже вопрос физической реализации (собственно если бы не было изменений, то и не замечал бы oracle, что таблица мутировала).До 11 порядок срабатывания триггеров был неопределен. Потом появилось FOLLOWS . При чем здесь мутация? Сергей АрсеньевВ силу того, что триггер написан на PL читать содержимое блока он не может, он запускает новый sqlТриггеру вообще не надо читать блоки! В него передается то, что необходимо. А вообще неожиданно читать такие фантазии после того как был упомянут необходимый инструментарий. Все вызовы SQL можно отловить трассой 10046, но это ж надо было такое придумать! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 19:31 |
|
||
|
Вопрос про :NEW-псевдозапись в BEFORE-триггере
|
|||
|---|---|---|---|
|
#18+
dbms_photoshopТриггеру вообще не надо читать блоки! В него передается то, что необходимо. Ну чтобы отловить мутацию - таки надо читать блоки :) Другой вопрос, что уважаемый визави нафантазировал тут с три короба - но то такое... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2016, 19:42 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39321316&tid=1887306]: |
0ms |
get settings: |
7ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
181ms |
get topic data: |
6ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
| others: | 216ms |
| total: | 486ms |

| 0 / 0 |
