情境:
我有一个引用两个外键的表,并且对于这些外键的每个唯一组合,都有自己的auto_increment列。我需要实现一个复合键,它将使用这三个组合将一行标识为唯一(一个外键和一个auto_increment列,另一个列具有非唯一值)
表格
CREATE TABLE `issue_log` (
`sr_no` INT NOT NULL AUTO_INCREMENT ,
`app_id` INT NOT NULL ,
`test_id` INT NOT NULL ,
`issue_name` VARCHAR(255) NOT NULL ,
primary key (app_id, test_id,sr_no)
);
当然,我的查询必定有问题,因为抛出的错误是:
错误1075:表定义不正确;只有一个汽车 列,它必须定义为键
我想要实现的目标:
我有一个Application Table(以app_id为主键),每个Application都有一组要解决的问题,每个Application都有多个测试(所以test_id col) 对于唯一的app_id和test_id,sr_no col应该递增。
即。表中的数据应如下所示:
数据库引擎是InnoDB。 我希望尽可能简单地实现这一目标(即如果可能的话,避免使用触发器/程序 - 这是针对其他问题的类似案例的建议)。
答案 0 :(得分:27)
您不能让MySQL为InnoDB表自动执行此操作 - 您需要使用触发器或过程,或者使用其他数据库引擎(如MyISAM)。只能对单个主键执行自动递增。
以下内容应该有效
DELIMITER $$
CREATE TRIGGER xxx BEFORE INSERT ON issue_log
FOR EACH ROW BEGIN
SET NEW.sr_no = (
SELECT IFNULL(MAX(sr_no), 0) + 1
FROM issue_log
WHERE app_id = NEW.app_id
AND test_id = NEW.test_id
);
END $$
DELIMITER ;
答案 1 :(得分:7)
您可以使用myISAM和BDB引擎执行此操作。 InnoDB不支持此功能。引自MySQL 5.0参考手册。
对于MyISAM和BDB表,您可以在多列索引的辅助列上指定AUTO_INCREMENT。在这种情况下,AUTO_INCREMENT列的生成值计算为MAX(auto_increment_column)+ 1 WHERE prefix = given-prefix。
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
答案 2 :(得分:3)
您可以使用sr_no
复合键app_id
,test_id
& sr_no
。您不能在CREATE TABLE IF NOT EXISTS `issue_log` (
`sr_no` int(11) NOT NULL,
`app_id` int(11) NOT NULL,
`test_id` int(11) NOT NULL,
`issue_name` varchar(255) NOT NULL,
UNIQUE KEY `app_id` (`app_id`,`test_id`,`sr_no`)
) ENGINE=InnoDB ;
中使用增量,因为这不是唯一的。
{{1}}
我在unique中注释了唯一约束违规,以演示(删除架构第22行中的#并重建架构)
答案 3 :(得分:3)
我不完全理解test_id
列上的增量要求,但是如果你想要一个〜自动增量序列重新启动(app_id
,test_id
)的每个唯一组合,你可以在同一个表中执行INSERT ... SELECT,如下所示:
mysql> INSERT INTO `issue_log` (`sr_no`, `app_id`, `test_id`, `issue_name`) SELECT
IFNULL(MAX(`sr_no`), 0) + 1 /* next sequence number */,
3 /* desired app_id */,
1 /* desired test_id */,
'Name of new row'
FROM `issue_log` /* specify the table name as well */
WHERE `app_id` = 3 AND `test_id` = 1 /* same values as in inserted columns */
这假定表定义没有声明的AUTO_INCREMENT列。您实际上是使用IFNULL(MAX())+ 1子句模拟自动增量行为,但手动仿真适用于任意列,与内置自动增量不同。
请注意,INSERT ... SELECT是单个查询,可确保操作的原子性。 InnoDB将对适当的索引进行间隙锁定,并且许多并发进程可以执行此类查询,同时仍然生成非冲突序列。
答案 4 :(得分:0)
只需在自动增量列上添加密钥(sr_no
)
CREATE TABLE `issue_log` (
`sr_no` INT NOT NULL AUTO_INCREMENT ,
`app_id` INT NOT NULL ,
`test_id` INT NOT NULL ,
`issue_name` VARCHAR(255) NOT NULL ,
primary key (app_id, test_id,sr_no),
key (`sr_no`)
);
答案 5 :(得分:0)
为什么不尝试将声明字段的位置更改为主键,因为当您使用“auto_increment”时,它必须作为第一个引用。就像下面的例子
CREATE TABLE `issue_log` (
`sr_no` INT NOT NULL AUTO_INCREMENT ,
`app_id` INT NOT NULL ,
`test_id` INT NOT NULL ,
`issue_name` VARCHAR(255) NOT NULL ,
primary key (sr_no,app_id, test_id)
);