使用 MySQL 8.0 触发器自动生成内部产品编号

Automate Internal Product Number Generation with MySQL 8.0 Triggers

我对 SQL 的模式方面不是很有经验,我必须创建一个系统来在将新行输入数据库时​​生成内部产品编号。我已经决定使用 SQL 触发器将是执行此操作的最佳方式,而不是外部编程,因为它在 SQL.

内部看起来更整洁和可行

示例内部产品编号:101-001

内部产品编号有两部分,我分别调用group_idproduct_idgroup_idcategory_id 相关(它在数据库中的存储方式)并且有一个 table 我正在使用它们来连接这些 PartCategory。每个 group_id 中的 product_id 是递增的,但是如果删除了一行,它们预计会像 none 已被删除一样继续,我认为 MAX 是合适的。

这是我正在使用的两个 table 的示例:

DROP TABLE IF EXISTS Part;
CREATE TABLE Part (
    id INT AUTO_INCREMENT PRIMARY KEY,
    category_id INT,
    internalPartNumber VARCHAR(255),
    name VARCHAR(255),
    createdate DATETIME,
    group_id INT,
    product_id INT
);

DROP TABLE IF EXISTS PartCategory;
CREATE TABLE PartCategory (
    id INT AUTO_INCREMENT PRIMARY KEY,
    category_id INT,
    name VARCHAR(255),
    internal_id INT,
    last_product_id INT
);


INSERT INTO PartCategory (internal_id, category_id, name) VALUE (101, 2, 'category1');
INSERT INTO PartCategory (internal_id, category_id, name) VALUE (102, 3, 'category2');

INSERT INTO Part (category_id, name, createdate, group_id, product_id) VALUE (2,   'screw', NOW(), 101, 1);
INSERT INTO Part (category_id, name, createdate, group_id, product_id) VALUE (2, 'spanner', NOW(), 101, 2);
INSERT INTO Part (category_id, name, createdate, group_id, product_id) VALUE (3,  'hammer', NOW(), 102, 1);
INSERT INTO Part (category_id, name, createdate, group_id, product_id) VALUE (3,   'paint', NOW(), 102, 2);

DELIMITER //
CREATE TRIGGER add_group_id BEFORE INSERT ON Part
FOR EACH ROW
BEGIN
    UPDATE Part
    LEFT JOIN PartCategory
    ON Part.category_id = PartCategory.category_id
    SET NEW.group_id = PartCategory.internal_id
    WHERE Part.group_id IS NULL;
    
    UPDATE Part
    SET NEW.product_id = MAX(Part.product_id) OVER(PARTITION BY Part.category_id ORDER BY createdate)
    WHERE NEW.product_id IS NULL;
    
    SET NEW.internalPartNumber = CONCAT(RIGHT(NEW.group_id+1000, 3),'-',RIGHT(NEW.product_id+1000, 3))
    WHERE NEW.internalPartNumber IS NULL;
END; //
DELIMITER ;

INSERT INTO Part (category_id, name, createdate) VALUE (2, 'bolt', NOW());
INSERT INTO Part (category_id, name, createdate) VALUE (3, 'metal', NOW());

SELECT internalPartNumber, name FROM Part
ORDER BY internalPartNumber;

但是在触发器内部我不能使用 table 部分,因为它调用了触发器。我不知道该怎么做。前六个插入代表通过脚本输入数据库的数据,这些我可以设置任何行,最后两个代表将由用户输入的数据(触发器需要处理的数据)。

从这个例子我想看到:

internalPartNumber | name
101-001            | screw
101-002            | spanner
101-003            | bolt
102-001            | hammer
102-002            | paint
102-003            | metal
CREATE TRIGGER tr_bi_Part
BEFORE INSERT
ON Part
FOR EACH ROW
SET NEW.internalPartNumber = CONCAT( ( SELECT internal_id 
                                       FROM PartCategory 
                                       WHERE category_id = NEW.category_id ),
                                     '-',
                                     ( SELECT LPAD(1 + COALESCE(COUNT(*), 0), 3, '0')
                                       FROM Part
                                       WHERE category_id = NEW.category_id ) );

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=58fd1bc356c0a2f771d8160235be3c0c