Модераторы: LSD
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> конкуренция при вставке строки 
:(
    Опции темы
kora
  Дата 7.12.2006, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 7.12.2006

Репутация: нет
Всего: нет



Есть следующая проблема:
Имеется таблица, в которую поступают данные - произвольный набор алфавитных символов, набор должен состоять не меньше чем из N символов. В таблице не должны содержаться наборы символов, которые включают в себя уже существующие в таблицы наборы. Т.е. если в таблице есть набор "абвгд", то не должно существовать набора "ХабвгдХ". Данные в таблицу поступают асинхронно. Подскажите наиболее предпочитаемый вариант.
PM MAIL   Вверх
Sqlninja
Дата 7.12.2006, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Код

CREATE TABLE t(f VARCHAR2(30));

INSERT INTO t
     VALUES ('maska'
            );

CREATE OR REPLACE TRIGGER t_check
   BEFORE INSERT
   ON t
   FOR EACH ROW
DECLARE
   CURSOR c
   IS
      SELECT 1
      FROM   t
      WHERE  :NEW.f LIKE '%' || :OLD.f || '%';

   a   INT;
BEGIN
   OPEN c;

   FETCH c
   INTO  a;

   IF c%FOUND
   THEN
      CLOSE c;

      raise_application_error (num      => -20000, msg => 'Cannot insert row.');
   END IF;
END;

INSERT INTO t
     VALUES ('ask'
            );




--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
kora
Дата 7.12.2006, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 7.12.2006

Репутация: нет
Всего: нет



Спасибо, за ответ!
А есть ли более "универсальное" решение для подобного рода задач. Просто эта задача тривиальная (вычисления вложений), а может понадобится прощёты намного сложнее, выходящие за рамки возможностей оракла.
PM MAIL   Вверх
LSD
Дата 7.12.2006, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 18
Всего: 538



Я бы написал процедуру для вставки данных в таблицу, и разрешил бы вставлять данные только через нее. Вначале lock table, затем проверка что таких данных нет, insert и commit.

Sqlninja, что-то я не пойму твой триггер. После него даже такой insert не проходит:
Код
INSERT INTO t VALUES ('ddd');

И вообще, разве :OLD доступно в триггере BEFORE INSERT?


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sqlninja
Дата 7.12.2006, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Исправил smile

Код

CREATE TABLE t(f VARCHAR2(30));

INSERT INTO t
     VALUES ('maska'
            );

CREATE OR REPLACE TRIGGER t_check
   BEFORE INSERT
   ON t
   FOR EACH ROW
DECLARE
   CURSOR c
   IS
      SELECT 1
      FROM   t
      WHERE  f LIKE '%' || :NEW.f || '%';

   a   INT;
BEGIN
   OPEN c;

   FETCH c
   INTO  a;

   IF c%FOUND
   THEN
      CLOSE c;

      raise_application_error (num      => -20000, msg => 'Cannot insert row.');
   END IF;
END;
/
INSERT INTO t
     VALUES ('ask'
            );
INSERT INTO t
     VALUES ('www'
            );



Если вам нужно проделать сложные вычисления напишите внешнюю процедуру на С или Java, и пусть триггер ее дергает. Кроме того, сам триггер может быть написан на Java. Так что для Oracle нет ничего невозможного.

Это сообщение отредактировал(а) Sqlninja - 7.12.2006, 13:11


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
LSD
Дата 7.12.2006, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 18
Всего: 538



Цитата(Sqlninja @  7.12.2006,  13:08 Найти цитируемый пост)
Исправил

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

Есть конечно хороший вариант, с функциональными индексами, но они далеко не всегда применимы.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sqlninja
Дата 7.12.2006, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Делаем процедуру вставки автономной транзакцией, получаем автоматическую блокировку + триггер все видит.


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
LSD
Дата 7.12.2006, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 18
Всего: 538



Можно и триггер объявить автономным, но он все равно не увидит незакомиченные данные.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sqlninja
Дата 7.12.2006, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



Триггер как раз не нужно делать автономным. Автономной делаем ПРОЦЕДУРУ ВСТАВКИ
Код

CREATE OR REPLACE PROCEDURE t_ins (
   p_f   IN   VARCHAR2
)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   INSERT INTO t
        VALUES (p_f
               );

   COMMIT;
END t_ins;


которая делает commit в случае успешного завершения. Так что при следующей вставке триггер все прекрасно увидит.


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
LSD
Дата 7.12.2006, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 18
Всего: 538



ОК, такой сценарий:
- первая сессия вставляет данные в таблицу, триггер проверяет есть ли похожие строки в таблице и не находит их, первая сессия на время приостанавливается
- вторая сессия вставляет данные в таблицу, триггер проверяет есть ли похожие строки в таблице и не находит их
- далее отрабатывают две вставки в таблицу от обоих сессий и мы имеем нарушение целостности


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
kora
Дата 8.12.2006, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 7.12.2006

Репутация: нет
Всего: нет



Спасибо всем, за проявленный интерес. Были сделаны соовтетствующие выводы по поводу решения данной задачи.
PM MAIL   Вверх
Sqlninja
Дата 8.12.2006, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13



LSD, что-то я тебя не пойму. Триггер выстреливает исключение, транзакция не начнется. Всё! 

Цитата(LSD @  7.12.2006,  18:58 Найти цитируемый пост)
первая сессия на время приостанавливается

Нет. Ну с каких делов ей приостанавливаться?

Цитата(LSD @  7.12.2006,  18:58 Найти цитируемый пост)
вторая сессия вставляет данные в таблицу, триггер проверяет есть ли похожие строки в таблице и не находит их

Происходит абсолютно тоже самое.

Цитата(LSD @  7.12.2006,  18:58 Найти цитируемый пост)
далее отрабатывают две вставки в таблицу от обоих сессий 

Ничего далее отрабатывать не будет. При выбросе исключения транзакции не превращаются в отложенные и в очередь не ставятся чтобы когда-то там далее выполниться. RTFM.


--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
LSD
Дата 8.12.2006, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 18
Всего: 538



Цитата(Sqlninja @  8.12.2006,  10:46 Найти цитируемый пост)
Триггер выстреливает исключение, транзакция не начнется. Всё! 

Транзакция начнется при попытке вставить данные.

Цитата(Sqlninja @  8.12.2006,  10:46 Найти цитируемый пост)
Нет. Ну с каких делов ей приостанавливаться?

Да мало ли почему. Закончился тик для данного треда, нужно подгрузить процедуру в кеш или еще что. При многопоточной работе, никогда нельзя с уверенностью сказать когда будет произведено переключение тредов. Единственная возможность как-то упорядочить выполнение потоков, это их синхронизация.

Я вообще, что-то запутался, что именно ты предлагаешь. Как ты предлагаешь пользователю вставлять данные в таблицу, прямым инсертом или процедурой?


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sqlninja
Дата 8.12.2006, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 353
Регистрация: 15.5.2006
Где: San Francisco, CA

Репутация: 13
Всего: 13




Цитата(LSD @  8.12.2006,  12:56 Найти цитируемый пост)
Единственная возможность как-то упорядочить выполнение потоков, это их синхронизация.

Если на сервере (а речь идет о серверной логике) правильно организовать транзакции, то никакие потоки упорядочивать не надо, в оракле это уже сделано без нас. Можно конечно и ядро оракла переписать, но нафига...

Цитата(LSD @  8.12.2006,  12:56 Найти цитируемый пост)
Как ты предлагаешь пользователю вставлять данные в таблицу, прямым инсертом или процедурой? 


Процедурой. Там даже выше есть ее код. Да какая уже разница, автор уже выводы сделал по ходу. 




--------------------
It's better to burn out than to fade away.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Oracle"
Zloxa
LSD

Данный раздел предназначен для обсуждения проблем с Oracle Database, другие продукты Oracle здесь не обсуждаются. Просьба при создании темы, придерживаться следующих правил:

  • при создании темы давайте ей осмысленное название, описывающее суть проблемы
  • указывайте используемую версию базы, способ соединения и язык программирования
  • при ошибках обязательно приводите код ошибки и сообщение сервера
  • приводите код в котором возникла ошибка, по возможности дайте тестовый пример демонстрирующий ошибку
  • при вставке кода используйте соответсвующие теги: [code=sql] [/code] для подсветки SQL и PL/SQL кода, [code=java] [/code] - для Java, и т.д.

  • документация по Oracle: 9i, 10g, 11g
  • книги по Oracle можно поискать здесь
  • действия модераторов можно обсудить здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, LSD.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Oracle | Следующая тема »


 




[ Время генерации скрипта: 0.0864 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.