使用 MySQL 8.0 触发器自动生成内部产品编号
Automate Internal Product Number Generation with MySQL 8.0 Triggers
我对 SQL 的模式方面不是很有经验,我必须创建一个系统来在将新行输入数据库时生成内部产品编号。我已经决定使用 SQL 触发器将是执行此操作的最佳方式,而不是外部编程,因为它在 SQL.
内部看起来更整洁和可行
示例内部产品编号:101-001
内部产品编号有两部分,我分别调用group_id
和product_id
。 group_id
与 category_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
我对 SQL 的模式方面不是很有经验,我必须创建一个系统来在将新行输入数据库时生成内部产品编号。我已经决定使用 SQL 触发器将是执行此操作的最佳方式,而不是外部编程,因为它在 SQL.
内部看起来更整洁和可行示例内部产品编号:101-001
内部产品编号有两部分,我分别调用group_id
和product_id
。 group_id
与 category_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