Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / получение свободного идентификатора из sequence / 24 сообщений из 24, страница 1 из 1
03.08.2010, 14:44
    #36773005
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
Доброго, дня всем! Прошу помощи с написанием запроса...
имеется таблица
Код: plaintext
CREATE TABLE table (id	SERIAL PRIMARY KEY,label VARCHAR );
-- в результате этого будет ещё создана SEQUENCE table_id_seq (плюс я разрешил Cycled=1), которая будет инкрементироваться на 1 при каждой вставке, если не указано другое значение.
добавляем записи:
Код: plaintext
1.
2.
INSERT INTO table(id)   VALUES ( 0 );
INSERT INTO table(id)   VALUES ( 1 );
INSERT INTO table(id)   VALUES ( 5 );
после выполнения вставок значения table_id_seq будет ==1 и при попытке выполнить:
Код: plaintext
INSERT INTO table(label)   VALUES ('some text');
получим сообщение из-за ограничения уникальности первичного ключа, а ХОЧЕТСЯ!!! чтоб в случае уже существующео значения делался поиск следующего идентификатора которого нет в таблице. На текущий момент сделал в тригере вставки следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
loop_count :=  0 ;-- MAXVALUE 9223372036854775807
LOOP
  SELECT id INTO tmp FROM table WHERE id=NEW.id;
  EXIT WHEN tmp IS NULL;
  SELECT nextval('table_id_seq') INTO NEW.id;		
  IF loop_count> 9223372036854775806  THEN
    RAISE EXCEPTION 'Нет свободных значений для ключа'; 
  loop_count:=loop_count+ 1 ;
END LOOP;
Но выглядит это как то не кошерно :) и в правилах использовать никак, хотелось бы организовать это SQL запросом типа такого:
Код: plaintext
1.
SELECT nextval('table_id_seq') EXCEPT SELECT id FROM table;
может даже рекурсивным... никак не могу сообразить :(
...
Рейтинг: 0 / 0
03.08.2010, 15:00
    #36773050
Alexius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV,

А нельзя сделать чтобы диапазоны id, которые генерирует последовательность и которые вставляются непосредственно в запросе не пересекались?
например задать очень большое начальное значение для последовательности.
...
Рейтинг: 0 / 0
03.08.2010, 15:09
    #36773082
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
Ну то что так желать запрещено по всем канонам - тебя 2-я Нормальная Форма выучит, а если нет, то это хорошо. На спецов будет больше спрос. То, что вы хотите сделать обычно делается через луп по id и взятие 1-го пустого номера. То что при этом у вас будут дикие проблемы с транзакциями и придется лочить таблицу - так-же понимаете? Если да, но все-таки хочется - можно через цикл, а можно при делите заносит id'ы в отдельную таблицу и лочить ее. Соответственно делать или лок этой таблицы, выбор оттуда значения, анлок таблицы, а если таблица уже залочена, то nextval.

Но еще раз повторюсь: Если вы так сделаете с первичным ключом (может у вас там еще для чего-то это надо), то ночью придет злой дух СУБД и анально вас покарает =)))
...
Рейтинг: 0 / 0
03.08.2010, 15:11
    #36773097
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV
Код: plaintext
1.
2.
INSERT INTO table(id)   VALUES ( 0 );
INSERT INTO table(id)   VALUES ( 1 );
INSERT INTO table(id)   VALUES ( 5 );
при этих вставках генерите id из последовательности (которую создайте явно)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create sequence s1;
create table t1 ( id integer default nextval('s1'), val real );

-- 1 --
insert into t1( val ) values (  3 . 14  );

-- 2 --
insert into t1( id ) select nextval('s1');

drop table t1;
drop sequence s1;
...
Рейтинг: 0 / 0
03.08.2010, 15:18
    #36773121
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
Alexius,

