Загрузка данных
DROP DATABASE IF EXISTS bicycle_store;
CREATE DATABASE bicycle_store
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE bicycle_store;
-- ============================================
-- РОЛИ
-- ============================================
CREATE TABLE roles (
role_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(50) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ПОЛЬЗОВАТЕЛИ
-- ============================================
CREATE TABLE users (
user_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
role_id INT UNSIGNED NOT NULL,
login VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
patronymic VARCHAR(50),
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_users_role
FOREIGN KEY (role_id)
REFERENCES roles(role_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
) ENGINE=InnoDB;
-- ============================================
-- КАТЕГОРИИ
-- ============================================
CREATE TABLE categories (
category_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
category_name VARCHAR(100) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ПРОИЗВОДИТЕЛИ
-- ============================================
CREATE TABLE manufacturers (
manufacturer_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
manufacturer_name VARCHAR(100) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ПОСТАВЩИКИ
-- ============================================
CREATE TABLE suppliers (
supplier_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
supplier_name VARCHAR(150) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ЕДИНИЦЫ ИЗМЕРЕНИЯ
-- ============================================
CREATE TABLE units (
unit_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
unit_name VARCHAR(30) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ТОВАРЫ
-- ============================================
CREATE TABLE products (
product_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
article VARCHAR(30) NOT NULL UNIQUE,
product_name VARCHAR(150) NOT NULL,
category_id INT UNSIGNED NOT NULL,
description TEXT,
manufacturer_id INT UNSIGNED NOT NULL,
supplier_id INT UNSIGNED NOT NULL,
price DECIMAL(10,2) NOT NULL,
unit_id INT UNSIGNED NOT NULL,
stock_quantity INT UNSIGNED NOT NULL DEFAULT 0,
discount_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00,
image_path VARCHAR(255),
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_product_price
CHECK (price >= 0),
CONSTRAINT chk_product_discount
CHECK (discount_percent >= 0 AND discount_percent <= 100),
CONSTRAINT fk_products_category
FOREIGN KEY (category_id)
REFERENCES categories(category_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT fk_products_manufacturer
FOREIGN KEY (manufacturer_id)
REFERENCES manufacturers(manufacturer_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT fk_products_supplier
FOREIGN KEY (supplier_id)
REFERENCES suppliers(supplier_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT fk_products_unit
FOREIGN KEY (unit_id)
REFERENCES units(unit_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
) ENGINE=InnoDB;
-- ============================================
-- СТАТУСЫ ЗАКАЗОВ
-- ============================================
CREATE TABLE order_statuses (
status_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
status_name VARCHAR(50) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- ============================================
-- ЗАКАЗЫ
-- ============================================
CREATE TABLE orders (
order_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
article VARCHAR(30) NOT NULL UNIQUE,
status_id INT UNSIGNED NOT NULL,
pickup_address VARCHAR(255) NOT NULL,
order_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_orders_status
FOREIGN KEY (status_id)
REFERENCES order_statuses(status_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
) ENGINE=InnoDB;
-- ============================================
-- СОСТАВ ЗАКАЗА
-- ============================================
CREATE TABLE order_items (
order_item_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
order_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL,
quantity INT UNSIGNED NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
CONSTRAINT chk_order_item_quantity
CHECK (quantity > 0),
CONSTRAINT chk_order_item_price
CHECK (unit_price >= 0),
CONSTRAINT fk_order_items_order
FOREIGN KEY (order_id)
REFERENCES orders(order_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT fk_order_items_product
FOREIGN KEY (product_id)
REFERENCES products(product_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
UNIQUE KEY uq_order_product (order_id, product_id)
) ENGINE=InnoDB;
-- ============================================
-- ИНДЕКСЫ
-- ============================================
CREATE INDEX idx_products_name
ON products(product_name);
CREATE INDEX idx_products_category
ON products(category_id);
CREATE INDEX idx_products_price
ON products(price);
CREATE INDEX idx_products_stock
ON products(stock_quantity);
CREATE INDEX idx_products_discount
ON products(discount_percent);
CREATE INDEX idx_orders_date
ON orders(order_date);
CREATE INDEX idx_order_items_product
ON order_items(product_id);
-- ============================================
-- РОЛИ
-- ============================================
INSERT INTO roles (role_name) VALUES
('Гость'),
('Авторизованный клиент'),
('Менеджер'),
('Администратор');
-- ============================================
-- ПОЛЬЗОВАТЕЛИ
-- ============================================
INSERT INTO users
(role_id, login, password_hash, last_name, first_name, patronymic)
VALUES
(1, 'guest', 'guest123', 'Гость', 'Гость', NULL),
(2, 'client', 'client123', 'Иванов', 'Иван', 'Иванович'),
(3, 'manager', 'manager123', 'Петров', 'Пётр', 'Петрович'),
(4, 'admin', 'admin123', 'Сидоров', 'Алексей', 'Алексеевич');
-- ============================================
-- КАТЕГОРИИ
-- ============================================
INSERT INTO categories (category_name) VALUES
('Горные велосипеды'),
('Шоссейные велосипеды'),
('Городские велосипеды'),
('Детские велосипеды'),
('Электровелосипеды'),
('Аксессуары');
-- ============================================
-- ПРОИЗВОДИТЕЛИ
-- ============================================
INSERT INTO manufacturers (manufacturer_name) VALUES
('Forward'),
('Stels'),
('Merida'),
('Cube'),
('Author'),
('Giant');
-- ============================================
-- ПОСТАВЩИКИ
-- ============================================
INSERT INTO suppliers (supplier_name) VALUES
('ООО Веломир'),
('ООО СпортСнаб'),
('ООО Велоторг'),
('ООО Велосипедный мир');
-- ============================================
-- ЕДИНИЦЫ ИЗМЕРЕНИЯ
-- ============================================
INSERT INTO units (unit_name) VALUES
('шт.'),
('компл.'),
('упак.');
-- ============================================
-- СТАТУСЫ ЗАКАЗОВ
-- ============================================
INSERT INTO order_statuses (status_name) VALUES
('Новый'),
('В обработке'),
('Готов к выдаче'),
('Выдан'),
('Отменён');
-- ============================================
-- ТОВАРЫ
-- ============================================
INSERT INTO products
(
article,
product_name,
category_id,
description,
manufacturer_id,
supplier_id,
price,
unit_id,
stock_quantity,
discount_percent,
image_path
)
VALUES
(
'BIK-0001',
'Forward Apache 27',
1,
'Горный велосипед с колёсами 27 дюймов.',
1,
1,
45990.00,
1,
12,
0.00,
'images/BIK-0001.jpg'
),
(
'BIK-0002',
'Stels Navigator 500',
1,
'Горный велосипед для прогулок и активного катания.',
2,
2,
38990.00,
1,
8,
10.00,
'images/BIK-0002.jpg'
),
(
'BIK-0003',
'Merida Scultura 100',
2,
'Шоссейный велосипед для тренировок и длительных поездок.',
3,
3,
79990.00,
1,
5,
5.00,
'images/BIK-0003.jpg'
),
(
'BIK-0004',
'Cube Attain',
2,
'Шоссейный велосипед с алюминиевой рамой.',
4,
4,
109990.00,
1,
3,
0.00,
'images/BIK-0004.jpg'
),
(
'BIK-0005',
'Author Compact',
3,
'Городской велосипед для ежедневных поездок.',
5,
1,
52990.00,
1,
10,
15.00,
'images/BIK-0005.jpg'
),
(
'BIK-0006',
'Giant Escape 3',
3,
'Универсальный городской велосипед.',
6,
2,
61990.00,
1,
7,
0.00,
'images/BIK-0006.jpg'
),
(
'BIK-0007',
'Stels Pilot 20',
4,
'Детский велосипед с колёсами 20 дюймов.',
2,
3,
23990.00,
1,
14,
7.00,
'images/BIK-0007.jpg'
),
(
'BIK-0008',
'Forward Twister 24',
4,
'Детский велосипед с колёсами 24 дюйма.',
1,
1,
27990.00,
1,
0,
0.00,
'images/BIK-0008.jpg'
),
(
'BIK-0009',
'Cube Reaction Hybrid',
5,
'Электровелосипед с электродвигателем и аккумулятором.',
4,
4,
219990.00,
1,
4,
20.00,
'images/BIK-0009.jpg'
),
(
'BIK-0010',
'Giant Explore E+',
5,
'Городской электровелосипед.',
6,
2,
189990.00,
1,
6,
12.00,
'images/BIK-0010.jpg'
),
(
'ACC-0001',
'Велосипедный шлем',
6,
'Защитный велосипедный шлем.',
5,
1,
4990.00,
1,
25,
0.00,
'images/ACC-0001.jpg'
),
(
'ACC-0002',
'Велосипедный замок',
6,
'Надёжный замок для защиты велосипеда.',
3,
3,
2990.00,
1,
30,
0.00,
'images/ACC-0002.jpg'
),
(
'ACC-0003',
'Фонарь передний',
6,
'Передний светодиодный фонарь.',
2,
2,
1990.00,
1,
0,
5.00,
'images/ACC-0003.jpg'
),
(
'ACC-0004',
'Насос велосипедный',
6,
'Компактный ручной насос.',
1,
1,
2490.00,
1,
18,
0.00,
'images/ACC-0004.jpg'
);
-- ============================================
-- ЗАКАЗЫ
-- ============================================
INSERT INTO orders
(article, status_id, pickup_address, order_date)
VALUES
(
'ORD-000001',
4,
'г. Москва, ул. Ленина, д. 10',
'2026-09-20 10:30:00'
),
(
'ORD-000002',
3,
'г. Москва, ул. Пушкина, д. 25',
'2026-09-22 14:15:00'
),
(
'ORD-000003',
2,
'г. Москва, ул. Гагарина, д. 5',
'2026-09-24 09:45:00'
),
(
'ORD-000004',
1,
'г. Москва, ул. Центральная, д. 12',
'2026-09-27 16:20:00'
);
-- ============================================
-- СОСТАВ ЗАКАЗОВ
-- ============================================
INSERT INTO order_items
(order_id, product_id, quantity, unit_price)
VALUES
(1, 1, 1, 45990.00),
(1, 11, 1, 4990.00),
(2, 5, 1, 52990.00),
(2, 12, 2, 2990.00),
(3, 9, 1, 219990.00),
(4, 7, 1, 23990.00),
(4, 13, 2, 1990.00);
-- ============================================
-- ПРЕДСТАВЛЕНИЕ ТОВАРОВ
-- ============================================
CREATE VIEW v_products AS
SELECT
p.product_id,
p.article,
p.product_name,
c.category_name AS category,
p.description,
m.manufacturer_name AS manufacturer,
s.supplier_name AS supplier,
p.price,
u.unit_name AS unit,
p.stock_quantity,
p.discount_percent,
CASE
WHEN p.discount_percent > 0
THEN ROUND(
p.price * (1 - p.discount_percent / 100),
2
)
ELSE p.price
END AS final_price,
p.image_path
FROM products p
JOIN categories c
ON c.category_id = p.category_id
JOIN manufacturers m
ON m.manufacturer_id = p.manufacturer_id
JOIN suppliers s
ON s.supplier_id = p.supplier_id
JOIN units u
ON u.unit_id = p.unit_id;
-- ============================================
-- ПРЕДСТАВЛЕНИЕ ЗАКАЗОВ
-- ============================================
CREATE VIEW v_orders AS
SELECT
o.order_id,
o.article AS order_article,
os.status_name AS status,
o.pickup_address,
o.order_date,
COALESCE(
SUM(oi.quantity),
0
) AS total_items,
COALESCE(
SUM(oi.quantity * oi.unit_price),
0
) AS total_amount
FROM orders o
JOIN order_statuses os
ON os.status_id = o.status_id
LEFT JOIN order_items oi
ON oi.order_id = o.order_id
GROUP BY
o.order_id,
o.article,
os.status_name,
o.pickup_address,
o.order_date;
-- ============================================
-- ПРОВЕРКА БАЗЫ
-- ============================================
SELECT * FROM v_products;
SELECT * FROM v_orders;
-- Товары, которые есть на складе
SELECT *
FROM v_products
WHERE stock_quantity > 0;
-- Товары, которых нет на складе
SELECT *
FROM v_products
WHERE stock_quantity = 0;
-- Товары со скидкой от 12% до 18.99%
SELECT *
FROM v_products
WHERE discount_percent >= 12
AND discount_percent < 19;
-- Товары со скидкой 19% и более
SELECT *
FROM v_products
WHERE discount_percent >= 19;
-- Поиск товара
SELECT *
FROM v_products
WHERE product_name LIKE '%велосипед%'
OR description LIKE '%велосипед%'
OR manufacturer LIKE '%Forward%';
-- Сортировка по цене
SELECT *
FROM v_products
ORDER BY price ASC;
-- Сортировка по количеству на складе
SELECT *
FROM v_products
ORDER BY stock_quantity ASC;