4

我正在使用mysql。我有一个设置了 auto_increment 计数器的数据库表。现在由于一个要求,我需要保留起始 100 个 id,并从 101 开始移动所有现有记录,因此当前 id 1 将变为 101,id 2 将变为 102,依此类推。

我可以将记录移动到 101,但问题是如何将 auto_increment 计数器更改为 max(id)+1。

我这里的主要限制是我需要在单个 sql 语句中执行此操作。我无法使用 @counter 保存该值并稍后使用它。

我尝试使用以下查询

ALTER TABLE role AUTO_INCREMENT = (SELECT rd.counter FROM (SELECT (MAX(id) + 1) AS counter FROM role r) rd);

但它不起作用。

4

4 回答 4

11

解析器在您尝试使用它的地方不支持子查询。

这是 MySQL 源代码的摘录,来自 sql/sql_yacc.yy:

create_table_option:
    . . .
    | AUTO_INC opt_equal ulonglong_num

您应该在那里阅读的是AUTO_INCREMENTtable 选项只接受一个文字数字,而不是表达式或子查询或变量或其他任何东西。因此,您根本无法在您所做的同一语句中设置 AUTO_INCREMENT SELECT MAX(id)+1

但你不必这样做。

MySQL 永远不会分配小于表中当前最大值的自动增量 id。因此,如果您有一个 id 值为 102 的表,则分配的下一个值将至少为103。

您甚至可以尝试显式设置 AUTO_INCREMENT=50,但这会自动增加到 MAX(id)+1。

于 2014-10-06T16:36:04.410 回答
3

你在你的问题中说

我这里的主要限制是我需要在单个 sql 语句中执行此操作。我无法使用 @counter 保存该值并稍后使用它。

其实你可以尝试使用动态SQL,看看它是否工作如下:

SELECT (MAX(id) + 1) INTO @counter FROM role;
SET @sql = CONCAT('ALTER TABLE role AUTO_INCREMENT=',@counter);
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

这可能会也可能不会。即使它对您有用,Bill Karwin 的回答也表明它不是必需的,因为 MySQL 已经处理了自动增量值。无需手动执行 MySQL 已经执行的操作。

还要注意比尔帖子的第一行

解析器在您尝试使用它的地方不支持子查询。

在 DBA StackExchange 中写了一篇疯狂的帖子来解释原因

因此,您应该接受比尔的回答,因为最好的办法就是什么都不做。

于 2014-10-06T16:52:44.050 回答
0

根据手册(http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html),当您手动插入或更改 auto_increment 字段中的值时,auto_increment 值将自动调整.

因此,在为您的记录提供新的 id = id+100 之后,您不再需要关心 auto_increment 值......

于 2014-10-06T17:23:14.240 回答
0

作为对@Peter 的回应,您似乎必须在更改现有值后更新 AUTO_INCREMENT 值。以下示例是在 MariaDB 10.0.12 上完成的:

MariaDB [test]> show create table m;
+-------+--------------------------------------------------------+
| Table | Create Table                                           |
+-------+--------------------------------------------------------+
| m     | CREATE TABLE `m` (                                     |
|       |`id` int(10) unsigned NOT NULL AUTO_INCREMENT,          |
|       |`t` varchar(10) NOT NULL DEFAULT '',                    |  
|       |PRIMARY KEY (`id`)                                      |
|       |) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------+
1 row in set (0.00 sec)

MariaDB [test]> insert into m (t) values ('a'),('b');
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [test]> select * from m;
+----+---+
| id | t |
+----+---+
|  1 | a |
|  2 | b |
+----+---+
2 rows in set (0.00 sec)

MariaDB [test]> update m set id=id+10;
Query OK, 2 rows affected (0.05 sec)
Rows matched: 2  Changed: 2  Warnings: 0

MariaDB [test]> select * from m;
+----+---+
| id | t |
+----+---+
| 11 | a |
| 12 | b |
+----+---+
2 rows in set (0.00 sec)

MariaDB [test]> show create table m;
+-------+--------------------------------------------------------+
| Table | Create Table                                           |
+-------+--------------------------------------------------------+
| m     | CREATE TABLE `m` (                                     |
|       |`id` int(10) unsigned NOT NULL AUTO_INCREMENT,          |
|       |`t` varchar(10) NOT NULL DEFAULT '',                    |  
|       |PRIMARY KEY (`id`)                                      |
|       |) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------+
1 row in set (0.00 sec)

MariaDB [test]> insert into m (t) values ('c');
Query OK, 1 row affected (0.04 sec)

MariaDB [test]> select * from m;
+----+---+
| id | t |
+----+---+
|  3 | c |
| 11 | a |
| 12 | b |
+----+---+
3 rows in set (0.00 sec)

MariaDB [test]>
于 2014-10-06T21:54:22.340 回答