Да, конечно так можно сделать, и я прекрасно понимаю что 9223372036854775807 и проверку делать на переполнение можно не делать, это очень много и даже если вставлять каждую секунду то этого ватит на:
9223372036854775807сек=
153722867280912930.1167мин=
2562047788015215.50194часов=
106751991167300.65суток=
292471208677.54 лет =-O
но есть закон подлости же, вдруг кто-то введёт значение table.id со значением 10^5 , и через полгода произойдёт так что в один ответственный момент что-то не попадёт в табличку :).
Впринциме моя реализация "работает", так что вопрос скорей всего академический, но решить очень хочется :-[
...
Рейтинг: 0 / 0
03.08.2010, 15:37
    #36773214
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV
но есть закон подлости же, вдруг кто-то введёт значение table.id со значением 10^5 , и через полгода произойдёт так что в один ответственный момент что-то не попадёт в табличку :)
ну и чем принципиально будет тогда отличаться твой exception от pk violation? результат один и тот же.

ALEXSAV
Впринциме моя реализация "работает", так что вопрос скорей всего академический
без обоснования "зачем все это нужно" проблема высосана из пальца. придумали себе трудности и теперь их героически решаем. если в конечном итоге "половина" id все равно будет не теми, что хотели, то какой смысл?
...
Рейтинг: 0 / 0
03.08.2010, 15:39
    #36773221
Alexius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV,

Можно после вставки с заданным id делать
Код: plaintext
setval('table_id_seq', SELECT max(id)+ 1  FROM table)
но это тоже криво. Если вопрос академический, то можно сделать составной первичный ключ. Добавить какой-нибудь флаг и при вставке из последовательности вставлять в него одно значение, а при вставке id из запроса - другое.
...
Рейтинг: 0 / 0
03.08.2010, 15:42
    #36773232
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
WarstoneНу то что так желать запрещено по всем канонам - тебя 2-я Нормальная Форма выучит, а если нет, то это хорошо. На спецов будет больше спрос. ... это не относится к вопросу,вообще id-сурогат,а их плюсы и минусы обсуждались!
WarstoneТо, что вы хотите сделать обычно делается через луп по id и взятие 1-го пустого номера. То что при этом у вас будут дикие проблемы с транзакциями и придется лочить таблицу - так-же понимаете? Если да, но все-таки хочется - можно через цикл, а можно при делите заносит id'ы в отдельную таблицу и лочить ее. Соответственно делать или лок этой таблицы, выбор оттуда значения, анлок таблицы, а если таблица уже залочена, то nextval. тут вы меня видимо неправильно поняли, я допускаю пробелы в последовательности...

LeXa NalBatпри этих вставках генерите id из последовательности (которую создайте явно)
Неплохо,спасибо :), я так тоже пробовал - так неполучается в правилах использовать
...
Рейтинг: 0 / 0
03.08.2010, 15:46
    #36773241
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAVно есть закон подлости же, вдруг кто-то введёт значение table.id со значением 10^5 , и через полгода произойдёт так что в один ответственный момент что-то не попадёт в табличку :).
Впринциме моя реализация "работает", так что вопрос скорей всего академический, но решить очень хочется :-[Если у вас id - идентификатор записи, то вы не должны давать его править конечному пользователю. Это аксиома построения БД. Примите это на веру, если не понимаете - почему. Если-же id - это пользовательское что-то и не является PK, то nextval - это просто "подсказка" или "помощь ленивому". Ну а тогда все просто max(id)+1 после insert'а или update'а вас спасут, наверно.

Ну а то что вы написали в процитированном мной абзаце - бред полнейший. Так как если пользователь введет 2^64-1, то 2^64 вызову переполнение разрядной сетки и у вас транзакция откатится. Вот чтоб такого не было id'ы заводят автоматом, а не "как вы" (в том числе).
...
Рейтинг: 0 / 0
03.08.2010, 15:47
    #36773245
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV... это не относится к вопросу,вообще id-сурогат,а их плюсы и минусы обсуждались!Отлично, но он не должен быть изменяемым пользователем. Суррогат - на здоровье. Никто не мешает. Это удобно зачастую, а вот user-input в суррогатный ключ = профнепригодности программиста.
...
Рейтинг: 0 / 0
03.08.2010, 15:54
    #36773267
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
chpashaну и чем принципиально будет тогда отличаться твой exception от pk violation? результат один и тот же. мой экцепшн произойдёт только когда все из 9223372036854775807 будут использованы в id, его можно будет интерпретировать как ошибку и т.д :)
chpashaбез обоснования "зачем все это нужно" проблема высосана из пальца. придумали себе трудности и теперь их героически решаем. если в конечном итоге "половина" id все равно будет не теми, что хотели, то какой смысл? Может и из пальца и без смысла... надо мне, вот и обоснование!
...
Рейтинг: 0 / 0
03.08.2010, 16:04
    #36773303
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
WarstoneОтлично, но он не должен быть изменяемым пользователем. Суррогат - на здоровье. Никто не мешает. Это удобно зачастую, а вот user-input в суррогатный ключ = профнепригодности программиста. Вы собираетесь критиковать меня и вопрос?! Я спросил то что мне нужно и как мне нужно, если нет предложений по реализации, то спасибо за помощь.
...
Рейтинг: 0 / 0
03.08.2010, 16:16
    #36773335
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAVLeXa NalBatпри этих вставках генерите id из последовательности (которую создайте явно)Неплохо,спасибо :), я так тоже пробовал - так неполучается в правилах использоватьпоясните, что именно не получается?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create sequence s1;
create table t1 ( id integer default nextval('s1'), val numeric );

