板凳-------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', '[email protected]'),
(3, 'user3', '[email protected]'),
(7, 'user7', '[email protected]'),
(10, 'user10', '[email protected]');
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()
BEGIN
    DECLARE 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: LOOP
        FETCH cur INTO old_id;
        IF done THEN
            LEAVE 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/138009452

mysql> 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: 0

mysql>
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: 0

mysql> -- 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: 0

mysql> 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: 0

mysql> update housewares set serial = mid(id, 4, 5);
Query OK, 6 rows affected (0.01 sec)
Rows matched: 6  Changed: 6  Warnings: 0

mysql> update housewares set country = right(id, 2);
Query OK, 6 rows affected (0.01 sec)
Rows matched: 6  Changed: 6  Warnings: 0

mysql> alter table housewares drop id;
Query OK, 0 rows affected (0.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> 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: 2

mysql> 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)

你可能感兴趣的:(mysql,学习,数据库)