![]() |
|
Модераторы: Akella |
![]()
|
|
| Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Доброго времени суток!
Вдохновившись статьей на RSDN'е, решил попробовать реализовать версионность средствами Firebird. Реализовал следующую модель: Две таблицы, первая хранит данные, а вторая хранит предыдущее значение, дату изменения и пользователя, который изменил значение. Мультики начались при попытке осуществить предложенным в статье методом версионирование при удалении данных. Автор статьи предлогает ввести дополнительное поле - флаг удаления и при удалении записи запрещать удаление записи, а вместо этого поднимать флаг (например значением IsDeleted). Проблема в том, что как я не пытался я не смог создать триггер, который одновременно и запрещал удаление и в тоже время вносил какие либо изменения в БД. Т.о. прихожу к выводу, что реализовать в Firebird модель версионирования, при которой бы удаление заменялось на изменение флага (признака) удаления не получится. Вижу несколько вариантов. Например можно все DELET'ы записей заменить на их UPDATE'ы... Но мне это не совсем нравится (почему то). Второй вариант заключается в том, что бы для удаленных записей создать отдельную таблицу, и при удалении переносить запись из таблицы неудаленных данных в таблицу удаленных. Вопросы: хотелось бы услышать, приходилось ли кому сталкиваться с версионированием и как это было реализовано? -------------------- Слава Україні! |
|||
|
||||
| Deniz |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 22 Всего: 44 |
Один из вариантов, создать вьюшку на таблицу (запретить весь доступ к таблице), на нее триггеры, и в триггере можно делать что угодно. В других СУБД такие триггеры называются "instead of" (вроде пока таких в FB нет, поправьте если не так)
Второй вариант, завернуть все операции в хранимые процедуры. -------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
||||
|
||||
| Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Если коротко, то... Что бы отменить удаления я должен сгенерировать исключение, при вызове исключения, если его не обработать, все операции выполненные в триггере откатываются (т.е. нет возможности внести updeate флага признака удаления), а если обработать исключение, то удаление не отменяется (т.е. происходит удаление той(тех) записей для которых вызван delete)... Пытался разнести операции отмены удаления и обновления флага по триггерам before- и after- , но безрезультатно. На сколько я понял, то причина в том, что триггер after- не видит запись, которая удаляется. Это сообщение отредактировал(а) Gluttton - 28.10.2009, 18:47 -------------------- Слава Україні! |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
Ну да, я так и предполагал.
|
|||
|
||||
| Gluttton |
|
||||||||||||||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Можно конечно же, но... Точно так же можно заменить удаление обновлением... Не совсем то, что хотелось бы Как
Что не получится Вот как я делал... Пусть есть таблица с исходными данными - SC:
STATE - состояние ('NoD' - не удалено, 'IsD' - удалено). Пусть нам необходимо отслеживать изменения поля FIELD, для этого есть таблица истории - HS:
OWNER - имя пользователя, который внес изменения, D и T дата и время изменения, ACT - действие (удаление, обновление), RECORD - старое значение поля SC.FIELD, а FIELD - внешний ключ SC.ID. Создадим триггер на обновление:
Работает как часики А теперь пробую создать триггеры на удаление, для этого потребуется создать исключение:
Первый триггер:
Второй триггер:
При попытке удалить запись из исходной таблицы отмена удаления срабатывает, а обновления и логгирования не происходит... На всякий случай скрипт тестовой БД. Это сообщение отредактировал(а) Gluttton - 28.10.2009, 22:51 Присоединённый файл ( Кол-во скачиваний: 5 )
TRC.sql 5,59 Kb-------------------- Слава Україні! |
||||||||||||||
|
|||||||||||||||
| Deniz |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 22 Всего: 44 |
Gluttton, вроде уже говорил, но повторюсь.
используй одно поле в этом случае
Добавлено через 4 минуты и 30 секунд Gluttton, сделал у себя тест с вьюхой см. вложение. для сервера версии 1.5 Запрос во вьюхе необходимо сделать необновляемым, иначе триггер на удаление удаляет запись в таблице sc Присоединённый файл ( Кол-во скачиваний: 7 )
src.sql 4,11 Kb-------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
так как удаление выполняется в рамках одной транзакции, то при вызове исключения транзакция будет откачена, что повлечёт за собой и откат действий по записи данных в другую таблицу Добавлено через 1 минуту и 31 секунду
и я о том же |
|||
|
||||
| Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Deniz,
Спасибо за скрипт! Akella, Т.е. это безисходность? Триггер на уделение, выполняющий любое действие вместе с отменой удаления, никак не создать? Тогда думаю будет симпатичнее создать таблицу для хранения удаленных записей, т.е. триггеру прийдется не отменяя удаление копировать удаленную запись в другую таблицу (в которой хранятся удаленные записи)... -------------------- Слава Україні! |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
Ну в версии 2,5 ввели автономные транзакции.
|
|||
|
||||
| Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Akella, спасибо за ценный совет
Используя автономные транзакции сумел одним триггером и внести записть в таблицу истории (логов) и отменить само удаление! Но! Изначально задумывалось так, что при удалении запись в исходной таблице не удаляется, а помечается как удаленная. Так вот изменить (выполнить UPDATE) с той записью, которая удаляется никак не получается, т.к. до вызова исключения она удалена, а после вызова исключения уже ничего не выполняется... Вот это уже безисходность -------------------- Слава Україні! |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
1. В автономной транзакции помечай запись, как удалённую.
2. Вызывай исключение. В итоге, запись будет помечена, как удалённая. И удалена не будет. |
|||
|
||||
| Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Akella,
Ну честное слово вчера пробовал, не получалось! Сегодня, хотел повторить, что бы всё грамотно описать, что не получается, а тут бац - и всё работает! Итак по сути... Тема закрыта Для тех, кого в эту ветку приведет поиск, выкладываю конечный вариант скрипта для Firebird 2.5 (не эталон, но для примера, думаю, сгодится Присоединённый файл ( Кол-во скачиваний: 16 )
TRC.sql 5,43 Kb-------------------- Слава Україні! |
|||
|
||||
![]()
|
| Правила форума "Interbase" | |
|
|
Обязательно указание: 1. Версию InterBase (Firebird, Yaffil) 2. Способа доступа (ADO, BDE, IBX и т.д.)
Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Firebird, Interbase | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |