powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задачка
25 сообщений из 145, страница 5 из 6
Задачка
    #33324624
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересно, никто не пробовал решить подобную задачу на блокировочнике?
На грязном чтении?
...
Рейтинг: 0 / 0
Задачка
    #33327649
Stax.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanИнтересно, никто не пробовал решить подобную задачу на блокировочнике?
На грязном чтении?
Меня убедили, что в оракле нет грязного чтения
Можете привести пример когда есть?

.......
Stax
...
Рейтинг: 0 / 0
Задачка
    #33327739
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Stax

Он о другом, посмотри в профиль. Пытается показать что в данной задаче MS SQL круче, поскольку обеспечивает грязное чтение
...
Рейтинг: 0 / 0
Задачка
    #33327741
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sorry DB2 конечно
...
Рейтинг: 0 / 0
Задачка
    #33328216
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Данную задачу блокировочники действительно решают получше.
...
Рейтинг: 0 / 0
Задачка
    #33328292
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Грязное чтение это не решение
...
Рейтинг: 0 / 0
Задачка
    #33328321
Падонак
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanДанную задачу блокировочники действительно решают получше.
пашутил?
...
Рейтинг: 0 / 0
Задачка
    #33328352
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanДанную задачу блокировочники действительно решают получше.

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

Поясню на сценарии. Пусть сессии С1 и С2 добавляют в уникальный индекс одинаковый ключ К. Почучаем вот что:

1. С1 insert К. Ok.
2. С2 insert К. Wait
3. С1 commit
4. С2 ORA-00001: unique constraint violated

На шаге 2 С2 "видит", что в индексе присутствует ключ К, который добавила С1, но ещё не завершила транзакцию.
...
Рейтинг: 0 / 0
Задачка
    #33328427
Stax.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenab gardenmanДанную задачу блокировочники действительно решают получше.

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

Поясню на сценарии. Пусть сессии С1 и С2 добавляют в уникальный индекс одинаковый ключ К. Почучаем вот что:

1. С1 insert К. Ok.
2. С2 insert К. Wait
3. С1 commit
4. С2 ORA-00001: unique constraint violated

На шаге 2 С2 "видит", что в индексе присутствует ключ К, который добавила С1, но ещё не завершила транзакцию.

Нужен пример индекса,
какой создаете?

......
Stax
...
Рейтинг: 0 / 0
Задачка
    #33328522
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax. mcureenab gardenmanДанную задачу блокировочники действительно решают получше.

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

Поясню на сценарии. Пусть сессии С1 и С2 добавляют в уникальный индекс одинаковый ключ К. Почучаем вот что:

1. С1 insert К. Ok.
2. С2 insert К. Wait
3. С1 commit
4. С2 ORA-00001: unique constraint violated

На шаге 2 С2 "видит", что в индексе присутствует ключ К, который добавила С1, но ещё не завершила транзакцию.

Нужен пример индекса,
какой создаете?

......
Stax

create unique index ...

Ещё добавлю, что статистика Current Gets это ничто иное, как чтения текущих состояний блоков, т.е. состояний которые могут включать изменения созданые незавершёнными транзакциями. Статистика Consistent Gets это чтения блоков по состоянию на определённый момет времени, которые включают изменения только из завершенных к этому моменту времени транзакций.
...
Рейтинг: 0 / 0
Задачка
    #33328555
Stax.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabcreate unique index ...

Звиняйте, не точно задал вопрос,
интересует как укажите по чем индекс,
если грубо то по каких полях?

.......
Stax
...
Рейтинг: 0 / 0
Задачка
    #33328561
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поскольку в задече речь идёт о триггере, то может быть не в тему.

добавляем колонку:

num integer; -- Номер записи с одинаковым dept и name.

создаём ограничение целостности

check(num between 1 and 3)

-- замечу, что тип колонки integer, тоже содержит неявное ограничение, т.е. мы не можем сохранить, например 1.3.

создаём ограничение целостности

unique (dept, name, num)

теперь в таблицу с колонками (dept, name, num) можно вставить не более трёх записей с одинаковым значением (dept, name).

Как вычислить в триггере значение num, это уже другой вопрос. Один из вариантов, использовать дополнительную таблицу со счётчиком уже обсуждался тут.
...
Рейтинг: 0 / 0
Задачка
    #33328673
Stax.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabКак вычислить в триггере значение num, это уже другой вопрос
Это не другой, а главный вопрос,
имхо, пронумеровать не так просто

......
Stax
...
Рейтинг: 0 / 0
Задачка
    #33328810
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax. mcureenabКак вычислить в триггере значение num, это уже другой вопрос
Это не другой, а главный вопрос,
имхо, пронумеровать не так просто

......
Stax

Во истину, мы не ищем лёгких путей! Неужели от 1 до 3х посчитать так сложно?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
for i in  1 .. 3  loop
    begin
        insert into t (..., num) values (..., i);
        retun i;
    exception
    when dup_val_on_index then null;
    end;
end loop;
return  0 ;


Это конечно не триггерный вариант и далеко не самый оптимальный, но он тоже работает.

Придумать бы, чтобы одновременно три сессии могли скоординированно получить уникальные значения num и не мешая друг другу произвести вставку...
...
Рейтинг: 0 / 0
Задачка
    #33329093
Stax.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenab Stax. mcureenabКак вычислить в триггере значение num, это уже другой вопрос
Это не другой, а главный вопрос,
имхо, пронумеровать не так просто

......
Stax

Во истину, мы не ищем лёгких путей! Неужели от 1 до 3х посчитать так сложно?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
for i in  1 .. 3  loop
    begin
        insert into t (..., num) values (..., i);
        retun i;
    exception
    when dup_val_on_index then null;
    end;
end loop;
return  0 ;


Это конечно не триггерный вариант и далеко не самый оптимальный, но он тоже работает.

Придумать бы, чтобы одновременно три сессии могли скоординированно получить уникальные значения num и не мешая друг другу произвести вставку...
мне нравится последний абзац,
мне лично придумать сложно
......
Stax
...
Рейтинг: 0 / 0
Задачка
    #33329162
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот кому решение без триггера! Чистый FBI!
Elic, мой приз еще здесь?
К сожалению, "скоординировать" три сессии и мне не удалось, хотя... думаю, если хорошо извратить сущность dbms_lock, то все у нас получится :)

Код: plaintext
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.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
Connected to Oracle9i Enterprise Edition Release  9 . 2 . 0 . 7 . 0  
set serveroutput off
set echo on

create global temporary table ane_test_tmp( nom_otd number not null
                                          , name1 varchar2( 300 ) not null
                                          , inc number
                                          )
                              on commit delete rows;
Table created

create table ane_test( nom_otd number not null -- номер отдела
                     , name1 varchar2( 300 ) not null -- фамилия
);
Table created

create or replace package ane_test_p as
 function f( p_nom_otd number
           , p_name1 varchar2
           ) return varchar2
           deterministic;
end ane_test_p;
/
Package created
sho err
No errors for PACKAGE ANE_TEST_P

