В продолжение вопроса, поднятого тут (Наследование и уникальные индексы). Если вкратце - от предложенного в postgres наследования пришлось отказаться и делать все через связи таблиц и view.
Мне очень захотелось попробовать скрыть на БД за view всю эту структурную кашу с наследованием. Разобрался с обновлением родительских таблиц, и с удалением. А вот на вставке данных возникла проблема.
Код правила на вставку такой:
CREATE OR REPLACE RULE test_child_insert AS ON INSERT TO test_child DO INSTEAD ( INSERT INTO test_parent VALUES(NEW.id,NEW.parent_attr); INSERT INTO test_child_tab VALUES(NEW.id,NEW.child_attr); );
returning
, но вот как ее применить здесь понять пока не смог.
P.S. я с postgres только знакомлюсь, прошу сильно не пинать. И прошу прощения за слегка сумбурное изложение проблемы, не высыпаюсь в последнее время (((
мне кажется, такие вещи лучше
мне кажется, такие вещи лучше делать с помощью триггеров.
Тем не менее вашу задачку можно решить например так
если иногда нужно будет сохранять переданное значение поля id, то вариант другой:
для начала нужно установить в конфигурационном файле параметр custom_variable_classes='vars'
после чего правило можно записать так:
в качестве альтернативы можно создать табличку для хранения таких промежуточных значений, но, повторюсь, в триггере это все естественнее и проще
Спасибо, первый вариант -
Спасибо, первый вариант - самое то.
По поводу триггеров. Честно, не представляю, как это можно реализовать на них.
Может я не тот путь выбираю, но насколько я понимаю этот процесс, на триггерах делать прийдется так:
1.Если при вставке в родительскую таблицу не указано значение автоинкрементного поля, выбрать его из последовательности.
2.Вернуть выбранное значение в правило.
3. Вставить строку с полученным значением в наследуемую таблицу.
Так вот сам процесс возврата (п.2) мне и непонятен (я не знаю, как это сделать).
Если это возможно, то можно обойтись и без дополнительных тригеров, т.к. триггер, описанный в п.1 уже создан в postgres (при создании автоинкрементного поля).
Я забыл, что у вас там
Я забыл, что у вас там несколько дочерних таблиц.
триггер, описанный в п.1 уже создан в postgres (при создании автоинкрементного поля).
это не триггер, просто дефолтное значение поля
***
это не триггер, просто дефолтное значение поля
Извиняюсь, перепутал с Oracle.
А все таки, насколько надежна вот такая конструкция? :
Интересует в первую очередь, а не возникнут ли проблемы при конкурентном доступе? Сейчас делаю тесты на jmeter, думаю, к понедельнику буду знать ответ. Но может кто-то сталкивался?
вы по-моему переборщили с
вы по-моему переборщили с использованием правил, даже стандартный механизм переписали
Я имею в виду дефолтное значение поля id на главной таблице
Чтобы реализовать автоинкремент не нужно писать вьюшку и правило к ней, просто поставить по дефолту NEXTVAL(test_parent_tab_id_seq).
Проблема во втором правиле может возникнуть из-за (странной) особенности функции currval, которая возвращает последнее значение сиквенса, установленное функцией nextval в данной сессии, если такого не происходило, то возникает ошибка.
Поэтому либо напишите второе правило, как предлагал я (с nextval в первом запросе), либо замените currval('test_parent_tab_id_seq') на (select last_value from test_parent_tab_id_seq)
Но в последнем случае как раз есть подозрение, что возникнут проблемы с конкурентным доступом.
Спасибо за подсказку, что
Спасибо за подсказку, что можно убрать вставку id из главной таблицы, тут действительно не подумал . Только вьюшка там не совсем для автоинкремента. Она там для того, что если мне влруг стукнет в голову наследовать главную таблицу от другой, мне не прийдеться бегать по всему коду БД и искать ее использование; типа таая страховка от ошибок . Плюс из кода приложения я буду обращаться только ко вьюшкам, с этой же целью.
Поэтому либо напишите второе правило, как предлагал я (с nextval в первом запросе), либо замените currval('test_parent_tab_id_seq') на (select last_value from test_parent_tab_id_seq)
Вы здесь наверно не очень внимательно просмотрели пример, либо просто не вникали . На самом деле в первом запросе и вызывается nextval, т.к. по первому запросу выполняется правило по вставке в главную таблицу, которое и вызовет nextval.
И то, что currval имеет такую "странную" особенность, как раз и гарантирует мне отсутствие проблем при конкурентном доступе. Только что Вы здесь имели под словом "сессия"? Транзакция? или "от коннекта до дисконнекта"? Мое приложение будет на php, т.е. "сессия" - это от pg_connect до pg_close (так вроде)?
Вы здесь наверно не очень
Вы здесь наверно не очень внимательно просмотрели пример, либо просто не вникали . На самом деле в первом запросе и вызывается nextval, т.к. по первому запросу выполняется правило по вставке в главную таблицу, которое и вызовет nextval.
Я исходил из своего предположения, что первое правило и вюшка не нужны, если они все-таки нужны, то все правильно.
"от коннекта до дисконнекта"? Мое приложение будет на php, т.е. "сессия" - это от pg_connect до pg_close (так вроде)?
Да
Спасибо огромное Вам за
Спасибо огромное Вам за помощь.
На выходных я провел тестирование конкурентного доступа данной схемы. Проблем обнаружено не было
Судя по всему значения sequence не пересекаются при параллельных подключениях (отдельное спасибо комманде разработчиков).
Буквально только что проверил данное предположение (что-то раньше не доходило, как это можно сделать ):
Открыл две консоли постгреса и выполнил такие действия:
результаты:
т.е. теперь за конкурентный доступ я спокоен (а всего-то нужно было почитать документацию , но отписываюсь здесь специально для таких же ленивых как я)