create rule r1 as on delete to t1 do also
        insert into t1( id, val ) select nextval('s1'),  1 /old.val;

insert into t1( val ) values (  3 . 14  );
delete from t1 where val= 3 . 14 ;
select * from t1;

drop table t1;
drop sequence s1;
ps: правилами не пользуюсь
...
Рейтинг: 0 / 0
03.08.2010, 17:27
    #36773565
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAVМожет и из пальца и без смысла... надо мне, вот и обоснование!
это не обоснование, а детский сад
...
Рейтинг: 0 / 0
03.08.2010, 18:55
    #36773783
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
chpashaALEXSAVМожет и из пальца и без смысла... надо мне, вот и обоснование!
это не обоснование, а детский сад
Вы собираетесь критиковать меня и вопрос?! Я спросил то что мне нужно и как мне нужно, если нет предложений по реализации, то спасибо за помощь.
...
Рейтинг: 0 / 0
03.08.2010, 19:09
    #36773800
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAVchpashaну и чем принципиально будет тогда отличаться твой exception от pk violation? результат один и тот же. мой экцепшн произойдёт только когда все из 9223372036854775807 будут использованы в id, его можно будет интерпретировать как ошибку и т.д :)
chpashaбез обоснования "зачем все это нужно" проблема высосана из пальца. придумали себе трудности и теперь их героически решаем. если в конечном итоге "половина" id все равно будет не теми, что хотели, то какой смысл? Может и из пальца и без смысла... надо мне, вот и обоснование!

Я бы всетаки бы повесил before insert trigger который бы всегда бы проставлял для id - nextval(...) если даже id есть в insert запросе.
Т.е. вставлять можно и с id но реально вставленный id будет другой :).

Альтернатива опять же before insert триггер который будет проверять что nextval() значение не занято... и если занято вызывать его в цикле пока не будет найдено свободное значение.

Проблема вашего подхода в том что если кто то введет id=2^63 то циклом идти до него делая nextval на каждом шагу займет вечность :).
Проблема N2 в том что если разрешать вводить id руками могут попробовать ввести уже занятый id и что при этом делать совершенно не ясно.

