|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Доброго времени суток. Имеется Oracle 11.2.0.3 Enterprise Edition. Задача, использовать последовательность sequence в качестве уникального ключа без пропусков в нумерации. Вопрос в той или иной степени много раз поднимался (судя по поиску на форуме), но нормальной реализации я так и не смог найти. Задача, при insert строки в таблицу test1, при условии что значение поля kl > 5, после commit происходит insert в таблицу test2, в которую передается значение поля id из таблицы test1. При этом значение поле id в таблице test2 это последовательность, без пропусков, начинается с 1, в конце года обнуляется и с первого января вновь начинается с 1. Данные в таблицу test2 попадают только через триггер на таблице test1. В клиент-серверном приложении, откуда пользователи вносят данные, доступа нет, могу ограничения накладывать только через Oracle. Пользователь иногда вносит данные в таблицу test1, но потом либо связь пропадает, либо он передумывает и кнопку отправить не нажимает, не знаю что происходит, никак отловить его не могу, но последовательность нарушается в test2 и появляются пропуски, а это очень критично. В год в таблицу test2 попадает не более 2500 записей. Подскажите в какую сторону копать? --Создаем таблицы create table test1(id number(8), str varchar2(16), kl number(8)); / create table test2(id number(8), str varchar2(16)); / --Создаем последовательности create sequence seq_test1 minvalue 1 maxvalue 9999999999999999999999999999 start with 1 increment by 1 nocache; / create sequence seq_test2 minvalue 1 maxvalue 9999999999999999999999999999 start with 1 increment by 1 nocache; / --Создаем триггеры create or replace trigger TR_INS_test1 for insert ON test1 compound trigger tId number(16) :=0; tKl number(16) :=0; before statement is begin null; end before statement; before EACH ROW IS BEGIN :New.id := seq_test1.nextval; END before EACH ROW; after each row is begin tId := :New.id; tKl := :new.kl; if (tkl > 5) then insert into test2(str) values (tId); end if; end after each row; after statement is begin null; end after statement; end TR_INS_test1; / create or replace trigger TR_INS_test2 before INSERT ON test2 FOR EACH ROW DECLARE BEGIN :New.id := seq_test2.nextval; end TR_INS_test2; / --Запросы insert into test1(str,kl) values ('Test1','7'); commit; insert into test1(str,kl) values ('Test2','8'); rollback; insert into test1(str,kl) values ('Test3','1'); commit; insert into test1(str,kl) values ('Test4','4'); rollback; insert into test1(str,kl) values ('Test5','8'); commit; / --Выводим результат select * from test1; select * from test2; В выборке из test2 2 записи, но поле id должно иметь значения 1 и 2. А не 1 и 3. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 15:45 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Задача, использовать последовательность sequence в качестве уникального ключа без пропусков в нумерации . На мой взгляд, задача с помощью секвенсов не решается, они придуманы не для этого. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 15:55 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro, Конечно, нахрена? Но если очень хочется, то последовательный доступ на вставку, сиквенс реализовать путем записи в отдельной таблице currvalue. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 15:57 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro --Создаем последовательности create sequence seq_test1 estro Вопрос в той или иной степени много раз поднимался (судя по поиску на форуме), но нормальной реализации я так и не смог найти. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 15:59 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
dmdmdm, ваши предложения? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:04 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Elic, max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? Сессии пользователей я не контролирую. И задачу они выполняют не одну. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:12 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro В выборке из test2 2 записи, но поле id должно иметь значения 1 и 2. А не 1 и 3. у Вас есть rollback Код: plsql 1. 2.
rollback не откатывает последовательности Вы двойку спалили при инсерте ('Test2','8'); после каждого инсерт (до commit/rollback) поставте вывод с тест2(сразу станет ясно) чтоб не было дырок из за роллбека надо менять алгоритм выдачи ид .... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:17 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:21 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Stax, Спасибо, но я не потерял двойку, я просто имитировал ситуацию, показывая когда образуются дырки в последовательности. На что поменять, последовательность удобна, раз в год ее обнуляешь и все по новой. Вариант с таблицей вместо последовательности тоже устроит, но как реализовать чтобы не было дырок и дублей? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:21 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Elic estro max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? Прочитал ветку, на которую дали ссылку. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:23 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro Прочитал ветку, на которую дали ссылку. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:29 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Elic estro Прочитал ветку, на которую дали ссылку. Если бы были проблемы со здоровьем, обратился бы к доктору, а не на форум sql.ru. В выделенном вами выше сообщении на ваш ответ в другой ветке не вижу ответа по теме. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:45 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estromax(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. Не могут. Ограничение уникальности не даст. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:50 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro, estro В выделенном вами выше сообщении на ваш ответ в другой ветке не вижу ответа по теме. А если почитать сообщения выше? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:53 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro Elic, max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? Сессии пользователей я не контролирую. И задачу они выполняют не одну. Елик не то (не max(id) + 1) советовал заводите табличку my_seq_test2(current_val number); insert into my_seq_test2 values(0); -стартовое значение в триггере TR_INS_test2 update my_seq_test2 set current_val=current_val+1 ...RETURNING current_val INTO v_currval; :New.id :=v_currval; если паралельно работает много инсертов выстроится очередь (почти однопользовательский режим) зы имхо, без блокировок дырки неизбежны зыы дырку "хранить" и выдавать повторно ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 16:58 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
env estro, estro В выделенном вами выше сообщении на ваш ответ в другой ветке не вижу ответа по теме. А если почитать сообщения выше? Вы извините, но все равно решения не увидел. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 17:05 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Stax estro Elic, max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? Сессии пользователей я не контролирую. И задачу они выполняют не одну. Елик не то (не max(id) + 1) советовал заводите табличку my_seq_test2(current_val number); insert into my_seq_test2 values(0); -стартовое значение в триггере TR_INS_test2 update my_seq_test2 set current_val=current_val+1 ...RETURNING current_val INTO v_currval; :New.id :=v_currval; если паралельно работает много инсертов выстроится очередь (почти однопользовательский режим) зы имхо, без блокировок дырки неизбежны зыы дырку "хранить" и выдавать повторно ..... stax Большое спасибо. Все работает как нужно. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 17:13 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Stax estro Elic, max(id) + 1 крайний вариант, и даже если 10 записей в день вставят, то могут быть совпадения. alter session set isolation_level = serializable куда мне прописать? Сессии пользователей я не контролирую. И задачу они выполняют не одну. Елик не то (не max(id) + 1) советовал заводите табличку my_seq_test2(current_val number); insert into my_seq_test2 values(0); -стартовое значение в триггере TR_INS_test2 update my_seq_test2 set current_val=current_val+1 ...RETURNING current_val INTO v_currval; :New.id :=v_currval; если паралельно работает много инсертов выстроится очередь (почти однопользовательский режим) зы имхо, без блокировок дырки неизбежны зыы дырку "хранить" и выдавать повторно ..... stax А как можно хранить дырку? Вообще решение заменить последовательность таблицей с одной строкой полностью устраивает, ее можно и обнулять раз в год, как мне и нужно. Но получается можно использовать и последовательность в моей задаче, с хранением и повторной выдачей дырок. Как это сделать? Для удовлетворения интереса просто. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 17:20 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro Для удовлетворения интереса просто. Напр 1) завести 10000 строк и отмечать флажком спаленные 2) искать дырки в тест2 и выдавать (на время поиска дырки/мах+1 блокировать ресурс) ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 17:31 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
В общем тему можно закрывать, сделал таблицу-последовательность по годам, надеюсь теперь забуду об этой задаче, но не забуду метод. create table my_seq_test2(current_valnumber(8),yyyy number(4)); / create or replace trigger TR_INS_test2 before INSERT ON test2 FOR EACH ROW DECLARE v_curval number(8) := 0; xc integer := 0; xYear number(4) := to_number(to_char(sysdate, 'yyyy')); BEGIN select count(1) into xC from my_seq_test2 where YYYY = xYear; if (xC > 0) then update my_seq_test2 set current_val = current_val + 1 where YYYY = xYear returning current_val into v_curval; else insert into my_seq_test2 (current_val, YYYY) values (0, xYear); update my_seq_test2 set current_val = current_val + 1 where YYYY = xYear returning current_val into v_curval; end if; -- :New.id := seq_test2.currval; :New.id := v_curval; end TR_INS_test2; Понял о чем говорили добрые и злые люди, давая ссылку на другую тему :). Всем спасибо, всем добра. Надеюсь информация будет кому-то еще полезна. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 18:01 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro, в триггере проверять год, лишняя нагрузка, да и есть манюхинькая вероятность дублирования лет я добавил наперед лет так 10/25 и проверку с трригера убрал зы если проверять, то можно после update if sql%rowcount=0 then --<> 1 .... ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 18:31 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
estro В общем тему можно закрывать, сделал таблицу-последовательность по годам, надеюсь теперь забуду об этой задаче, но не забуду метод. Код: 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.
SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2020, 16:44 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
SY, PRAGMA AUTONOMOUS_TRANSACTION; ему надо чтоб rollback откатывал и номер .... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2020, 16:49 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
Stax SY, PRAGMA AUTONOMOUS_TRANSACTION; ему надо чтоб rollback откатывал и номер .... stax В исходном посте сказано - "без пропусков". Это значит - без дырок как только "rollback откатывал и номер", значит либо a) rollback потенциально образовал дырку (а если дырка допустима, значит допустимо нарушение связи такой последовательности со временем) либо b) вставка идет строго последовательно, в однопользовательском, по существу, режиме, либо с глобальной блокировкой. Такие конструкции не то, чтобы совсем не летают, но очень очень нызенько, и,в целом, неважнецки. Их и технчески нельзя заствить выше какого-то не очень высокого потолка, и логически люди относятся к теме как к "просто последовательности", совсем нередко принимая решения, с которыми на практике жить где-то между нельзя совсем и очень тяжело. И особенно, если commit/rollback отложен по отношению к моменту получению значения такого "сиквенса". ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2020, 17:31 |
|
sequence без пропусков
|
|||
---|---|---|---|
#18+
boobyТакие конструкции не то, чтобы совсем не летают, но очень очень нызенько, Такие конструкции не используются там, где люди способны оформить тысячу накладных (или прочих документов строгой отчётности) в секунду. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2020, 17:34 |
|
|
start [/forum/topic.php?fid=52&msg=40017259&tid=1880723]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
150ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
others: | 307ms |
total: | 547ms |
0 / 0 |