60. Проектирование базы изделий (ведомость состава / BOM) #
Условие задачи:
📌 Нужно спроектировать схему БД для хранения состава изделия (BOM).
Есть изделие и его состав:
1 Датчик
2 Корпус 1 шт
3 Винт 8 шт
3 Винт 4 шт
Задача: какие будут таблицы и столбцы, чтобы:
хранить все изделия/детали (нормативка);
хранить структуру: какое изделие из каких компонентов состоит и в каком количестве;
поддерживать повторное использование одной и той же детали (например, «Винт» в разных местах и в разном количестве).
Спойлеры к решению
Подсказки
💡 Обычно делаем 2 таблицы:
items— справочник изделий/деталей (что это за номенклатура).bom(bill of materials) — связи «родитель → компонент + количество».
💡 В bom нужны:
parent_item_id— что собираем,component_item_id— из чего,quantity— сколько штук,опционально
level/position/unit.
Решение
1. Таблица изделий / деталей #
CREATE TABLE items (
id BIGINT PRIMARY KEY, -- 1, 2, 3 ...
name VARCHAR(255) NOT NULL, -- "Датчик", "Корпус", "Винт"
item_code VARCHAR(50), -- артикул / внутр. код (опционально)
item_type VARCHAR(50), -- тип: 'ASSEMBLY', 'PART', 'RAW' и т.п.
unit VARCHAR(20) NOT NULL DEFAULT 'шт', -- базовая единица измерения
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT now(),
updated_at TIMESTAMP NOT NULL DEFAULT now()
);
Примеры данных для твоего случая:
id | name | item_type
---+---------+----------
1 | Датчик | ASSEMBLY
2 | Корпус | ASSEMBLY
3 | Винт | PART
2. Таблица структуры изделия (BOM) #
CREATE TABLE bom (
id BIGINT PRIMARY KEY,
parent_item_id BIGINT NOT NULL, -- изделие, которое собираем (например, "Датчик")
component_item_id BIGINT NOT NULL, -- компонент (например, "Корпус", "Винт")
quantity NUMERIC(12, 3) NOT NULL, -- количество компонента на 1 ед. родителя
unit VARCHAR(20) NOT NULL DEFAULT 'шт', -- ед. измерения (шт, кг, м и т.п.)
position INT, -- позиция в спецификации (для печатных форм)
level_hint INT, -- опционально: уровень вложенности (1,2,3 ...)
CONSTRAINT fk_bom_parent
FOREIGN KEY (parent_item_id) REFERENCES items(id),
CONSTRAINT fk_bom_component
FOREIGN KEY (component_item_id) REFERENCES items(id)
);
Данные для примера:
-- Датчик состоит из:
-- 1) Корпус 1 шт
-- 2) Винт 4 шт
INSERT INTO bom (id, parent_item_id, component_item_id, quantity, unit, position, level_hint)
VALUES
(1, 1, 2, 1, 'шт', 1, 1), -- Датчик -> Корпус 1 шт
(2, 1, 3, 4, 'шт', 2, 1); -- Датчик -> Винт 4 шт
-- Корпус состоит из:
-- 3) Винт 8 шт
INSERT INTO bom (id, parent_item_id, component_item_id, quantity, unit, position, level_hint)
VALUES
(3, 2, 3, 8, 'шт', 1, 2); -- Корпус -> Винт 8 шт
Как читается структура:
parent_item_id = 1 ("Датчик"),component_item_id = 2 ("Корпус"),quantity = 1→
На один датчик нужен один корпус.parent_item_id = 1 ("Датчик"),component_item_id = 3 ("Винт"),quantity = 4→
На один датчик нужно 4 винта «верхнего уровня».parent_item_id = 2 ("Корпус"),component_item_id = 3 ("Винт"),quantity = 8→
На один корпус нужно 8 винтов.
Почему именно так:
Одна таблица
items— один раз описывает, что это за деталь/изделие.Таблица
bom— описывает, как одно изделие собирается из других (родитель → компоненты).Одна и та же деталь (
Винт, id=3) может фигурировать в разных BOM с разным количеством и на разных уровнях вложенности — это как раз то, что нужно для нормальной спецификации.
Такой дизайн — классический для систем управления составом изделия (BOM/ERP/PLM).