PS: бросайте в rules играться... триггера и хранимки 99% проблем (кроме updateable view) решают изящнее, быстрее,сильно менее глючно и главное понятным образом.
...
Рейтинг: 0 / 0
03.08.2010, 19:34
    #36773826
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV
Вы собираетесь критиковать меня и вопрос?! и ты и вопрос не выдерживают никакой критики. так что не стану.
...
Рейтинг: 0 / 0
03.08.2010, 20:16
    #36773863
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
chpasha,
извините, но если не хотите и не знаете ответа (написать запрос), то не надо хамить, просто пропустите эту тему, не надо тро́ллинга.Я намеренно абстрагировал и выделил от других сущностей вопрос, чтобы пользователям форума не пришлось копаться в реализации системы.Мне нужен один запрос на pgSQL!!!!!


Maxim Boguk,
Спасибо за советы, я уже тоже склоняюсь уже к вашему мнению :), если не придумаю, то так и оставлю с тригерами и хранимыми процедурами.

Пока есть время - почитаю мануалы по теме WITH RECURSIVE, если разберусь сам - так напишу результат :).

p.s.
...зае , уже не первый раз спрашиваю что-то на форуме и 80% ответов это тупо троллинг о неправильных вопросах и плохих програмистах...
Господа, будте вежливей!!!!!
...
Рейтинг: 0 / 0
03.08.2010, 21:00
    #36773911
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAVЯ намеренно абстрагировал и выделил от других сущностей вопрос, чтобы пользователям форума не пришлось копаться в реализации системы
ты не первый и не последний, кто думает, что знает, что ему надо. причем всем тебе подобным характерна одна и та же линия поведения - вы становитесь в позу.

ALEXSAV...зае
не бегай голым (с)

ALEXSAV
, уже не первый раз спрашиваю что-то на форуме и 80% ответов это тупо троллинг о неправильных вопросах и плохих програмистах
если тебе двое говорят, что ты пьян - иди спать

ALEXSAV
Господа, будте вежливей!!!!!
товарищ, будь попроще.
...
Рейтинг: 0 / 0
03.08.2010, 23:29
    #36774062
ОКТОГЕН
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV, И всё-таки, что вас удерживает от стандартного решения?
(запрет задания идентификатора руками и DEFAULT NEXTVAL('myseq') автоматом на поле)
Если вам нужен ручной номер - почему не хотите завести отдельное неключевое поле,для отображения?
Одно дело - приказ свыше о поле с неразрывной нумерации, другое как здесь.
Человек, конечно, взрослый, можете не обращать внимание на то, что так как вы - никто не делает,
и что это потенциальная проблема. Сами себе злобный буратино.
...
Рейтинг: 0 / 0
04.08.2010, 08:41
    #36774261
ALEXSAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
Сделал следующий запрос,
Код: plaintext
1.
2.
3.
4.
5.
6.
WITH RECURSIVE t(n) AS (
    VALUES ( nextval('table_id_seq') )
  UNION ALL
    SELECT nextval('table_id_seq') AS n FROM t WHERE n <  9223372036854775806 
)
SELECT n FROM t WHERE n NOT IN (SELECT id FROM "table" ) LIMIT  5 ;
результаты выборки - пять свободных id - 2,3,4,6,7 .
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
20.04.2016, 09:39
    #39219832
SJenek
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
ALEXSAV,
Спасибо тебе добрый человек, за интересное решение!
А по поводу умников, которые начинают выступать, зачем это нужно, скажу так кто как хочет, так и делает......
...
Рейтинг: 0 / 0
20.04.2016, 10:05
    #39219856
Lonepsycho
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
SJenek,

а вы сами это решение пробовали? я сам конечно его не пробовал, но мне лично, кажется что WITH... блок тут лишний, и только зря сиквенс прокручивается каждый раз (полностью?). вполне можно было использовать generate_series(1, 9223372036854775806, 1) не производя новых дырок в ид при конкурентой вставке (то что сиквенс работает вне транзакции вам наверное известно?).

имхо конечно.
...
Рейтинг: 0 / 0
20.04.2016, 10:21
    #39219881
Lonepsycho
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение свободного идентификатора из sequence
SJenek,

P.S. сказал это абстрагируясь от того, что были предложены более коректные варианты решения проблемы, и не считаю сам подход такого решения правильным.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / получение свободного идентификатора из sequence / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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