2011-09-08 142 views
4

MySQL不支持多个自动增量列。如何创建另一个MySQL自动增量列?

CREATE TABLE IF NOT EXISTS `parts` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `order` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

是否有另一种解决方案来自动进行的列order增加值当我插入一个新的记录?

+0

还有一个“rowid”,它代表每个插入的行:选择部分的rowid,其中id = somenumber – Louis

+0

http://stackoverflow.com/questions/7085275/multiple-auto-increment-in-mysql –

+1

所以,你想两个字段都是auto_incemented,并在所有行中存储完全相同的值? –

回答

5

为什么你想要2个字段自动增加 - 它们将有相同的值,所以你可以使用ID。

如果您希望让您的发票/订单具有连续编号,那么您应该将该编号保存在单独的表格中,并有单独的逻辑来更新这些编号。

+4

他们可能会相互抵消,或者OP可能会在自动增量中“关闭漏洞”。这篇文章是MSSQL,但可能是相关的。 http://stackoverflow.com/questions/349092/can-a-sql-server-table-have-two-identity-columns – StuartLC

+0

如果你自己没有指定一个,MySQL只会分配一个自动递增的id。因此,您可以使用它来自动分配一个新的值,如果没有填入任何值,但仍允许显式选择任何现有的值。所以他们不必每个记录都一样。 –

0

考虑添加的第二表为order柱:

CREATE TABLE IF NOT EXISTS `parts_order` (
    `order` int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`order`) 
) ENGINE=MyISAM; 

实例:

-- First we insert a new empty row into `parts_order` 
INSERT INTO `parts_order` VALUES (NULL); 
-- Next we insert a new row into `parts` with last inserted id from `parts_order` 
INSERT INTO `parts` SET `name` = "new name", `order` = LAST_INSERT_ID(); 

此方法不需要交易也不锁定。

+0

表是MyISAM,为什么事务呢? –

+0

如果没有交易或锁定,你无法做到这一点。 – sanmai

+0

如果您仔细阅读,您会发现表格类型是MyISAM。该表类型不支持事务。无论是否“好”,交易**都不会在MyISAM中起作用。 –

5

您可以通过发出另一个查询来增加order,或者您可以创建一个触发器来执行此操作。不管你做什么,为了编程世界的理智 - 不要使用保留字作为列名,例如order :)

+13

为了编程世界的智慧,您必须使用反引号来避免列名,并且永远不会对保留字有任何问题。 – sanmai

1

我建议你只设置order字段为AUTO_INCREMENT;并手动计算id字段的新值。这是一个例子 -

CREATE TABLE IF NOT EXISTS `parts` (
    `id` int(11) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `order` int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`, `order`) 
) ENGINE=myisam DEFAULT CHARSET=latin1 AUTO_INCREMENT=1; 

-- Add some new rows with manually auto-incremented id: 

-- SELECT COALESCE(MAX(id), 0) + 1 INTO @next_id FROM parts; 
-- INSERT INTO parts VALUES(@next_id, '', NULL); 
-- SELECT COALESCE(MAX(id), 0) + 1 INTO @next_id FROM parts; 
-- INSERT INTO parts VALUES(@next_id, '', NULL); 

    INSERT INTO parts SELECT COALESCE(MAX(id), 0) + 1, '', NULL FROM parts; 
    INSERT INTO parts SELECT COALESCE(MAX(id), 0) + 1, '', NULL FROM parts; 

SELECT * FROM parts; 
+----+------+-------+ 
| id | name | order | 
+----+------+-------+ 
| 1 |  |  1 | 
| 2 |  |  1 | 
+----+------+-------+ 


-- Add some new rows for specified `id`, the value for `order` field will be set automatically: 

INSERT INTO parts VALUES(2, '', NULL); 
INSERT INTO parts VALUES(2, '', NULL); 

+----+------+-------+ 
| id | name | order | 
+----+------+-------+ 
| 1 |  |  1 | 
| 2 |  |  1 | 
| 2 |  |  2 | 
| 2 |  |  3 | 
+----+------+-------+ 
+0

如果没有锁定或交易,这将无法正常工作。 – sanmai

+0

是的,表格可以锁定。 ...我编辑了我的答案,现在SELECT和INSERT语句被替换为一个INSERT ... SELECT语句;在这种情况下,我们可以不锁定地完成它。 – Devart

+0

INSERT ... SELECT在比赛条件下不安全 – sanmai

3

根据您的原始表:

CREATE TABLE IF NOT EXISTS `parts` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `order` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

这个怎么样单一插入查询:

INSERT INTO `parts` (`name`, `order`) 
SELECT 'name of new part', IFNULL(MAX(`order`), 0) + 1 FROM parts; 

如果说法属实,这不是一个安全查询,可以简单介绍如下表锁:

LOCK TABLES `parts` AS t1 WRITE, `parts` WRITE; 

INSERT INTO `parts` (`name`, `order`) 
SELECT 'name of new part', IFNULL(MAX(`order`), 0) + 1 FROM `parts` AS t1; 

UNLOCK TABLES; 
+0

如果没有锁定或交易,它将无法正常工作。 – sanmai

+1

无法对此查询产生任何问题; 50个并行查询,并且不会导致任何重复。是否有源代表说这种查询会导致问题? – HenrikW

+1

@sanmai为我的答案添加了表锁。如果没有表锁定,这个单个查询何时会导致问题,我们仍然想解释一下。 – HenrikW

相关问题