powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Внешний ключ для таблицы с наследованием.
10 сообщений из 10, страница 1 из 1
Внешний ключ для таблицы с наследованием.
    #39560263
sameuser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет.
Краткая суть:

Есть таблица пользователей users.
Есть корневая таблица goods, которую наследуют таблицы: drinks, food, alco ...

Есть таблица rating, в которой первичный ключ представлен двумя полями: user_id из таблицы users и goods_id из корневой таблицы товаров. Также в таблице rating есть поле rating_value, отвечающее за проставленную пользователем оценку.

Предполагается, что каждый товар может быть оценен каждым пользователем 1 раз.


Однако в этом случае, судя по докам, первичный ключ в таблице rating, ссылающийся на ID товара ( goods_id из корневой таблицы goods ), будет применим только для записей корневой таблицы, но не для записей из наследующих таблиц.
Т.е. если пользователь захочет оценить товар, находящийся в наследующих таблицах, он этого сделать не сможет.

http://www.lghost.ru/docs/postgres/postgres/ddl-inherit.html

авторЕсли в другой таблице какая-либо колонка имеет ограничение REFERENCES cities(name), то оно будет работать только с значением name в таблице cities, но не с значением name в таблице capitals. В данном случае — это нехорошо.

Примечательно то, что выборка SELECT распространяется и на дочерние (наследующие) таблицы, а внешний ключ - нет: только на родительскую таблицу.

Существует ли решение, которое позволяет "распространить" проверки первичного ключа на наследующие таблицы? Так же, как в случае с выборкой SELECT? Возможно, это правило Rule или триггер?
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560265
sameuser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Или более понятный пример в этом случае - корзина товаров, состоящая из полей fkey_user_id (кто положил товар в корзину ) и fkey_goods_id (какой именно товар). Если сделать запрос SELECT fkey_user_id, fkey_goods_id FROM cart, мы получим в ответ только те товары пользователя в его корзине, которые принадлежат корневой таблице goods. А если он набрал товаров в "дочерних" категориях, то в корзине они будут не видны.
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560296
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sameuser,

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

этим пряникам надо было сразу заложить понятие виртуальной таблицы, с тем, чтобы можно было наследоваться только от пустых "табличек". на мой вкус, ессно.
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560417
fte
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sameuser,

Есть такой вариант, но потребует некоторых усилий....

создаём таблицу goods_shadow_pk c единственной колонкой goods_id primary key, к ней вяжем все необходимые foreign keys...

для goods и всех наследников должны быть триггеры before insert,update,delete,truncate синхронизирующие goods_id c goods_shadow_pk.goods_id, кроме того нужен триггер на drop таблицы наследника goods, как-то так....
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560450
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
(хотя изначально у вас архитектура хромая, если товаров добавлено в соседней категории, то пользователь все равно должен их увидеть в своей карзине)

ок, у вас может просто пример немного неподходит, можно решить немного нестандартно:
хранить данные о выбранных товарах в виде LTREE дерева: Корзина.КатегорияТовара.Товар
(почему карзина а не пользователь: можно в будущем объединять к одной корзине несколько разных учетных записей, через гуглс, vk, и тд)

фишка в том что на деревьях очень легко находить соседние ветки от текущей, можно находить потомков и предков и тп
sameuserА если он набрал товаров в "дочерних" категориях

так же в будущем можно по Товару лекого найти всю цепочку предков, искать кто сколько заказывал оперируя только одним полем ltree + индекс по этому полю для ускорения поисков)
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560457
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и еще два плюса использования ltree: категории товаров могут быть вложенными любой длины:
категорияА -> категорияА1 -> товар1
категорияА -> категорияA2 -> категорияA3 -> товар2

и можно в магазине один товар привязывать к разным категориям, если вы в итоге при подсчете суммы в корзине группируете уже по товару, упуская категории
категорияА -> категорияА1 -> товар1
категорияB -> категорияB1 -> категорияB2 -> товар1
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560919
sameuser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет. Спасибо за ответы.

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

