|
|
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Ты путаешь INSTEAD OF триггер (на VIEW) и COMPAUND триггер. Последний -- это просто объединение триггеров на разные события в одном куске кода, что удобней при использовании например локальных PL/SQL коллекций для обхода той же мутации. Типо: в секции BEFORE STATEMENT заполняешь коллекцию текущим состоянием, а затем в секциях BEFORE/AFTER EACH ROW проверяешь не нарушает ли условие конкретная запись (на основании коллекции, чтоб не лезть в таблицу). При этом ты, естественно, не видишь изменений других сеансов (добавленных строк, например) и если не предусмотрена какая-либо сериализация (та же блокировка родительской записи) -- все твоя проверка может пойти лесом ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 10:53 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудровcreate trigger contr_trg before insert or update on contractиспользовать триггер для проверки допустимости значения очень однопло. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 10:58 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Не спорю, CHECK намного лучше А еще и индекс на FOREIGN KEY построить Но это таки пример -- вводить и объяснять новые понятия нет желания ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 11:02 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenВячеслав Любомудров, Спасибо. Я понял Вашу мысль. Любое изменение в платежах нужно с помощью триггера отразить в дополнительном поле в контрактах. Если сумма превышает, то тогда и происходит исключение. ОК. Если не найду другое решение, то так и сделаю. только внимательней со своим кодом, а то апдейт фк может не сработать, как мне показалось Код: plsql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 11:10 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав ЛюбомудровТы путаешь INSTEAD OF триггер (на VIEW) и COMPAUND триггер. Последний -- это просто объединение триггеров на разные события в одном куске кода, что удобней при использовании например локальных PL/SQL коллекций для обхода той же мутации. Типо: в секции BEFORE STATEMENT заполняешь коллекцию текущим состоянием, а затем в секциях BEFORE/AFTER EACH ROW проверяешь не нарушает ли условие конкретная запись (на основании коллекции, чтоб не лезть в таблицу). При этом ты, естественно, не видишь изменений других сеансов (добавленных строк, например) и если не предусмотрена какая-либо сериализация (та же блокировка родительской записи) -- все твоя проверка может пойти лесом Ну допустим, пользователь по конкретному контракту только 1, в смысле если я ввожу данные по одному контракту, то никто параллельно в этот момент не работает с данным контрактам. Соответственно, исключаем возможность других сеансов по конкретной записи. Или другой пример. Допустим я единственный пользователь базы. Т.е. пусть даже триггер не видит, что делают другие пользователи, а имеет дело только с конкретным пользователем. Я хочу исправить сумму платежа на большую и тут триггер должен меня остановить сообщив об ошибке. Неужели триггер на изменение никак не может просмотреть всю таблицу только по данному контракту? Неужели в корпорации ORACLE не предусмотрели такой поворот событий? Почему то в MS SQL Server нет таких проблем вообще. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 11:16 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenПочему то в MS SQL Server нет таких проблем вообще. MS SQL - тупой блокировочник. Фактически, он работает в однопользовательском режиме. Поэтому у него нет проблем с конкурентным доступом к данным. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 12:31 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovstudierenПочему то в MS SQL Server нет таких проблем вообще. MS SQL - тупой блокировочник. Фактически, он работает в однопользовательском режиме. Поэтому у него нет проблем с конкурентным доступом к данным. Я с Вами не согласен. В MS SQL Server с одной таблицей могут работать сразу несколько пользователей и при этом триггер спокойно видит все сохранённые данные. Да, там тоже может быть блокировка, но как правило, так происходит если 2 пользователя правят одну и ту же запись. Вот тогда тот, кто успел первым сохранить, то его данные и будут в базе. А у второго - ошибка блокировки. Но на практике одну и ту же запись 2 пользователя почти никогда не правят. Поэтому кто тупой, MS SQL Server или ORACLE в данном вопросе очень и очень спорно! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 12:41 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
dba123studierenВячеслав Любомудров, Спасибо. Я понял Вашу мысль. Любое изменение в платежах нужно с помощью триггера отразить в дополнительном поле в контрактах. Если сумма превышает, то тогда и происходит исключение. ОК. Если не найду другое решение, то так и сделаю. только внимательней со своим кодом, а то апдейт фк может не сработать, как мне показалось Код: plsql 1. Все, заклевали Нафиг я сюда вообще влез studierenНу допустим, пользователь по конкретному контракту только 1, в смысле если я ввожу данные по одному контракту, то никто параллельно в этот момент не работает с данным контрактам. Соответственно, исключаем возможность других сеансов по конкретной записи. Или другой пример. Допустим я единственный пользователь базы.Такие допущения надо чем-то обеспечить studierenПочему то в MS SQL Server нет таких проблем вообще.Просто они разные Когда ты изменяешь несколько строк одним оператором и пытаешься (в триггере для каждой обновленной строки) например, подсчитать сумму в этих строках, то возникает вопрос, на какой момент времени брать значения? Точнее даже какой именно из возможных -- ты не можешь управлять порядком обновления/удаления/вставки строк (при многострочной обработке) и при другом порядке (который выбирает Oracle) результат будет другой. Возьмем твой пример -- ограничить сумму в 1500 Пусть у нас есть строки со значениями: 1000, 500, -1000 Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3 То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п. Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо Вот от такой неоднозначности тебя Oracle и страхует ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 12:51 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудров, Дык он студент вроде, кто знает, что он там напишет :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 12:56 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenВ MS SQL Server с одной таблицей могут работать сразу несколько пользователей и при этом триггер спокойно видит все сохранённые данные. Уверен? Проверь на своей схеме следующий сценарий: 1) Сессия 1 стартует транзакцию 2) Сессия 2 стартует транзакцию. 3) Сессия 1 добавляет к документу строку, полностью выбирающую лимит. 4) Сессия 2 добавляет к тому же документу вторую строку, полностью выбирающую лимит. 5) Сессия 1 коммитится. 6) Сессия 2 коммитится. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 13:05 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
пардон, если баян - тему читал по оч. большой диагонали studieren, в sql оракловом есть несколько функций каждой из которых достаточно, для создания подходящего вашей теме проверочного констрейнта например, ltrim(ляля,'0123456789') is null ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 13:51 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
orawishпардон, если баян - тему читал по оч. большой диагонали studieren, в sql оракловом есть несколько функций каждой из которых достаточно, для создания подходящего вашей теме проверочного констрейнта например, ltrim(ляля,'0123456789') is null Ту проблема я уже решил с помощью regexp_like (спасибо товарищам за подсказку). Теперь у меня совсем другая проблема. Когда пользователь правит какую-либо таблицу (мутирующая таблица), то мне необходимо ставить такое ограничение, которое проверяет все записи мутирующей таблицы и если что не так, то запрещает внесение изменений. При этом даже если предположить, что где-то другой пользователь пытается внести изменение в данную таблицу, то эти изменения игнорировать если данные фактически ещё НЕ СОХРАНЕНЫ! Как это сделать? Не пойму. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 15:10 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудров... Возьмем твой пример -- ограничить сумму в 1500 Пусть у нас есть строки со значениями: 1000, 500, -1000 Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3 То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п. Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо Вот от такой неоднозначности тебя Oracle и страхует В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так. А вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 15:16 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenВячеслав Любомудров... Возьмем твой пример -- ограничить сумму в 1500 Пусть у нас есть строки со значениями: 1000, 500, -1000 Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3 То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п. Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо Вот от такой неоднозначности тебя Oracle и страхует В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так. А вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ. ты откуда ж такого фееричного бреда понабрал-то... а про мутирующие таблицы тебе уже 2 страницы разжевывают. пишет и пишет, говорят ему доку открой, "ну-не-пойму-я" заклинило :). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 15:38 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenВячеслав Любомудров... Возьмем твой пример -- ограничить сумму в 1500 Пусть у нас есть строки со значениями: 1000, 500, -1000 Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3 То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п. Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо Вот от такой неоднозначности тебя Oracle и страхует В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так. Ты нихрена не понял Вопрос в непредсказуемости результата studierenА вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ.Какое-то извращенное понятие, можно подумать БД разбирается -- обычный это юзер или "специалист ИТ" На одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибки Именно потому, что результат детерминирован ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 15:44 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenВ MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Вот только твой триггер не даст "сбой". Сценарий я описал выше. Триггерами можно обеспечить целостность группы записей только на уровне изоляции DIRTY READ. Которого в Oracle нет. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 15:51 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovТриггерами можно обеспечить целостность группы записей только на уровне изоляции DIRTY READ. Которого в Oracle нет. целостность и dirty read. целостность можно обеспечить при любом уровне изоляции, кроме dirty read. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:00 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov, ОК. Вот ещё одна проблема. Я должен хранить серийные номера "от" и "до" в разных полях/столбцах. При этом серийные номера не в коем случае не должны пересекаться. Скажем, в таблице есть такие данные: От До1 1020 30 Если я попытаюсь ввести диапазон 7 и 11 программа должна ругаться, так как внутри диапазона 1 и 10 уже есть хотя бы как минимум 1 элемент из 7 и 10. Неужели в ORACLE я не смогу создать такой запрет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:05 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenНеужели в ORACLE я не смогу создать такой запрет? Сможешь. Но работать правильно он будет исключительно в однопользовательском режиме. Как и в любой другой СУБД кроме тех, которые выше DIRTY READ ничего не умеют. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:12 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenТ.е. пусть даже триггер не видит, что делают другие пользователи, а имеет дело только с конкретным пользователем. В этом то вся и проблема. В этом самом конкретном пользователе. Другие фиг с ними - он не закоммитились - их нет. Oracle версионник. А это значит, что он не возвращает данные, которые есть в базе. Он возвращает данные на какой-то момент времени (иногда оп выбору иногда на усмотрение сервера). Основная операция еще не завершилась - поэтому ее результата еще нет. И в том числе для триггера. Если так сделать Вы же первый взвоете - какого черта? Ну и в большинстве случаев подобный подход, когда проверяется верность несогласованного набора данных, чаще всего нужно тем, кто хочет совершить ошибку. Поэтому Oraclke СУБД и выплевывает ошибку в этот момент. Простой пример. Вы всегда хотите, чтобы сумма чего-то разложенного по полкам была равна константе. Тогда Вы не сможете одной операцией увеличить значение на одной полке и уменьшить на другой, если будете проверять сумму по ходу операции. Для этого надо проверять сумму после операции. О чем и сигнализирует ошибка. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:20 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
studierenНеужели в ORACLE я не смогу создать такой запрет? Можешь. Но делается это иначе. Делается мат вью, которое возвращает количество пересекающихся интервалов, обновляемое по commit. И constraint который не позволяет количеству пересекающихся интервалов быть больше 0. Одна проверка на транзакцию. Не на каждое изменение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:25 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Ну или iot табличку с уникальными номерами (вставляем для всего диапазона). Заодно можно получить отлуп (взаимная блокировка), если кто-то еще пытается вместе с вами работать в том же направлении. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:30 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав ЛюбомудровНа одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибкиВставках. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:31 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
ElicВячеслав ЛюбомудровНа одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибкиВставках.Упс... Точно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.04.2016, 16:43 |
|
||
|
Перевод из MS SQL Server в ORACLE
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудров, Прочёл книжку "ORACLE PL/SQL Как писать мощные и гибкие программы на PL/SQL" Кристофер Аллен. Там нашёл ответ на свою проблему. Вот отрывок: Когда триггер пытается прочитать таблицу, а затем записать в нее данные, возбуждается исключение "мутирующей таблицы". Хотя намерение ограничить действия такого типа вполне объяснимо, корпорация Oracle зашла в этом дальше, чем необходимо, запретив операции, при которых таблица просто блокируется, а не изменяется. Один из способов обойти эту проблему заключается в том, чтобы создать вторую таблицу с копиями столбцов, которые триггер должен прочитать из главной таблицы. В этом случае триггер получает необходимые значения из второй таблицы, а затем выполняет запланированные действия с первой таблицей. При реализации данного подхода важно обеспечить синхронизацию таблиц. Для этого все операции INSERT, UPDATE и DELETE над главной таблицей должны отражаться триггером на второй таблице. Т.е. создаю таблицу точь в точь с "оригиналом", туда добавляю все изменения (вставка, изменение, удаление). Все необходимые мне проверки провожу во второй таблице. Ну если это единственный способ, что поделать! Буду так. Но я в шоке от корпорации ORACLE. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.04.2016, 09:19 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39222588&tid=1886761]: |
0ms |
get settings: |
10ms |
get forum list: |
20ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
199ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
89ms |
get tp. blocked users: |
2ms |
| others: | 240ms |
| total: | 585ms |

| 0 / 0 |
