我知道MySQL将auto_increment列限制为主键。为什么是这样?我的第一个想法是这是对性能的限制,因为在某个位置可能必须锁定一些计数器表才能获得此值。
为什么同一张表中不能有多个auto_increment列?
谢谢。
我知道MySQL将auto_increment列限制为主键。为什么是这样?我的第一个想法是这是对性能的限制,因为在某个位置可能必须锁定一些计数器表才能获得此值。
为什么同一张表中不能有多个auto_increment列?
谢谢。
Answers:
为什么要有一个不是主键的auto_increment列?
根据定义,如果您希望一列是auto_increment,则不会在该列中存储有意义的数据。唯一有意义的存储无意义信息的情况是您希望拥有合成主键的特殊情况。在那种情况下,信息的缺乏是有好处的,因为没有风险,因为将来某个实体会改变某些实体的某些属性,因此将来有人会出现这种情况。
在同一表中具有多个auto_increment列似乎更奇怪。两列将具有相同的数据-它们是由相同的算法生成的,并且毕竟是在同一时间填充的。我想您可以提出一个实现,如果有足够的并发会话,它们可能会稍微不同步。但是我无法想象这在应用程序中将如何有用。
实际上,AUTO_INCREMENT属性不仅限于PRIMARY KEY(不再是)。在旧版本中曾经如此-肯定是3.23,可能是4.0。自4.1以来的所有版本的MySQL手册仍然是这样的
每个表只能有一个AUTO_INCREMENT列,必须对其建立索引,并且不能具有DEFAULT值。
因此,您确实可以在不是主键的表中包含一个AUTO_INCREMENT列。如果这有意义,则是另一个话题。
我还应该提到,AUTO_INCREMENT列应始终为整数类型(技术上也允许使用浮点类型),并且应为UNSIGNED。SIGNED类型不仅浪费键空间的一半,而且如果偶然插入负值也会导致巨大的问题。
最后,MySQL 4.1和更高版本为BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE 定义了类型别名SERIAL。
这是一个有趣的问题,因为不同的数据库具有提供auto_increment的独特方法。
MySQL:仅生成一个auto_increment键来唯一标识表中的一行。为什么没有很多解释,只是实现。根据数据类型,auto_increment值由数据类型的长度(以字节为单位)固定:
内部数据类型串行用于从1到2,147,483,647的自动递增。使用bigserial允许更大的范围。
Oracle:名为SEQUENCE的模式对象可以通过简单地调用nextval函数来创建新数字。PostgreSQL也有这样的机制。
这是一个很好的URL,它提供了其他DB如何指定它们的方法:http : //www.w3schools.com/sql/sql_autoincrement.asp
现在关于您的问题,如果您真的想在单个表中具有多个auto_increment列,则必须进行模拟。
必须模仿的两个原因:
您将如何模仿它?
使用只有一个auto_increment列的多个表,并将它们映射到目标表中的所需列。这是一个例子:
复制并粘贴此示例:
use test
DROP TABLE IF EXISTS teacher_popquizzes;
CREATE TABLE teacher_popquizzes
(
teacher varchar(20) not null,
class varchar(20) not null,
pop_mon INT NOT NULL DEFAULT 0,
pop_tue INT NOT NULL DEFAULT 0,
pop_wed INT NOT NULL DEFAULT 0,
pop_thu INT NOT NULL DEFAULT 0,
pop_fri INT NOT NULL DEFAULT 0,
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO teacher_popquizzes (teacher,class) VALUES
('mr jackson','literature'),
('mrs andrews','history'),
('miss carroll','spelling');
DROP TABLE IF EXISTS mon_seq;
DROP TABLE IF EXISTS tue_seq;
DROP TABLE IF EXISTS wed_seq;
DROP TABLE IF EXISTS thu_seq;
DROP TABLE IF EXISTS fri_seq;
CREATE TABLE mon_seq
(
val INT NOT NULL DEFAULT 0,
nextval INT NOT NULL DEFAULT 1,
PRIMARY KEY (val)
);
CREATE TABLE tue_seq LIKE mon_seq;
CREATE TABLE wed_seq LIKE mon_seq;
CREATE TABLE thu_seq LIKE mon_seq;
CREATE TABLE fri_seq LIKE mon_seq;
BEGIN;
INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM mon_seq;
UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 2;
COMMIT;
BEGIN;
INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM tue_seq;
UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 1;
COMMIT;
BEGIN;
INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM wed_seq;
UPDATE teacher_popquizzes SET pop_wed = pop_wed + 1 WHERE id = 2;
COMMIT;
SELECT * FROM teacher_popquizzes;
这将为教师创建一个流行测验表。我还创建了五个序列模拟器,每个上学日每天一个。每个序列仿真器通过在val列中插入值0来工作。如果序列仿真器为空,则以val 0,nextval 1开头。如果不是,则nextval列递增。然后,您可以从序列仿真器中获取nextval列。
这是示例的示例结果:
mysql> CREATE TABLE teacher_popquizzes
-> (
-> teacher varchar(20) not null,
-> class varchar(20) not null,
-> pop_mon INT NOT NULL DEFAULT 0,
-> pop_tue INT NOT NULL DEFAULT 0,
-> pop_wed INT NOT NULL DEFAULT 0,
-> pop_thu INT NOT NULL DEFAULT 0,
-> pop_fri INT NOT NULL DEFAULT 0,
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.11 sec)
mysql> INSERT INTO teacher_popquizzes (teacher,class) VALUES
-> ('mr jackson','literature'),
-> ('mrs andrews','history'),
-> ('miss carroll','spelling');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> DROP TABLE IF EXISTS mon_seq;
Query OK, 0 rows affected (0.06 sec)
mysql> DROP TABLE IF EXISTS tue_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS wed_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS thu_seq;
Query OK, 0 rows affected (0.05 sec)
mysql> DROP TABLE IF EXISTS fri_seq;
Query OK, 0 rows affected (0.07 sec)
mysql> CREATE TABLE mon_seq
-> (
-> val INT NOT NULL DEFAULT 0,
-> nextval INT NOT NULL DEFAULT 1,
-> PRIMARY KEY (val)
-> );
Query OK, 0 rows affected (0.12 sec)
mysql> CREATE TABLE tue_seq LIKE mon_seq;
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE TABLE wed_seq LIKE mon_seq;
Query OK, 0 rows affected (0.08 sec)
mysql> CREATE TABLE thu_seq LIKE mon_seq;
Query OK, 0 rows affected (0.07 sec)
mysql> CREATE TABLE fri_seq LIKE mon_seq;
Query OK, 0 rows affected (0.14 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT nextval INTO @pop FROM mon_seq;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT nextval INTO @pop FROM wed_seq;
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_wed = pop_wed + 1 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT * FROM teacher_popquizzes;
+--------------+------------+---------+---------+---------+---------+---------+----+
| teacher | class | pop_mon | pop_tue | pop_wed | pop_thu | pop_fri | id |
+--------------+------------+---------+---------+---------+---------+---------+----+
| mr jackson | literature | 0 | 1 | 0 | 0 | 0 | 1 |
| mrs andrews | history | 0 | 1 | 1 | 0 | 0 | 2 |
| miss carroll | spelling | 0 | 0 | 0 | 0 | 0 | 3 |
+--------------+------------+---------+---------+---------+---------+---------+----+
3 rows in set (0.00 sec)
mysql>
如果在MySQL中确实需要多个自动增量值,则这是模拟它的最接近方法。
试试看 !!!
更新2011-06-23 21:05
我只是在示例中注意到我不使用@pop值。
这次我将'pop_tue = pop_tue + 1'替换为'pop_tue = @pop'并重试了示例:
mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS teacher_popquizzes;
Query OK, 0 rows affected (0.05 sec)
mysql> CREATE TABLE teacher_popquizzes
-> (
-> teacher varchar(20) not null,
-> class varchar(20) not null,
-> pop_mon INT NOT NULL DEFAULT 0,
-> pop_tue INT NOT NULL DEFAULT 0,
-> pop_wed INT NOT NULL DEFAULT 0,
-> pop_thu INT NOT NULL DEFAULT 0,
-> pop_fri INT NOT NULL DEFAULT 0,
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO teacher_popquizzes (teacher,class) VALUES
-> ('mr jackson','literature'),
-> ('mrs andrews','history'),
-> ('miss carroll','spelling');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> DROP TABLE IF EXISTS mon_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS tue_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS wed_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS thu_seq;
Query OK, 0 rows affected (0.01 sec)
mysql> DROP TABLE IF EXISTS fri_seq;
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TABLE mon_seq
-> (
-> val INT NOT NULL DEFAULT 0,
-> nextval INT NOT NULL DEFAULT 1,
-> PRIMARY KEY (val)
-> );
Query OK, 0 rows affected (0.08 sec)
mysql> CREATE TABLE tue_seq LIKE mon_seq;
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE TABLE wed_seq LIKE mon_seq;
Query OK, 0 rows affected (0.13 sec)
mysql> CREATE TABLE thu_seq LIKE mon_seq;
Query OK, 0 rows affected (0.11 sec)
mysql> CREATE TABLE fri_seq LIKE mon_seq;
Query OK, 0 rows affected (0.08 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.01 sec)
mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_tue = @pop WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_tue = @pop WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.01 sec)
mysql> SELECT nextval INTO @pop FROM wed_seq;
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE teacher_popquizzes SET pop_wed = @pop WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT * FROM teacher_popquizzes;
+--------------+------------+---------+---------+---------+---------+---------+----+
| teacher | class | pop_mon | pop_tue | pop_wed | pop_thu | pop_fri | id |
+--------------+------------+---------+---------+---------+---------+---------+----+
| mr jackson | literature | 0 | 2 | 0 | 0 | 0 | 1 |
| mrs andrews | history | 0 | 1 | 1 | 0 | 0 | 2 |
| miss carroll | spelling | 0 | 0 | 0 | 0 | 0 | 3 |
+--------------+------------+---------+---------+---------+---------+---------+----+
3 rows in set (0.00 sec)
mysql>
bigserial
数据类型,该数据类型提供的范围远远大于2,147,483,647