К такой структуре данных пришел потому, что не нашел подходящего способа решения в mysql:

можно было использовать разреженную таблицу ( sparsed ), но по мне хранение всех параметров всех категорий товаров в одной таблице - дурной тон.. Атомарность данных, нормализация БД нарушаются..
можно было использовать хранение свойств товаров в JSON-сериализованных данных, но этот вариант мне тоже не подошел, потому что по свойствам надо работать, делать выборки и пр.
можно было использовать паттерн EAV, но мне он не понравился по ряду причин, в числе которых трудности с использованием дополнительных таблиц, хранящих значения атрибутов.. И сложность запросов - масса JOIN'ов и прочее..

А в наследовании таблиц в postgre мне показался ключ к решению вопроса. Здесь можно использовать корневую таблицу товаров и несколько наследующих (в каждой из наследующих таблиц - свои уникальные параметры той или иной товарной категории). Этих категорий будет немного - напитки, еда, сигареты и пару других.


> для goods и всех наследников должны быть триггеры before insert,update,delete,truncate синхронизирующие goods_id c goods_shadow_pk.goods_id, кроме того нужен триггер на drop таблицы наследника goods, как-то так....

Удаление не потребуется, поскольку товар, единожды принимавший участие в расчетах (например, был заказан), останется в БД.
Удаление таблиц тем более.. Речь иет о небольшом заведении типа кафе или ресторанчика, миллионные записи в таблицах очень нескоро будут достигнуты.. )


> (хотя изначально у вас архитектура хромая, если товаров добавлено в соседней категории, то пользователь все равно должен их увидеть в своей карзине)
Ага. На первый взгляд, может, и хромая. Но куда более хромые варианты перечислены выше в этом же сообщении).
Буду рад услышать предложенные варианты улучшения архитектуры. Про деревья почитаю, подумаю, как их увязать с предполагаемой архитектурой БД.
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39560993
sameuser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вариант с наследованием таблиц оказался бесполезным в рамках данной задачи..
Внешний ключ, использующий ID товара из корневой таблицы, не работает с товарами из дочерних таблиц..

ERROR: insert or update on table "cart" violates foreign key constraint "fkey_goods_id"
DETAIL: Key (fkey_goods_id)=(6) is not present in table "Goods".
SQL state: 23503
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39561044
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sameuserВариант с наследованием таблиц оказался бесполезным в рамках данной задачи..
Внешний ключ, использующий ID товара из корневой таблицы, не работает с товарами из дочерних таблиц..

ERROR: insert or update on table "cart" violates foreign key constraint "fkey_goods_id"
DETAIL: Key (fkey_goods_id)=(6) is not present in table "Goods".
SQL state: 23503
вам сразу сказали, что вы путаете наследование в пж с наследованием в ооп.


звизда для наследников в пж строится только руками. и предок не является её центром.

тоже выше предлагали.

налседование в пж полезно, но мало поддержано специфическими фичами, желательными именно в ключе пж--ного наследования. таких например, как мультитабличный "уникъю" -- объект над пачкой однотабличных индексов. и т.п.. , который мог бы служить для фк без звизды.

к тому же наследование в пж множественное. что богато.
...
Рейтинг: 0 / 0
Внешний ключ для таблицы с наследованием.
    #39567511
Jackvoron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я делал проверку с помощью check

Что то типа этого
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE OR REPLACE FUNCTION check_goods_id(p_goods_id bigint)
RETURNS boolean AS
$BODY$
SELECT EXISTS(SELECT  true FROM goods WHERE goods_id = p_goods_id)) AS is_check;
$BODY$
LANGUAGE sql IMMUTABLE;

ALTER TABLE rating ADD CONSTRAINT chk_test_goods_id CHECK (check_goods_id(goods_id));



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


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