create or replace package body ane_test_p as
 upd_stage pls_integer :=  0 ;
 function get_persistent ( p_nom_otd number, p_name1 varchar2
                         ) return number deterministic
                         is pragma autonomous_transaction;
   cnt number;
 begin
   select count(*)
   into cnt
   from ane_test
   where nom_otd=p_nom_otd
     and name1=p_name1;
   return cnt;
 end;

 function calc_key (p_nom_otd number, p_name1 varchar2, offset number) return varchar2 is
 begin
   return p_nom_otd||'/#/'||p_name1||'/#/'||offset;
 end;

 function f( p_nom_otd number
           , p_name1 varchar2
           ) return varchar2
           deterministic is
   pers_cnt number;
   temp_cnt number;
   rzt varchar2( 2000 );
 begin
   select nvl(sum(inc), 0 )
   into temp_cnt
   from ane_test_tmp
   where nom_otd=p_nom_otd and name1=p_name1;

   pers_cnt := get_persistent(p_nom_otd, p_name1);

   if inserting then
     dbms_output.put_line('FBI: INSERTING: p_nom_sotr='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
     if pers_cnt + temp_cnt >=  3  then
       rzt := calc_key(p_nom_otd, p_name1, 1 ); -- DUP_VAL_ON_INDEX
       dbms_output.put_line('FBI: INSERTING: too many, key='||rzt);
     else
       rzt := calc_key(p_nom_otd, p_name1,pers_cnt + temp_cnt +  1 );
       dbms_output.put_line('FBI: INSERTING: OK, key='||rzt);
     end if;
     insert into ane_test_tmp values(p_nom_otd, p_name1,  1 );
   end if;

   if deleting then
     dbms_output.put_line('FBI: DELETING: p_nom_sotr='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
     delete ane_test_tmp where nom_otd = p_nom_otd and name1=p_name1 and rownum= 1  and inc= 1 ;
     if SQL%ROWCOUNT =  0  then
       insert into ane_test_tmp values(p_nom_otd, p_name1, - 1 );
     end if;
     rzt := calc_key(p_nom_otd, p_name1,pers_cnt + temp_cnt);
   end if;

   if UPDATING then
     dbms_output.put_line('FBI: UPDATING: p_nom_sotr='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
     if upd_stage =  0  then
       dbms_output.put_line('FBI: UPDATE DELETING: p_nom_sotr='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
       delete ane_test_tmp where nom_otd = p_nom_otd and name1=p_name1 and rownum= 1  and inc= 1 ;
       if SQL%ROWCOUNT =  0  then
         insert into ane_test_tmp values(p_nom_otd, p_name1, - 1 );
       end if;
       rzt := calc_key(p_nom_otd, p_name1,pers_cnt + temp_cnt);
       upd_stage :=  1 ;
     else
       dbms_output.put_line('FBI: UPDATE INSERTING: p_nom_sotr='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
       insert into ane_test_tmp values(p_nom_otd, p_name1,  1 );
       if pers_cnt + temp_cnt >=  3  then
         rzt := calc_key(p_nom_otd, p_name1, 1 ); -- DUP_VAL_ON_INDEX
       else
         rzt := calc_key(p_nom_otd, p_name1,pers_cnt + temp_cnt +  1 );
       end if;
       upd_stage :=  0 ;
     end if;
   end if;
   return rzt;
 end;
end ane_test_p;
/
Package body created

sho err
No errors for PACKAGE BODY ANE_TEST_P

--ВОТ ОНО!!!

create unique index ane_test_f_unq on ane_test (substr(ane_test_p.f(nom_otd,name1), 1 , 2000 ));

Index created

insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
 1  row inserted
insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
 1  row inserted
insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
 1  row inserted

--сейчас будет reject
insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
*insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q')
ORA- 00001 : unique constraint (ANE_TEST_F_UNQ) violated

delete ane_test where nom_otd= 1  and rownum< 2 ;
 1  row deleted

insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
 1  row inserted

insert into ane_test( nom_otd, name1) values( 1 ,'^Q!Q');
 1  row inserted

update ane_test set nom_otd=nom_otd+ 1 ;
 4  rows updated

commit;
Commit complete

insert into ane_test( nom_otd, name1) values( 3 ,'Q!Q');
 1  row inserted

--сейчас будет reject

update ane_test set nom_otd=nom_otd+ 1  where nom_otd <  3 ;
*update ane_test set nom_otd=nom_otd+ 1  where nom_otd <  3 
ORA- 00001 : unique constraint (ANE_TEST_F_UNQ) violated

commit;
Commit complete

select * from ane_test;

   NOM_OTD NAME1
---------- -----------------------------------------------
          2  Q!Q
          2  Q!Q
          2  Q!Q
          2  ^Q!Q
          3  Q!Q

drop table ane_test;
Table dropped

drop package ane_test_p;
Package dropped

drop table ane_test_tmp;
Table dropped

...
Рейтинг: 0 / 0
Задачка
    #33329203
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousА вот кому решение без триггера! Чистый FBI!
Elic, мой приз еще здесь?

I do not think you can claim it. Your FBI is not deterministic:

Код: plaintext
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.
.
.
.
SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');

 1  row created.

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');

 1  row created.

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');

 1  row created.

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q')
*
ERROR at line  1 :
ORA- 00001 : unique constraint (SCOTT.ANE_TEST_F_UNQ) violated


SQL> alter index ane_test_f_unq rebuild;

Index altered.

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');

 1  row created.

SQL> select count(*) from ane_test where nom_otd =  1  and name1 = 'Q!Q';

  COUNT(*)
----------
          4 

SQL> 

SY.
...
Рейтинг: 0 / 0
Задачка
    #33329217
Владимир Бегун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
:-)
...
Рейтинг: 0 / 0
Задачка
    #33329239
Andrew Max
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почему-то не заметил раньше этой ветки. ;(

Мои несколько копеек:
Задача интересная. Хотя само бизнес-правило "не иметь более n однофамильцев в одном отделе" несколько странное. Неужели, где-то это в реальности практикуется?
И что делают, если появляется n+1-ый однофамилец? Его в другой отдел переводят? А как быть, если в каждом отделе уже работает n Ивановых и приходит еще один Иванов? Новый отдел создается??? ;)

Тем не менее, если не задумываться над странностями бизнес-правила, -- наилучший вариант, имхо, предложил Владимир Бегун.
...
Рейтинг: 0 / 0
Задачка
    #33329297
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Well, somehow nobody offered INSTEAD OF trigger solution:

Код: plaintext
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.
37.
38.
39.
40.
41.
42.
43.
CREATE TABLE AAA(
                 DEPARTMENT NUMBER,
                 LAST_NAME  VARCHAR2( 30 )
                )
/
CREATE OR REPLACE
  TRIGGER BIU_AAA
    BEFORE INSERT
        OR UPDATE
    ON AAA
    BEGIN
        IF WHO_CALLED_ME <> 'SCOTT.BIUR_AAA_VIEW'
          THEN
            RAISE_APPLICATION_ERROR(- 20987 ,'Table SCOTT.AAA can not be updated/inserted directly.');
        END IF;
END;
/
CREATE OR REPLACE
  VIEW AAA_VIEW
  AS 
    SELECT * FROM AAA
/
CREATE OR REPLACE
  TRIGGER BIUR_AAA_VIEW
    INSTEAD OF INSERT
            OR UPDATE
    ON AAA_VIEW
    FOR EACH ROW
    DECLARE
        v_cnt NUMBER;
    BEGIN
        SELECT  COUNT(*)
          INTO  v_cnt
          FROM  AAA
          WHERE LAST_NAME  = :NEW.LAST_NAME
            AND DEPARTMENT = :NEW.DEPARTMENT;
        IF v_cnt >=  3 
          THEN
            RAISE_APPLICATION_ERROR(- 20986 ,'Get your name changed.');
          ELSE
            INSERT INTO AAA VALUES(:NEW.DEPARTMENT,:NEW.LAST_NAME);
        END IF;
END;
/

where WHO_CALLED_ME is a function that reads dbms_utility.format_call_stack and retrurns calling routine name (I believe you can find source code у Кайта).

SY.
...
Рейтинг: 0 / 0
Задачка
    #33329303
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY andrey_anonymousА вот кому решение без триггера! Чистый FBI!
Elic, мой приз еще здесь?
I do not think you can claim it. Your FBI is not deterministic:
SY.Ну не так уж все и плохо.
Просто забыл про rebuild
Добавьте в ane_test_p.f следующий кусок и все заработает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
...
   if NOT inserting and NOT updating and NOT deleting then
     dbms_output.put_line('FBI: REBUILDING INSERTING: p_nom_otd='||p_nom_otd||', p_name1='||p_name1||', tmp_cnt='||temp_cnt||', pers_cnt='||pers_cnt);
     if /*pers_cnt +*/ temp_cnt >=  3  then
       rzt := calc_key(p_nom_otd, p_name1, 1 ); -- DUP_VAL_ON_INDEX
       dbms_output.put_line('FBI: REBUILDING INSERTING: too many, key='||rzt);
     else
       rzt := calc_key(p_nom_otd, p_name1,/*pers_cnt +*/ temp_cnt +  1 ); 
       dbms_output.put_line('FBI: REBUILDING INSERTING: OK, key='||rzt);
     end if;
     insert into ane_test_tmp values(p_nom_otd, p_name1,  1 );
   end if;   
...
Хотя я, разумеется, осознаю, что это не deterministic. Потому и спрашиваю Elic'a про приз
...
Рейтинг: 0 / 0
Задачка
    #33329307
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sorry, I hit "post it" too early. There is a caveat. Trigger based solution, applies to future changes only (changes since trigger create time), while index applies to current data + future data. Another word, if we will create table AAA, populate it with, lets say, 5 Joe Shmoe's in department 8, and only then create view and triggers, it will not be detected. It could be considered as a disadvantage or as an advantage since it allows to implement "from now on no more более трех однофамильцев, работающих в одном отделе" rule.

SY.
...
Рейтинг: 0 / 0
Задачка
    #33329310
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous Ну не так уж все и плохо

I think it is worse than you think. Just add dbms_output to deleting part:

Код: plaintext
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.
37.
38.
39.
40.
41.
42.
43.
SQL> truncate table ane_test;

Table truncated.

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
FBI: INSERTING: p_nom_sotr= 1 , p_name1=Q!Q, tmp_cnt= 0 , pers_cnt= 0 
FBI: INSERTING: OK, key= 1 /#/Q!Q/#/ 1 

 1  row created.

SQL> select rowid from ane_test;

ROWID
------------------
AAAKULAABAAANdCAAA

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
FBI: INSERTING: p_nom_sotr= 1 , p_name1=Q!Q, tmp_cnt= 1 , pers_cnt= 0 
FBI: INSERTING: OK, key= 1 /#/Q!Q/#/ 2 

 1  row created.

SQL> select rowid from ane_test;

ROWID
------------------
AAAKULAABAAANdCAAA
AAAKULAABAAANdCAAB

SQL> insert into ane_test( nom_otd, name1) values( 1 ,'Q!Q');
FBI: INSERTING: p_nom_sotr= 1 , p_name1=Q!Q, tmp_cnt= 2 , pers_cnt= 0 
FBI: INSERTING: OK, key= 1 /#/Q!Q/#/ 3 

 1  row created.

SQL> select rowid from ane_test;

ROWID
------------------
AAAKULAABAAANdCAAA
AAAKULAABAAANdCAAB
AAAKULAABAAANdCAAC

SQL> 

As you can see FBI values for each of three rows will be:

Код: plaintext
1.
2.
 1 /#/Q!Q/#/ 1         AAAKULAABAAANdCAAA
 1 /#/Q!Q/#/ 2         AAAKULAABAAANdCAAB
 1 /#/Q!Q/#/ 3         AAAKULAABAAANdCAAC

Now lets delete row with 1/#/Q!Q/#/2:

Код: plaintext
1.
2.
3.
4.
5.
6.
SQL> delete ane_test where rowid = 'AAAKULAABAAANdCAAB';
FBI: DELETING: p_nom_sotr= 1 , p_name1=Q!Q, tmp_cnt= 3 , pers_cnt= 0 
FBI: DELETING: OK, key= 1 /#/Q!Q/#/ 3 

 1  row deleted.

SQL> 

As you can see your function wll delete wrong FBI entry 1/#/Q!Q/#/3. So index becomes logically corrupt. You can probably get away with it, since you can not use this FBI in WHERE clause anyway, but still corrupt index is a corrupt index.

SY.
...
Рейтинг: 0 / 0
Задачка
    #33329317
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Actually, I overlooked a major issue with your solution. It simply will not work. Assume session A inserts a row (for simplicity lets say table is empty). That row will have index value of 1/#/Q!Q/#/1. Session A does not commit/rollback yet. Now session B tries to insert a row. Obviously, table is locked and session B waits. Now the fun part - read consistency. Since session B transaction started before Session A committed, session B will not see any changes done by session A. So when session A will commit and release the lock, session B will also try to insert index value 1/#/Q!Q/#/1 and will get unique constraint violation.

SY.
...
Рейтинг: 0 / 0
Задачка
    #33329324
Владимир Бегун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
:-)
Код: plaintext
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.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
SQL> CREATE TABLE AAA(
   2                    DEPARTMENT NUMBER,
   3                    LAST_NAME  VARCHAR2( 30 )
   4                   )
   5   /

Table created.

SQL> CREATE OR REPLACE
   2     VIEW AAA_VIEW
   3     AS 
   4       SELECT * FROM AAA
   5   /

View created.

SQL> CREATE OR REPLACE
   2     TRIGGER BIUR_AAA_VIEW
   3       INSTEAD OF INSERT
   4               OR UPDATE
   5       ON AAA_VIEW
   6       FOR EACH ROW
   7       DECLARE
   8           v_cnt NUMBER;
   9       BEGIN
  10           SELECT  COUNT(*)
  11             INTO  v_cnt
  12             FROM  AAA
  13             WHERE LAST_NAME  = :NEW.LAST_NAME
  14               AND DEPARTMENT = :NEW.DEPARTMENT;
  15           IF v_cnt >=  3 
  16             THEN
  17               RAISE_APPLICATION_ERROR(- 20986 ,'Get your name changed.');
  18             ELSE
  19               INSERT INTO AAA VALUES(:NEW.DEPARTMENT,:NEW.LAST_NAME);
  20           END IF;
  21   END;
  22   /

Trigger created.

SQL> INSERT INTO aaa_view VALUES( 1 , 'A');

 1  row created.

SQL> INSERT INTO aaa_view VALUES( 1 , 'A');

 1  row created.

SQL> INSERT INTO aaa_view VALUES( 1 , 'A');

 1  row created.

SQL> DECLARE
   2     PRAGMA AUTONOMOUS_TRANSACTION;
   3   BEGIN
   4     INSERT INTO aaa_view VALUES( 1 , 'A');
   5     COMMIT;
   6   END;
   7   /

PL/SQL procedure successfully completed.

SQL> COMMIT;

Commit complete.

SQL> SELECT * FROM aaa;

DEPARTMENT LAST_NAME
---------- ------------------------------
          1  A
          1  A
          1  A
          1  A

SQL> INSERT INTO aaa_view VALUES( 1 , 'A');
INSERT INTO aaa_view VALUES( 1 , 'A')
*
ERROR at line  1 :
ORA- 20986 : Get your name changed.
ORA- 06512 : at "BIUR_AAA_VIEW", line  11 
ORA- 04088 : error during execution of trigger 'BIUR_AAA_VIEW'

Let me repeat: "Кодирование, обход мутаций и обеспечение целостности данных при конкурентном изменении данных в таблице -- это ряд вещей, над которыми приходится задумываться решая эту и подобные ей задачи используя DIY-методы."
...
Рейтинг: 0 / 0
25 сообщений из 145, страница 5 из 6
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задачка
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]