板凳-------Mysql cookbook学习 (十一--------2)
11.6 扩展序列列的取值范围 2025-07-01
11.7 序列顶部数值的再使用
11.8 确保各行按照给定顺序重编号
思路
1、 创建表的空克隆
2、 使用insert into ......select 从源表自制行
3、删除源表, 并将克隆表重命名为源表表名
4、如果是巨大的MyISAM, 并含有多个索引,创建新表时不定义除了auto_increment列之外的索引,会使整个过程更高效重新编号时解决主键冲突的示例
通过一个完整的可运行示例来演示如何安全地重新编号表中的主键,避免冲突。示例场景
假设我们有一个用户表 users,其中主键 id 不是连续的(可能因为删除了某些行),现在需要重新编号使其连续。1. 创建原始表并插入数据
sql
-- 创建原始表
CREATE TABLE users (id INT PRIMARY KEY,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 插入一些数据(故意跳过某些ID)
INSERT INTO users (id, username, email) VALUES
(1, 'user1', 'user1@example.com'),
(3, 'user3', 'user3@example.com'),
(7, 'user7', 'user7@example.com'),
(10, 'user10', 'user10@example.com');
2. 方法一:创建新表并重新编号
sql
-- 创建新表结构(不包含主键约束)
CREATE TABLE users_new LIKE users;
ALTER TABLE users_new DROP PRIMARY KEY;-- 插入数据并重新编号
INSERT INTO users_new (id, username, email, created_at)
SELECT ROW_NUMBER() OVER (ORDER BY id) AS new_id,username,email,created_at
FROM users;-- 删除旧表并重命名新表
DROP TABLE users;
RENAME TABLE users_new TO users;-- 重新添加主键
ALTER TABLE users ADD PRIMARY KEY (id);-- 验证结果
SELECT * FROM users;
3. 方法二:更高效的MyISAM表处理
如果表很大且是MyISAM引擎:sql
-- 创建只有基本结构的新表(无索引)
CREATE TABLE users_new (id INT,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,created_at TIMESTAMP
) ENGINE=MyISAM;-- 插入数据并重新编号
INSERT INTO users_new (id, username, email, created_at)
SELECT @row := @row + 1 AS new_id,username,email,created_at
FROM users, (SELECT @row := 0) r
ORDER BY id;-- 删除旧表并重命名新表
DROP TABLE users;
RENAME TABLE users_new TO users;-- 添加主键和索引
ALTER TABLE users ADD PRIMARY KEY (id);
ALTER TABLE users ADD INDEX (email);-- 验证结果
SELECT * FROM users;
注意事项
外键约束:如果表有外键引用,需要先删除约束,操作后再重新添加事务:在大表上操作时,考虑使用事务确保数据安全备份:操作前务必备份数据权限:确保有足够的权限执行这些操作完整示例(包含外键处理)
sql
-- 创建有外键关系的表
CREATE TABLE departments (dept_id INT PRIMARY KEY,dept_name VARCHAR(50)
);CREATE TABLE employees (emp_id INT PRIMARY KEY,emp_name VARCHAR(50),dept_id INT,FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);-- 插入数据
INSERT INTO departments VALUES (1, 'HR'), (2, 'IT');
INSERT INTO employees VALUES (5, 'Alice', 1),(8, 'Bob', 2),(12, 'Charlie', 1);-- 1. 删除外键约束
ALTER TABLE employees DROP FOREIGN KEY employees_ibfk_1;-- 2. 创建新表并重新编号
CREATE TABLE employees_new LIKE employees;
ALTER TABLE employees_new DROP PRIMARY KEY;INSERT INTO employees_new (emp_id, emp_name, dept_id)
SELECT ROW_NUMBER() OVER (ORDER BY emp_id) AS new_id,emp_name,dept_id
FROM employees;-- 3. 替换表
DROP TABLE employees;
RENAME TABLE employees_new TO employees;-- 4. 重新添加约束
ALTER TABLE employees ADD PRIMARY KEY (emp_id);
ALTER TABLE employees ADD CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES departments(dept_id);-- 验证结果
SELECT * FROM employees;
通过以上方法,可以安全地重新编号表中的主键,即使存在外键约束也能正确处理。更优的重新编号主键方法
确实有比创建新表更高效的方案,特别是在生产环境中处理大表时。以下是几种更优的方法:方法一:使用临时列交换(无需重建表)
sql
-- 1. 添加临时列存储新ID
ALTER TABLE users ADD COLUMN new_id INT;-- 2. 更新临时列为新编号
SET @row_number = 0;
UPDATE users
SET new_id = (@row_number := @row_number + 1)
ORDER BY id;-- 3. 删除原主键约束
ALTER TABLE users DROP PRIMARY KEY;-- 4. 更新原ID列
UPDATE users SET id = new_id;-- 5. 删除临时列并重建主键
ALTER TABLE users DROP COLUMN new_id;
ALTER TABLE users ADD PRIMARY KEY (id);
优点:不需要创建新表减少磁盘空间使用保留所有原始表属性(触发器、权限等)方法二:事务处理确保数据安全
sql
START TRANSACTION;-- 禁用外键检查(如有外键约束)
SET FOREIGN_KEY_CHECKS = 0;-- 使用临时变量重新编号
SET @new_id = 0;
UPDATE users
SET id = (@new_id := @new_id + 1)
ORDER BY id;-- 重置自增值
ALTER TABLE users AUTO_INCREMENT = @new_id + 1;-- 重新启用外键检查
SET FOREIGN_KEY_CHECKS = 1;COMMIT;
方法三:针对InnoDB的优化方案
sql
-- 1. 创建临时序列表
CREATE TEMPORARY TABLE sequence (new_id INT AUTO_INCREMENT PRIMARY KEY);-- 2. 生成连续序号
INSERT INTO sequence ()
SELECT NULL FROM users ORDER BY id;-- 3. 联表更新(单次操作完成)
UPDATE users u
JOIN sequence s ON 1=1
SET u.id = s.new_id
ORDER BY u.id
LIMIT (SELECT COUNT(*) FROM users);-- 4. 清理
DROP TEMPORARY TABLE sequence;
方法四:使用存储过程(适合复杂场景)
sql
DELIMITER //
CREATE PROCEDURE renumber_ids()
BEGINDECLARE done INT DEFAULT FALSE;DECLARE old_id, new_id INT;DECLARE cur CURSOR FOR SELECT id FROM users ORDER BY id;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;SET new_id = 0;OPEN cur;read_loop: LOOPFETCH cur INTO old_id;IF done THENLEAVE read_loop;END IF;SET new_id = new_id + 1;-- 只有当ID不同时才更新IF old_id != new_id THEN-- 处理可能的冲突UPDATE users SET id = -old_id WHERE id = old_id;UPDATE users SET id = new_id WHERE id = -old_id;END IF;END LOOP;CLOSE cur;-- 重置自增值SELECT MAX(id) INTO @max_id FROM users;SET @sql = CONCAT('ALTER TABLE users AUTO_INCREMENT = ', @max_id + 1);PREPARE stmt FROM @sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;
END //
DELIMITER ;-- 执行存储过程
CALL renumber_ids();
最佳实践建议
评估必要性:主键是否真的需要连续?业务上是否有此需求?外键处理:sql
-- 查找所有外键约束
SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'users';-- 临时禁用外键检查
SET FOREIGN_KEY_CHECKS = 0;
-- 执行重编号操作...
SET FOREIGN_KEY_CHECKS = 1;
性能优化:对大表操作时添加适当索引分批处理(每次更新10000行)在低峰期执行原子性保障:sql
START TRANSACTION;
-- 执行重编号操作
COMMIT;
-- 或出错时 ROLLBACK;
选择哪种方法取决于您的具体场景:小表:方法一或方法二大表:方法三或方法四有复杂约束:存储过程方案
11.9 从某个特定值开始一个序列
mysql> create table tt01-> (id int unsigned not null auto_increment, primary key (id));
Query OK, 0 rows affected (0.11 sec)mysql> insert into tt01 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt01 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt01 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> select id from tt01 order by id;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
3 rows in set (0.00 sec)-- 删除表前先检查是否存在
DROP TABLE IF EXISTS table_name;
AI写代码
在上面的代码中,IF EXISTS 关键字用于判断表是否存在,如果表存在则执行删除操作,否则不会报错。一些需要注意的事项:1. 数据备份
在删除表之前,务必进行数据备份。无论是误操作还是其他意外原因导致数据丢失,备份可以帮助恢复数据,避免信息丢失造成的损失。2. 确认操作对象
在执行删除表操作前,要确保明确操作的是正确的表。避免误删其他重要表,确认操作对象是正确的是非常重要的。3. 删除表前查看依赖关系
在删除表之前,要先查看该表是否被其他表或程序所依赖。如果存在外键关联或其他依赖关系,需要先解除这些关系,否则可能导致其他功能异常。4. 谨慎使用DELETE语句
在删除表中数据时,要谨慎使用DELETE语句,确保只删除需要的数据行。同时,如果只是删除表而不需要保留表结构,建议使用DROP TABLE命令,效率更高。5. 使用事务
在删除表操作中,可以使用事务来确保操作的一致性和完整性。如果删除表是一个重要的操作,可以结合事务来处理,避免意外中断导致数据不一致。6. 注意权限控制
在删除表时,要注意当前用户是否具有足够的权限。确保只有授权人员才能执行删除表的操作,避免未经授权的删除操作带来安全风险。
————————————————
原文链接:https://blog.csdn.net/q7w8e9r4/article/details/138009452mysql> drop table tt02;
Query OK, 0 rows affected (0.04 sec)mysql> create table tt02-> (id int unsigned not null auto_increment, primary key (id))-> auto_increment = 100;
Query OK, 0 rows affected (0.04 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> select id from tt02 order by id;
+-----+
| id |
+-----+
| 100 |
| 101 |
| 102 |
+-----+
3 rows in set (0.00 sec)mysql> create table tt02-> (id int unsigned not null auto_increment, primary key (id))-> auto_increment = 100;
Query OK, 0 rows affected (0.04 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt02 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> select id from tt02 order by id;
+-----+
| id |
+-----+
| 100 |
| 101 |
| 102 |
+-----+
3 rows in set (0.00 sec)mysql> create table tt03-> (id int unsigned not null auto_increment, primary key (id))-> alter table tt03 auto_increment = 100;
Query OK, 0 rows affected (0.04 sec)mysql> insert into tt03 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt03 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt03 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> select id from tt03 order by id;
+-----+
| id |
+-----+
| 100 |
| 101 |
| 102 |
+-----+
3 rows in set (0.00 sec)mysql> CREATE TABLE tt04 (-> id INT UNSIGNED NOT NULL AUTO_INCREMENT,-> PRIMARY KEY (id)-> ) ENGINE = InnoDB;
Query OK, 0 rows affected (0.04 sec)mysql> insert into tt04 (id) values(99);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt04 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt04 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt04 (id) values(null);
Query OK, 1 row affected (0.01 sec)mysql> delete from tt04 where id = 99;
Query OK, 1 row affected (0.01 sec)mysql> select * from tt04 order by id;
+-----+
| id |
+-----+
| 100 |
| 101 |
| 102 |
+-----+
3 rows in set (0.00 sec)
11.10 序列化一个未序列的表
CREATE TABLE tt05 (name VARCHAR(50) NOT NULL,age INT NOT NULL,PRIMARY KEY (name) -- 假设name是唯一的,设为主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;INSERT INTO tt05 (name, age) VALUES
('boris', 47),
('clarence', 62),
('abner', 53),
('alice', 71);-- 1. 删除现有的主键约束(需要先删除依赖它的外键,如果有的话)
ALTER TABLE tt05 DROP PRIMARY KEY;-- 2. 添加自增ID列并设为主键
ALTER TABLE tt05
ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, -- 添加到第一列
ADD PRIMARY KEY (id);mysql> select * from tt05;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | abner | 53 |
| 2 | alice | 71 |
| 3 | boris | 47 |
| 4 | clarence | 62 |
+----+----------+-----+
4 rows in set (0.00 sec)方法 2:保留原主键,只添加自增ID(但不设为主键)
sql
复制
下载
-- 仅添加自增ID列(作为普通列)
ALTER TABLE tt05
ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST;
方法 3:创建新表并迁移数据
如果数据量不大,可以重建表:
sql
复制
下载
-- 1. 创建新表
CREATE TABLE tt05_new (id INT NOT NULL AUTO_INCREMENT,name VARCHAR(50) NOT NULL,age INT NOT NULL,PRIMARY KEY (id),UNIQUE KEY (name) -- 保持name唯一
) ENGINE=InnoDB;-- 2. 导入数据
INSERT INTO tt05_new (name, age)
SELECT name, age FROM tt05;-- 3. 删除旧表,重命名新表
DROP TABLE tt05;
RENAME TABLE tt05_new TO tt05;+----------+-----+----+
| name | age | id |
+----------+-----+----+
| abner | 53 | 1 |
| alice | 71 | 2 |
| boris | 47 | 3 |
| clarence | 62 | 4 |
+----------+-----+----+
方法 1:重建表结构(推荐)
直接创建符合要求的表结构(适用于数据量小或新表):
mysql> -- 1. 创建新表(id在第三列)
mysql> CREATE TABLE tt05_new (-> name VARCHAR(50) NOT NULL,-> age INT NOT NULL,-> id INT NOT NULL AUTO_INCREMENT,-> PRIMARY KEY (id),-> UNIQUE KEY (name) -- 可选:确保name唯一-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.08 sec)mysql>
mysql> -- 2. 导入原数据(不指定id,让MySQL自动生成)
mysql> INSERT INTO tt05_new (name, age)-> SELECT name, age FROM tt05;
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0mysql>
mysql> -- 3. 替换旧表
mysql> DROP TABLE tt05;
Query OK, 0 rows affected (0.04 sec)mysql> RENAME TABLE tt05_new TO tt05;
Query OK, 0 rows affected (0.04 sec)mysql> select * from tt05;
+----------+-----+----+
| name | age | id |
+----------+-----+----+
| abner | 53 | 1 |
| alice | 71 | 2 |
| boris | 47 | 3 |
| clarence | 62 | 4 |
+----------+-----+----+
4 rows in set (0.00 sec)________________________________________
方法 2:通过 ALTER TABLE 调整(复杂)
如果必须保留原表,可通过临时列实现:
sql
复制
下载
-- 1. 移除id的自增属性(需先删除主键)
ALTER TABLE tt05 MODIFY id INT NOT NULL;
ALTER TABLE tt05 DROP PRIMARY KEY;-- 2. 将id列重命名为临时列
ALTER TABLE tt05 CHANGE id temp_id INT;-- 3. 在末尾添加新的自增id列
ALTER TABLE tt05 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST;
ALTER TABLE tt05 ADD PRIMARY KEY (id);-- 4. 将数据从temp_id复制到新id列(如果需要保留原id值)
UPDATE tt05 SET id = temp_id;-- 5. 删除临时列
ALTER TABLE tt05 DROP COLUMN temp_id;-- 6. 将id列移动到第三位(MySQL不支持直接移动列,需重建表)
-- 此处需使用方法1的步骤mysql> -- 1. 删除现有id列
mysql> ALTER TABLE tt05 DROP COLUMN id;
Query OK, 4 rows affected (0.13 sec)
Records: 4 Duplicates: 0 Warnings: 0mysql> -- 2. 添加新的自增id列
mysql> ALTER TABLE tt05-> ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST,-> ADD PRIMARY KEY (id),-> AUTO_INCREMENT = 100;
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> select * from tt05;
+-----+----------+-----+
| id | name | age |
+-----+----------+-----+
| 100 | abner | 53 |
| 101 | alice | 71 |
| 102 | boris | 47 |
| 103 | clarence | 62 |
+-----+----------+-----+
4 rows in set (0.00 sec)
11.11 使用auto_increment栏来创建多重序列
需要将自增列id单独设为主键。原表定义中同时使用name和id作为复合主键,且id为自增列,这违反了 MySQL 的规则。以下是修正后的 SQL 语句:sql
CREATE TABLE bug (id INT UNSIGNED NOT NULL AUTO_INCREMENT,name VARCHAR(30) NOT NULL,date DATE NOT NULL,origin VARCHAR(30) NOT NULL,PRIMARY KEY (id), -- 仅使用id作为主键UNIQUE KEY (name) -- 如果需要确保name唯一,可添加唯一索引
);INSERT INTO bug (name, date, origin) VALUES
('mosquito', '2006-10-08', 'bathroom'),
('spider', '2006-10-08', 'basement'),
('fly', '2006-10-08', 'kitchen'),
('moth', '2006-10-09', 'bedroom'),
('centipede', '2006-10-09', 'garage'),
('millipede', '2006-10-09', 'back yard'),
('roach', '2006-10-09', 'kitchen'),
('bee', '2006-10-10', 'garden'),
('wasp', '2006-10-10', 'porch'),
('ladybug', '2006-10-10', 'front yard'),
('butterfly', '2006-10-11', 'garden'),
('grasshopper', '2006-10-11', 'back yard'),
('termite', '2006-10-11', 'basement'),
('flea', '2006-10-12', 'living room'),
('tick', '2006-10-12', 'front yard'),
('silverfish', '2006-10-12', 'bathroom'),
('earwig', '2006-10-13', 'garage'),
('gnat', '2006-10-13', 'kitchen'),
('firefly', '2006-10-13', 'back yard'),
('dragonfly', '2006-10-14', 'garden'),
('aphid', '2006-10-14', 'front yard'),
('caterpillar', '2006-10-14', 'garden'),
('weevil', '2006-10-15', 'pantry'),
('carpenter ant', '2006-10-15', 'basement'),
('black widow', '2006-10-15', 'garage'),
('brown recluse', '2006-10-16', 'basement'),
('cricket', '2006-10-16', 'living room'),
('housefly', '2006-10-16', 'kitchen'),
('fruit fly', '2006-10-17', 'kitchen'),
('woodlouse', '2006-10-17', 'back yard');mysql> select * from bug order by name, id;
+----+---------------+------------+-------------+
| id | name | date | origin |
+----+---------------+------------+-------------+
| 21 | aphid | 2006-10-14 | front yard |
| 8 | bee | 2006-10-10 | garden |
| 25 | black widow | 2006-10-15 | garage |
| 26 | brown recluse | 2006-10-16 | basement |
| 11 | butterfly | 2006-10-11 | garden |
| 24 | carpenter ant | 2006-10-15 | basement |
| 22 | caterpillar | 2006-10-14 | garden |
| 5 | centipede | 2006-10-09 | garage |
| 27 | cricket | 2006-10-16 | living room |
| 20 | dragonfly | 2006-10-14 | garden |
| 17 | earwig | 2006-10-13 | garage |
| 19 | firefly | 2006-10-13 | back yard |
| 14 | flea | 2006-10-12 | living room |
| 3 | fly | 2006-10-08 | kitchen |
| 29 | fruit fly | 2006-10-17 | kitchen |
| 18 | gnat | 2006-10-13 | kitchen |
| 12 | grasshopper | 2006-10-11 | back yard |
| 28 | housefly | 2006-10-16 | kitchen |
| 10 | ladybug | 2006-10-10 | front yard |
| 6 | millipede | 2006-10-09 | back yard |
| 1 | mosquito | 2006-10-08 | bathroom |
| 4 | moth | 2006-10-09 | bedroom |
| 7 | roach | 2006-10-09 | kitchen |
| 16 | silverfish | 2006-10-12 | bathroom |
| 2 | spider | 2006-10-08 | basement |
| 13 | termite | 2006-10-11 | basement |
| 15 | tick | 2006-10-12 | front yard |
| 9 | wasp | 2006-10-10 | porch |
| 23 | weevil | 2006-10-15 | pantry |
| 30 | woodlouse | 2006-10-17 | back yard |
+----+---------------+------------+-------------+
30 rows in set (0.00 sec)mysql> select * from housewares;
+------------+------------------+
| id | description |
+------------+------------------+
| DIN40672US | dining table |
| KIT00372UK | garbage disposal |
| KIT01729JP | microwave oven |
| BED00038SG | bedside lamp |
| BTH00485US | shower stall |
| BTH00415JP | lavatory |
+------------+------------------+
6 rows in set (0.00 sec)关键修改点:
1. 将自增列serial单独设为主键(MySQL 要求自增列必须是主键)
2. 添加唯一索引UNIQUE (category, country, serial)来满足原复合主键的业务逻辑
3. 保留id列的唯一性约束ALTER TABLE housewares
ADD category VARCHAR(3) NOT NULL FIRST,
ADD serial INT UNSIGNED NOT NULL AUTO_INCREMENT AFTER category,
ADD country VARCHAR(2) NOT NULL AFTER serial,
ADD PRIMARY KEY (serial), -- 将自增列单独设为主键
ADD UNIQUE KEY (category, country, serial), -- 添加唯一约束确保业务逻辑
ADD UNIQUE KEY (id); -- 保持原id唯一性mysql> select * from housewares;
+----------+--------+---------+------------+------------------+
| category | serial | country | id | description |
+----------+--------+---------+------------+------------------+
| | 1 | | DIN40672US | dining table |
| | 2 | | KIT00372UK | garbage disposal |
| | 3 | | KIT01729JP | microwave oven |
| | 4 | | BED00038SG | bedside lamp |
| | 5 | | BTH00485US | shower stall |
| | 6 | | BTH00415JP | lavatory |
+----------+--------+---------+------------+------------------+
6 rows in set (0.00 sec)mysql> update housewares set category = left(id, 3);
Query OK, 6 rows affected (0.01 sec)
Rows matched: 6 Changed: 6 Warnings: 0mysql> update housewares set serial = mid(id, 4, 5);
Query OK, 6 rows affected (0.01 sec)
Rows matched: 6 Changed: 6 Warnings: 0mysql> update housewares set country = right(id, 2);
Query OK, 6 rows affected (0.01 sec)
Rows matched: 6 Changed: 6 Warnings: 0mysql> alter table housewares drop id;
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> select * from housewares;
+----------+--------+---------+------------------+
| category | serial | country | description |
+----------+--------+---------+------------------+
| BED | 38 | SG | bedside lamp |
| KIT | 372 | UK | garbage disposal |
| BTH | 415 | JP | lavatory |
| BTH | 485 | US | shower stall |
| KIT | 1729 | JP | microwave oven |
| DIN | 40672 | US | dining table |
+----------+--------+---------+------------------+
6 rows in set (0.00 sec)mysql> select category, serial, country,-> concat(category, lpad(serial, 5, '0'), country) as id-> from housewares order by category, country, serial;
+----------+--------+---------+------------+
| category | serial | country | id |
+----------+--------+---------+------------+
| BED | 38 | SG | BED00038SG |
| BTH | 415 | JP | BTH00415JP |
| BTH | 485 | US | BTH00485US |
| DIN | 40672 | US | DIN40672US |
| KIT | 1729 | JP | KIT01729JP |
| KIT | 372 | UK | KIT00372UK |
+----------+--------+---------+------------+
6 rows in set (0.00 sec)mysql> alter table housewares-> modify serial int(5) unsigned zerofill not null auto_increment;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 2mysql> select category, serial, country,-> concat(category, serial, country) as id-> from housewares order by category, country, serial;
+----------+--------+---------+------------+
| category | serial | country | id |
+----------+--------+---------+------------+
| BED | 00038 | SG | BED00038SG |
| BTH | 00415 | JP | BTH00415JP |
| BTH | 00485 | US | BTH00485US |
| DIN | 40672 | US | DIN40672US |
| KIT | 01729 | JP | KIT01729JP |
| KIT | 00372 | UK | KIT00372UK |
+----------+--------+---------+------------+
6 rows in set (0.00 sec)mysql> CREATE FUNCTION houseware_id( category varchar(3),-> serial int unsigned,-> country varchar(2))-> returns varchar(10) deterministic-> return concat(category, lpad(serial, 5, '0'), country);
Query OK, 0 rows affected (0.01 sec)mysql> select category, serial, country,-> houseware_id(category, serial, country) as id-> from housewares;
+----------+--------+---------+------------+
| category | serial | country | id |
+----------+--------+---------+------------+
| BED | 00038 | SG | BED00038SG |
| BTH | 00415 | JP | BTH00415JP |
| BTH | 00485 | US | BTH00485US |
| DIN | 40672 | US | DIN40672US |
| KIT | 01729 | JP | KIT01729JP |
| KIT | 00372 | UK | KIT00372UK |
+----------+--------+---------+------------+
6 rows in set (0.00 sec)