From 6ed26d630dd3af9a6a228905b466cdb37280c1c2 Mon Sep 17 00:00:00 2001 From: xcztj <3356577685@qq.com> Date: Sat, 28 Dec 2024 12:12:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=80=E7=BB=88sql=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/create.sql | 104 ++++++++++++++++++++++++++++ sql/grant.sql | 42 ++++++++++++ sql/index.sql | 20 ++++++ sql/my_insert.sql | 158 +++++++++++++++++++++++++++++++++++++++++++ sql/query.sql | 106 +++++++++++++++++++++++++++++ sql/storeprocess.sql | 158 +++++++++++++++++++++++++++++++++++++++++++ sql/trigger.sql | 79 ++++++++++++++++++++++ sql/update.sql | 72 ++++++++++++++++++++ sql/view.sql | 53 +++++++++++++++ 9 files changed, 792 insertions(+) create mode 100644 sql/create.sql create mode 100644 sql/grant.sql create mode 100644 sql/index.sql create mode 100644 sql/my_insert.sql create mode 100644 sql/query.sql create mode 100644 sql/storeprocess.sql create mode 100644 sql/trigger.sql create mode 100644 sql/update.sql create mode 100644 sql/view.sql diff --git a/sql/create.sql b/sql/create.sql new file mode 100644 index 0000000..5e456ad --- /dev/null +++ b/sql/create.sql @@ -0,0 +1,104 @@ +CREATE TABLE IF NOT EXISTS products ( + product_id int PRIMARY KEY AUTO_INCREMENT, + product_name VARCHAR(20) NOT NULL, + price DOUBLE NOT NULL, + stock_quantity INT DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS customers ( + customer_id INT PRIMARY KEY AUTO_INCREMENT, + customer_name VARCHAR(20) NOT NULL, + phone VARCHAR(11) +); + + +CREATE TABLE IF NOT EXISTS kpi ( + kid INT PRIMARY KEY AUTO_INCREMENT, + grade INT CHECK(grade >= 0), + sid INT, + FOREIGN KEY (sid) REFERENCES sales_people(salesperson_id) +); + +CREATE TABLE IF NOT EXISTS sales_people ( + salesperson_id INT PRIMARY KEY AUTO_INCREMENT, + saleperson_name VARCHAR(20) NOT NULL, + phone VARCHAR(11) +); + + +CREATE TABLE IF NOT EXISTS suppliers ( + supplier_id INT PRIMARY KEY AUTO_INCREMENT, + company_name VARCHAR(20) NOT NULL, + phone VARCHAR(11) +); + + +CREATE TABLE IF NOT EXISTS warehouses ( + warehouse_id INT PRIMARY KEY AUTO_INCREMENT, + location VARCHAR(20) NOT NULL, + capacity INT DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS sales_orders ( + order_id INT PRIMARY KEY AUTO_INCREMENT, + order_date DATE NOT NULL, + customer_id INT, + salesperson_id INT, + total_amount int NOT NULL, + FOREIGN KEY (customer_id) REFERENCES customers(customer_id), + FOREIGN KEY (salesperson_id) REFERENCES sales_people(salesperson_id) +); + +CREATE TABLE IF NOT EXISTS order_details ( + order_detail_id INT PRIMARY KEY AUTO_INCREMENT, + order_id INT, + product_id INT, + quantity INT NOT NULL, + unit_price DOUBLE NOT NULL, + FOREIGN KEY (order_id) REFERENCES sales_orders(order_id), + FOREIGN KEY (product_id) REFERENCES products(product_id) +); + +CREATE TABLE IF NOT EXISTS returns ( + return_id INT PRIMARY KEY AUTO_INCREMENT, + return_date DATE NOT NULL, + order_id INT, + reason varchar(30), + FOREIGN KEY (order_id) REFERENCES sales_orders(order_id) +); + +CREATE TABLE IF NOT EXISTS product_suppliers ( + product_supplier_id INT PRIMARY KEY AUTO_INCREMENT, + product_id INT, + supplier_id INT, + FOREIGN KEY (product_id) REFERENCES products(product_id), + FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id) +); + +CREATE TABLE IF NOT EXISTS product_warehouses ( + product_warehouse_id INT PRIMARY KEY AUTO_INCREMENT, + product_id INT, + warehouse_id INT, + quantity_in_warehouse INT DEFAULT 0, + FOREIGN KEY (product_id) REFERENCES products(product_id), + FOREIGN KEY (warehouse_id) REFERENCES warehouses(warehouse_id) +); + +CREATE TABLE IF NOT EXISTS sales_activities ( + activity_id INT PRIMARY KEY AUTO_INCREMENT, + activity_name VARCHAR(20) NOT NULL, + start_date DATE NOT NULL, + end_date DATE NOT NULL, + total_sales_amount double DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS shipping_methods ( + shipping_method_id INT PRIMARY KEY AUTO_INCREMENT, + methodname VARCHAR(20) NOT NULL, + cost_per_unit double NOT NULL CHECK (cost_per_unit >= 0), + estimated_delivery_time INT NOT NULL CHECK (estimated_delivery_time > 0), + order_id INT, + FOREIGN KEY (order_id) REFERENCES sales_orders(order_id) +); + + diff --git a/sql/grant.sql b/sql/grant.sql new file mode 100644 index 0000000..a51f8d2 --- /dev/null +++ b/sql/grant.sql @@ -0,0 +1,42 @@ +-- 创建用户 +CREATE USER 'admin_user'@'localhost' IDENTIFIED BY 'password123'; +CREATE USER 'salesperson_user'@'localhost' IDENTIFIED BY 'password123'; +CREATE USER 'customer_user'@'localhost' IDENTIFIED BY 'password123'; + +-- 授予管理员权限 +GRANT ALL PRIVILEGES ON *.* TO 'admin_user'@'localhost' WITH GRANT OPTION; +FLUSH PRIVILEGES; + +-- 授予销售员权限 +-- 查看所有产品信息 +GRANT SELECT ON my_company_db.products TO 'salesperson_user'@'localhost'; + +-- 创建新的销售订单 +GRANT INSERT ON my_company_db.sales_orders TO 'salesperson_user'@'localhost'; +GRANT INSERT ON my_company_db.order_details TO 'salesperson_user'@'localhost'; + +-- 查看自己的销售记录 +GRANT SELECT ON my_company_db.sales_orders TO 'salesperson_user'@'localhost'; +GRANT SELECT ON my_company_db.order_details TO 'salesperson_user'@'localhost'; + +-- 查看客户的订单信息 +GRANT SELECT ON my_company_db.customers TO 'salesperson_user'@'localhost'; +GRANT SELECT ON my_company_db.sales_orders TO 'salesperson_user'@'localhost'; +GRANT SELECT ON my_company_db.order_details TO 'salesperson_user'@'localhost'; + +FLUSH PRIVILEGES; + +-- 授予客户权限 +-- 查看自己的订单信息 +GRANT SELECT ON my_company_db.customers TO 'customer_user'@'localhost'; +GRANT SELECT ON my_company_db.sales_orders TO 'customer_user'@'localhost'; +GRANT SELECT ON my_company_db.order_details TO 'customer_user'@'localhost'; + +-- 创建新的订单 +GRANT INSERT ON my_company_db.sales_orders TO 'customer_user'@'localhost'; +GRANT INSERT ON my_company_db.order_details TO 'customer_user'@'localhost'; + +-- 查看产品的基本信息(名称、价格) +GRANT SELECT (product_name, price) ON my_company_db.products TO 'customer_user'@'localhost'; + +FLUSH PRIVILEGES; \ No newline at end of file diff --git a/sql/index.sql b/sql/index.sql new file mode 100644 index 0000000..1fb642c --- /dev/null +++ b/sql/index.sql @@ -0,0 +1,20 @@ +-- 加速基于产品名称的查询。 +CREATE INDEX idx_product_name ON products (product_name); +-- 加速基于客户姓名的查询 +CREATE INDEX idx_customer_name ON customers (customer_name); +-- 加速基于销售人员姓名的查询 +CREATE INDEX idx_salesperson_name ON sales_people (saleperson_name); +-- 加速基于订单日期的查询 +CREATE INDEX idx_order_date ON sales_orders (order_date); +-- 加速基于退货日期的查询 +CREATE INDEX idx_return_date ON returns (return_date); +-- 加速基于订单ID和产品ID的联合查询 +CREATE INDEX idx_order_product ON order_details (order_id, product_id); +-- 加速基于客户ID和订单日期的联合查询 +CREATE INDEX idx_customer_order_date ON sales_orders (customer_id, order_date); +-- 加速基于销售人员ID和订单日期的联合查询 +CREATE INDEX idx_salesperson_order_date ON sales_orders (salesperson_id, order_date); +-- 加速基于供应商公司名称的查询 +CREATE INDEX idx_supplier_company_name ON suppliers (company_name); +-- 加速基于仓库位置和产品ID的联合查询 +CREATE INDEX idx_warehouse_product ON product_warehouses (warehouse_id, product_id); \ No newline at end of file diff --git a/sql/my_insert.sql b/sql/my_insert.sql new file mode 100644 index 0000000..544ab07 --- /dev/null +++ b/sql/my_insert.sql @@ -0,0 +1,158 @@ +INSERT INTO products (product_name, price, stock_quantity) VALUES +('笔记本电脑', 999.99, 100), +('智能手机', 499.99, 200), +('平板电脑', 299.99, 150), +('显示器', 199.99, 300), +('键盘', 49.99, 500), +('鼠标', 29.99, 600), +('耳机', 89.99, 400), +('充电器', 19.99, 700), +('电源适配器', 29.99, 800), +('U盘', 14.99, 900); + +INSERT INTO customers (customer_name, phone) VALUES +('张伟', '1234567890'), +('李娜', '0987654321'), +('王丽', '1122334455'), +('赵强', '5566778899'), +('陈敏', '9988776655'), +('孙华', '1133557788'), +('周静', '2244668877'), +('刘洋', '3355779966'), +('杨柳', '4466880055'), +('朱刚', '5577991144'); + +INSERT INTO sales_people (saleperson_name, phone) VALUES +('王明', '1133557799'), +('李华', '2244668800'), +('刘洋', '3355779911'), +('周红', '4466880022'), +('吴刚', '5577991133'), +('赵雷', '6688001122'), +('钱芳', '7799112233'), +('孙涛', '8800112244'), +('周梅', '9911223355'), +('郑强', '0011223366'); + +INSERT INTO kpi (grade, sid) VALUES +(85, 1), +(90, 2), +(78, 3), +(92, 4), +(88, 5), +(82, 6), +(95, 7), +(79, 8), +(84, 9), +(91, 10); + +INSERT INTO suppliers (company_name, phone) VALUES +('科技公司', '1234567890'), +('电子公司', '0987654321'), +('部件公司', '1122334455'), +('供应中心', '5566778899'), +('零件工厂', '9988776655'), +('创新科技', '2233445566'), +('未来电子', '3344556677'), +('智能设备', '4455667788'), +('高效物流', '5566778899'), +('可靠供应商', '6677889900'); + +INSERT INTO warehouses (location, capacity) VALUES +('北京', 5000), +('上海', 7000), +('广州', 6000), +('深圳', 8000), +('青岛', 4000), +('郑州', 6500), +('济南', 7500), +('西安', 5500), +('太原', 8500), +('合肥', 4500); + +INSERT INTO sales_orders (order_date, customer_id, salesperson_id, total_amount) VALUES +('2024-10-01', 1, 1, 1999.98), +('2024-10-02', 2, 2, 999.98), +('2024-10-03', 3, 3, 299.99), +('2024-10-04', 4, 4, 399.98), +('2024-10-05', 5, 5, 499.98), +('2024-10-06', 6, 6, 1499.94), +('2024-10-07', 7, 7, 999.94), +('2024-10-08', 8, 8, 299.98), +('2024-10-09', 9, 9, 399.98), +('2024-10-10', 10, 10, 499.98); + +INSERT INTO order_details (order_id, product_id, quantity, unit_price) VALUES +(1, 1, 1, 999.99), +(2, 2, 2, 499.99), +(3, 3, 1, 299.99), +(4, 4, 2, 199.99), +(5, 5, 1, 49.99), +(6, 6, 1, 29.99), +(7, 7, 2, 89.99), +(8, 8, 1, 19.99), +(9, 9, 2, 29.99), +(10, 10, 1, 14.99); + +INSERT INTO returns (return_date, order_id, reason) VALUES +('2024-11-01', 1, '损坏'), +('2024-11-02', 2, '错发商品'), +('2024-11-03', 3, '破损'), +('2024-11-04', 4, '改变主意'), +('2024-11-05', 5, '不需要'), +('2024-11-06', 6, '质量问题'), +('2024-11-07', 7, '尺寸不符'), +('2024-11-08', 8, '包装损坏'), +('2024-11-09', 9, '颜色错误'), +('2024-11-10', 10, '功能故障'); + +INSERT INTO product_suppliers (product_id, supplier_id) VALUES +(1, 1), +(2, 2), +(3, 3), +(4, 4), +(5, 5), +(6, 6), +(7, 7), +(8, 8), +(9, 9), +(10, 10); + +INSERT INTO product_warehouses (product_id, warehouse_id, quantity_in_warehouse) VALUES +(1, 1, 100), +(2, 2, 200), +(3, 3, 150), +(4, 4, 300), +(5, 5, 500), +(6, 6, 600), +(7, 7, 400), +(8, 8, 700), +(9, 9, 800), +(10, 10, 900); + +INSERT INTO sales_activities (activity_name, start_date, end_date, total_sales_amount) VALUES +('劳动节促销', '2024-05-01', '2024-05-03', 15000.00), +('元旦促销', '2024-01-01', '2024-01-03', 12000.00), +('冬季清仓', '2024-12-01', '2024-12-31', 20000.00), +('春季促销', '2024-03-01', '2024-03-31', 18000.00), +('夏季折扣', '2024-06-01', '2024-08-31', 22000.00), +('国庆促销', '2024-10-01', '2024-10-07', 17000.00), +('春节促销', '2024-02-12', '2024-02-18', 16000.00), +('中秋节促销', '2024-09-21', '2024-09-25', 14000.00), +('双十一促销', '2024-11-11', '2024-11-11', 19000.00), +('双十二促销', '2024-12-12', '2024-12-12', 21000.00); + +INSERT INTO shipping_methods (methodname, cost_per_unit, estimated_delivery_time, order_id) VALUES +('标准运输', 5.99, 5, 1), +('快速运输', 15.99, 2, 2), +('次日达', 25.99, 1, 3), +('地面运输', 3.99, 7, 4), +('隔夜运输', 45.99, 1, 5), +('经济运输', 7.99, 6, 6), +('普通快递', 10.99, 3, 7), +('加急快递', 20.99, 2, 8), +('自提', 60.99, 4, 9), +('快递', 8.99, 8, 10); + + + diff --git a/sql/query.sql b/sql/query.sql new file mode 100644 index 0000000..2d9e39e --- /dev/null +++ b/sql/query.sql @@ -0,0 +1,106 @@ +-- 比较条件 +-- 找出所有价格大于500元的产品。 +SELECT product_name, price FROM products WHERE price > 500; +-- 列出所有总销售额大于1000元的销售订单。 +SELECT order_id, total_amount FROM sales_orders WHERE total_amount > 1000; +-- 集合比较 +-- 获取所有来自“科技公司”的产品列表。 +SELECT p.product_name +FROM products p +JOIN product_suppliers ps ON p.product_id = ps.product_id +JOIN suppliers s ON ps.supplier_id = s.supplier_id +WHERE s.company_name = '科技公司'; +-- 查找由“王明”或“李华”负责的所有销售订单。 +SELECT so.order_id, so.customer_id, so.total_amount +FROM sales_orders so +JOIN sales_people sp ON so.salesperson_id = sp.salesperson_id +WHERE sp.saleperson_name IN ('王明', '李华'); +-- 范围比较 +-- 找到2024年1月1日至2024年1月31日之间的所有销售订单。 +SELECT * FROM sales_orders +WHERE order_date BETWEEN '2024-10-01' AND '2024-10-31'; +-- 列出库存数量在100到200之间的所有产品。 +SELECT product_name, stock_quantity +FROM products +WHERE stock_quantity BETWEEN 100 AND 200; +-- 字符串相似比较 +-- 搜索名字中包含“华”的所有客户。 +SELECT customer_name, phone +FROM customers +WHERE customer_name LIKE '%华%'; +-- 找出公司名称以“电子”开头的所有供应商。 +SELECT company_name, phone +FROM suppliers +WHERE company_name LIKE '电子%'; +-- 多表连接 +-- 显示每个销售订单的详细信息,包括订单ID、客户名、销售人员名和总金额。 +SELECT so.order_id, c.customer_name, sp.saleperson_name, so.total_amount +FROM sales_orders so +JOIN customers c ON so.customer_id = c.customer_id +JOIN sales_people sp ON so.salesperson_id = sp.salesperson_id; +-- 列出每种产品的供应商及其仓库位置。 +SELECT p.product_name, s.company_name, w.location +FROM products p +JOIN product_suppliers ps ON p.product_id = ps.product_id +JOIN suppliers s ON ps.supplier_id = s.supplier_id +JOIN product_warehouses pw ON p.product_id = pw.product_id +JOIN warehouses w ON pw.warehouse_id = w.warehouse_id; +-- 嵌套查询 +-- 找到所有购买了“笔记本电脑”的客户。 +SELECT DISTINCT c.customer_name +FROM customers c +JOIN sales_orders so ON c.customer_id = so.customer_id +JOIN order_details od ON so.order_id = od.order_id +JOIN products p ON od.product_id = p.product_id +WHERE p.product_name = '笔记本电脑'; +-- 列出有退货记录的销售订单。 +SELECT so.order_id, so.order_date, so.total_amount +FROM sales_orders so +WHERE so.order_id IN (SELECT r.order_id FROM returns r); +-- EXISTS 查询 +-- 检查是否有任何产品没有关联的供应商。 +SELECT p.product_name +FROM products p +WHERE NOT EXISTS ( + SELECT 1 FROM product_suppliers ps WHERE ps.product_id = p.product_id +); +-- 找出至少有一条退货记录的客户。 +SELECT c.customer_name +FROM customers c +WHERE EXISTS ( + SELECT 1 FROM returns r + JOIN sales_orders so ON r.order_id = so.order_id + WHERE so.customer_id = c.customer_id +); +-- 进阶查询 +-- 计算每个销售人员的总销售额。 +SELECT sp.saleperson_name, SUM(so.total_amount) AS total_sales +FROM sales_people sp +JOIN sales_orders so ON sp.salesperson_id = so.salesperson_id +GROUP BY sp.saleperson_name; +-- 统计每个仓库的产品总数。 +SELECT w.location, SUM(pw.quantity_in_warehouse) AS total_products +FROM warehouses w +JOIN product_warehouses pw ON w.warehouse_id = pw.warehouse_id +GROUP BY w.location; +-- 找出每个客户的最近一次购买日期。 +SELECT c.customer_name, MAX(so.order_date) AS last_purchase_date +FROM customers c +JOIN sales_orders so ON c.customer_id = so.customer_id +GROUP BY c.customer_name; +-- 列出所有销售活动及其对应的总销售额。 +SELECT sa.activity_name, SUM(so.total_amount) AS total_sales +FROM sales_activities sa +JOIN sales_orders so ON so.order_date BETWEEN sa.start_date AND sa.end_date +GROUP BY sa.activity_name; +-- 找到最贵的三个产品及其供应商。 +SELECT p.product_name, s.company_name, p.price +FROM products p +JOIN product_suppliers ps ON p.product_id = ps.product_id +JOIN suppliers s ON ps.supplier_id = s.supplier_id +ORDER BY p.price DESC +LIMIT 3; +-- 计算每个运输方式的平均单位成本。 +SELECT sm.methodname, AVG(sm.cost_per_unit) AS avg_cost +FROM shipping_methods sm +GROUP BY sm.methodname; \ No newline at end of file diff --git a/sql/storeprocess.sql b/sql/storeprocess.sql new file mode 100644 index 0000000..5b97b7b --- /dev/null +++ b/sql/storeprocess.sql @@ -0,0 +1,158 @@ +-- 该存储过程应接受客户ID、销售人员ID、产品列表和数量作为参数,并自动计算总金额。 +DELIMITER // +CREATE PROCEDURE InsertNewOrder ( + IN p_customer_id INT, + IN p_salesperson_id INT, + IN p_product_list JSON, + OUT p_order_id INT +) +BEGIN + DECLARE v_total_amount DECIMAL(10, 2) DEFAULT 0; + DECLARE v_product_id INT; + DECLARE v_quantity INT; + DECLARE v_unit_price DECIMAL(10, 2); + DECLARE v_done BOOLEAN DEFAULT FALSE; + DECLARE cur_product CURSOR FOR SELECT product_id, quantity FROM JSON_TABLE(p_product_list, '$[*]' COLUMNS (product_id INT PATH '$.product_id', quantity INT PATH '$.quantity')) AS products; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE; + -- 开始事务 + START TRANSACTION; + -- 插入销售订单 + INSERT INTO sales_orders (order_date, customer_id, salesperson_id, total_amount) + VALUES (CURDATE(), p_customer_id, p_salesperson_id, 0); + -- 获取新插入的订单ID + SET p_order_id = LAST_INSERT_ID(); + -- 遍历产品列表并插入订单详情 + OPEN cur_product; + read_loop: LOOP + FETCH cur_product INTO v_product_id, v_quantity; + IF v_done THEN + LEAVE read_loop; + END IF; + -- 获取产品单价 + SELECT price INTO v_unit_price FROM products WHERE product_id = v_product_id; + -- 插入订单详情 + INSERT INTO order_details (order_id, product_id, quantity, unit_price) + VALUES (p_order_id, v_product_id, v_quantity, v_unit_price); + -- 累加总金额 + SET v_total_amount = v_total_amount + (v_unit_price * v_quantity); + END LOOP; + CLOSE cur_product; + -- 更新销售订单的总金额 + UPDATE sales_orders SET total_amount = v_total_amount WHERE order_id = p_order_id; + -- 提交事务 + COMMIT; +END // +DELIMITER ; +CALL InsertNewOrder(1, 2, '[{"product_id": 1, "quantity": 2}, {"product_id": 3, "quantity": 1}]', @p_order_id); +-- 查询新插入的订单ID +SELECT @p_order_id; + +-- 该存储过程应接受产品ID和调整的数量作为参数,并根据正负值增加或减少库存。 +DELIMITER // +CREATE PROCEDURE UpdateInventory ( + IN p_product_id INT, + IN p_quantity_change INT +) +BEGIN + -- 开始事务 + START TRANSACTION; + -- 更新库存数量 + UPDATE products + SET stock_quantity = stock_quantity + p_quantity_change + WHERE product_id = p_product_id; + -- 如果库存数量变为负数,则回滚事务 + IF (SELECT stock_quantity FROM products WHERE product_id = p_product_id) < 0 THEN + ROLLBACK; + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '库存不足,无法完成操作'; + ELSE + -- 提交事务 + COMMIT; + END IF; +END // +DELIMITER ; + +-- 该存储过程应返回每个销售人员的总销售额、订单数量和平均订单金额。 +DELIMITER // +CREATE PROCEDURE GenerateSalesReport ( + IN p_start_date DATE, + IN p_end_date DATE +) +BEGIN + SELECT + sp.saleperson_name, + COUNT(so.order_id) AS total_orders, + SUM(so.total_amount) AS total_sales, + AVG(so.total_amount) AS avg_order_amount + FROM sales_people sp + JOIN sales_orders so ON sp.salesperson_id = so.salesperson_id + WHERE so.order_date BETWEEN p_start_date AND p_end_date + GROUP BY sp.saleperson_name; +END // +DELIMITER ; + +-- 该存储过程应接受订单ID、退货原因和退货日期作为参数,并更新相关表 +DELIMITER // +CREATE PROCEDURE ProcessReturn ( + IN p_order_id INT, + IN p_return_reason VARCHAR(30), + IN p_return_date DATE +) +BEGIN + DECLARE v_product_id INT; + DECLARE v_quantity INT; + DECLARE v_done BOOLEAN DEFAULT FALSE; + DECLARE cur_order_detail CURSOR FOR SELECT product_id, quantity FROM order_details WHERE order_id = p_order_id; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE; + -- 开始事务 + START TRANSACTION; + -- 插入退货记录 + INSERT INTO returns (return_date, order_id, reason) + VALUES (p_return_date, p_order_id, p_return_reason); + -- 遍历订单详情并恢复库存 + OPEN cur_order_detail; + read_loop: LOOP + FETCH cur_order_detail INTO v_product_id, v_quantity; + IF v_done THEN + LEAVE read_loop; + END IF; + -- 更新产品库存 + UPDATE products + SET stock_quantity = stock_quantity + v_quantity + WHERE product_id = v_product_id; + END LOOP; + CLOSE cur_order_detail; + -- 提交事务 + COMMIT; +END // +DELIMITER ; + +-- 该存储过程应接受一个包含销售人员ID和新KPI等级的JSON数组作为参数,并批量更新kpi表。 +DELIMITER // +CREATE PROCEDURE BatchUpdateKPI ( + IN p_kpi_updates JSON -- JSON格式的KPI更新列表,例如: [{"salesperson_id": 1, "grade": 90}, {"salesperson_id": 2, "grade": 85}] +) +BEGIN + DECLARE v_salesperson_id INT; + DECLARE v_grade INT; + DECLARE v_done BOOLEAN DEFAULT FALSE; + DECLARE cur_kpi_update CURSOR FOR SELECT salesperson_id, grade FROM JSON_TABLE(p_kpi_updates, '$[*]' COLUMNS (salesperson_id INT PATH '$.salesperson_id', grade INT PATH '$.grade')) AS updates; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE; + -- 开始事务 + START TRANSACTION; + -- 遍历KPI更新列表并更新kpi表 + OPEN cur_kpi_update; + read_loop: LOOP + FETCH cur_kpi_update INTO v_salesperson_id, v_grade; + IF v_done THEN + LEAVE read_loop; + END IF; + -- 更新KPI等级 + UPDATE kpi + SET grade = v_grade + WHERE sid = v_salesperson_id; + END LOOP; + CLOSE cur_kpi_update; + -- 提交事务 + COMMIT; +END // +DELIMITER ; \ No newline at end of file diff --git a/sql/trigger.sql b/sql/trigger.sql new file mode 100644 index 0000000..a2b2c83 --- /dev/null +++ b/sql/trigger.sql @@ -0,0 +1,79 @@ +-- product_price_log 表用于记录产品价格变化 +CREATE TABLE IF NOT EXISTS product_price_log ( + log_id INT AUTO_INCREMENT PRIMARY KEY, + product_id INT, + old_price DOUBLE, + new_price DOUBLE, + change_date DATETIME, + FOREIGN KEY (product_id) REFERENCES products(product_id) +); +-- deleted_customers 表用于记录被删除的客户信息 +CREATE TABLE IF NOT EXISTS deleted_customers ( + log_id INT AUTO_INCREMENT PRIMARY KEY, + customer_id INT, + customer_name VARCHAR(20), + phone VARCHAR(11), + delete_date DATETIME +); + +DELIMITER // + +-- 触发器:在插入新订单时,自动更新相应产品的库存数量 +CREATE TRIGGER after_order_insert +AFTER INSERT ON sales_orders +FOR EACH ROW +BEGIN + UPDATE product_warehouses pw + JOIN order_details od ON pw.product_id = od.product_id + SET pw.quantity_in_warehouse = pw.quantity_in_warehouse - od.quantity + WHERE od.order_id = NEW.order_id; +END// + +-- 触发器:在插入新的退货记录时,恢复相应产品的库存数量 +CREATE TRIGGER after_return_insert +AFTER INSERT ON returns +FOR EACH ROW +BEGIN + UPDATE product_warehouses pw + JOIN order_details od ON pw.product_id = od.product_id + SET pw.quantity_in_warehouse = pw.quantity_in_warehouse + od.quantity + WHERE od.order_id = NEW.order_id; +END// + +-- 触发器:在插入新的KPI记录时,检查评分是否在有效范围内(0到100之间) +CREATE TRIGGER before_kpi_insert +BEFORE INSERT ON kpi +FOR EACH ROW +BEGIN + IF NEW.grade < 0 OR NEW.grade > 100 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'KPI评分必须在0到100之间'; + END IF; +END// +-- 尝试插入一个无效的KPI评分 +INSERT INTO kpi (grade, sid) +VALUES (-5, 1); + +-- 触发器:在更新产品价格时,记录旧价格和新价格的变化 +CREATE TRIGGER after_product_update +AFTER UPDATE ON products +FOR EACH ROW +BEGIN + INSERT INTO product_price_log (product_id, old_price, new_price, change_date) + VALUES (OLD.product_id, OLD.price, NEW.price, NOW()); +END// + +-- 触发器:在删除客户记录时,记录被删除的客户信息 +CREATE TRIGGER before_customer_delete +BEFORE DELETE ON customers +FOR EACH ROW +BEGIN + INSERT INTO deleted_customers (customer_id, customer_name, phone, delete_date) + VALUES (OLD.customer_id, OLD.customer_name, OLD.phone, NOW()); +END// + +DELIMITER ; + +SHOW TRIGGERS + + diff --git a/sql/update.sql b/sql/update.sql new file mode 100644 index 0000000..647b1a3 --- /dev/null +++ b/sql/update.sql @@ -0,0 +1,72 @@ +-- UPDATE 操作 +-- 将产品“笔记本电脑”的价格提高50%。 +select price from products where product_name = '笔记本电脑'; +UPDATE products +SET price = price * 1.5 +WHERE product_name = '笔记本电脑'; +-- 为所有库存量小于100的产品补充库存至100。 +UPDATE products +SET stock_quantity = 100 +WHERE stock_quantity < 100; +-- 更新客户“张伟”的电话号码为“13800138000”。 +UPDATE customers +SET phone = '13800138000' +WHERE customer_name = '张伟'; +-- 将销售人员“王明”的KPI等级提升到95。 +UPDATE kpi +SET grade = 95 +WHERE sid = (SELECT salesperson_id FROM sales_people WHERE saleperson_name = '王明'); +-- 将供应商“科技公司”的电话号码更改为“13700137000”。 +UPDATE suppliers +SET phone = '13700137000' +WHERE company_name = '科技公司'; +-- 将仓库“北京”的容量增加1000。 +UPDATE warehouses +SET capacity = capacity + 1000 +WHERE location = '北京'; +-- 将订单ID为1的销售订单的总金额更新为2000元。 +UPDATE sales_orders +SET total_amount = 2000 +WHERE order_id = 1; +-- 将所有退货记录中的退货原因统一为“客户不满意”。 +UPDATE returns +SET reason = '客户不满意'; +-- 将产品“智能手机”的供应商更改为“电子公司”。 +UPDATE product_suppliers +SET supplier_id = (SELECT supplier_id FROM suppliers WHERE company_name = '电子公司') +WHERE product_id = (SELECT product_id FROM products WHERE product_name = '智能手机'); +-- 将产品“平板电脑”在仓库“上海”的库存数量减少50。 +UPDATE product_warehouses +SET quantity_in_warehouse = quantity_in_warehouse - 50 +WHERE product_id = (SELECT product_id FROM products WHERE product_name = '平板电脑') +AND warehouse_id = (SELECT warehouse_id FROM warehouses WHERE location = '上海'); + +-- 删除产品表中的“键盘”产品 +DELETE FROM products WHERE product_name = '键盘'; + +-- 删除客户表中的“张伟”客户 +DELETE FROM customers WHERE customer_name = '张伟'; + +-- 删除销售人员表中的“王明”销售员 +DELETE FROM sales_people WHERE saleperson_name = '王明'; + +-- 删除KPI表中grade为85的记录 +DELETE FROM kpi WHERE grade = 85; + +-- 删除供应商表中的“科技公司” +DELETE FROM suppliers WHERE company_name = '科技公司'; + +-- 删除仓库表中location为“北京”的仓库 +DELETE FROM warehouses WHERE location = '北京'; + +-- 删除销售订单表中customer_id为1的订单 +DELETE FROM sales_orders WHERE customer_id = 1; + +-- 删除订单详情表中order_id为1的记录 +DELETE FROM order_details WHERE order_id = 1; + +-- 删除退货表中reason为“损坏”的记录 +DELETE FROM returns WHERE reason = '损坏'; + +-- 删除促销活动表中activity_name为“劳动节促销”的活动 +DELETE FROM sales_activities WHERE activity_name = '劳动节促销'; diff --git a/sql/view.sql b/sql/view.sql new file mode 100644 index 0000000..741222a --- /dev/null +++ b/sql/view.sql @@ -0,0 +1,53 @@ +-- 显示每个产品的销售详情,包括产品名称、销售数量、销售总金额和平均售价。 +CREATE VIEW product_sales_details AS +SELECT + p.product_name, + SUM(od.quantity) AS total_sold, + SUM(od.quantity * od.unit_price) AS total_sales_amount, + AVG(od.unit_price) AS avg_unit_price +FROM products p +JOIN order_details od ON p.product_id = od.product_id +GROUP BY p.product_name; +-- 显示每个客户的购买历史,包括客户姓名、订单日期、订单总金额和所购产品列表。 +CREATE VIEW customer_purchase_history AS +SELECT + c.customer_name, + so.order_date, + so.total_amount, + GROUP_CONCAT(p.product_name SEPARATOR ', ') AS products_bought +FROM customers c +JOIN sales_orders so ON c.customer_id = so.customer_id +JOIN order_details od ON so.order_id = od.order_id +JOIN products p ON od.product_id = p.product_id +GROUP BY c.customer_name, so.order_date, so.total_amount; +-- 显示每个销售人员的业绩,包括销售人员姓名、销售订单数量、总销售额和平均订单金额。 +CREATE VIEW sales_person_performance AS +SELECT + sp.saleperson_name, + COUNT(so.order_id) AS total_orders, + SUM(so.total_amount) AS total_sales, + AVG(so.total_amount) AS avg_order_amount +FROM sales_people sp +JOIN sales_orders so ON sp.salesperson_id = so.salesperson_id +GROUP BY sp.saleperson_name; +-- 显示每个仓库的库存状况,包括仓库位置、总库存量和各产品的库存明细。 +CREATE VIEW warehouse_inventory_status AS +SELECT + w.location, + SUM(pw.quantity_in_warehouse) AS total_inventory, + GROUP_CONCAT(CONCAT(p.product_name, ': ', pw.quantity_in_warehouse) SEPARATOR '; ') AS inventory_details +FROM warehouses w +JOIN product_warehouses pw ON w.warehouse_id = pw.warehouse_id +JOIN products p ON pw.product_id = p.product_id +GROUP BY w.location; +-- 创建一个视图,评估每个销售活动的效果,包括活动名称、开始日期、结束日期、总销售额和参与订单数量。 +CREATE VIEW sales_activity_effectiveness AS +SELECT + sa.activity_name, + sa.start_date, + sa.end_date, + SUM(so.total_amount) AS total_sales, + COUNT(so.order_id) AS total_orders +FROM sales_activities sa +LEFT JOIN sales_orders so ON so.order_date BETWEEN sa.start_date AND sa.end_date +GROUP BY sa.activity_name, sa.start_date, sa.end_date; \ No newline at end of file