这是我当前数据库的摘录(改表名字更容易理解):作用域/复合代理键在MySQL
Pet(ownerFK, id, name, age)
Owner(id, name)
哪里id
始终是一个代理键,用auto_increment
创建。
我希望代理键Pet.id
被作为“作用域”的Pet.ownerFK
或换句话说,有一个复合键[ownerFk, id]
作为我的最小键。我想表的行为是这样的:
INSERT Pet(1, ?, "Garfield", 8);
INSERT Pet(1, ?, "Pluto", 12);
INSERT Pet(2, ?, "Mortimer", 1);
SELECT * FROM Pet;
RESULT:
Pet(1, 1, "Garfield", 8)
Pet(1, 2, "Pluto", 12)
Pet(2, 1, "Mortimer", 1)
我目前使用这个feature of MyISAM其中“你可以在一个多列索引中第二列指定AUTO_INCREMENT
在这种情况下,对于AUTO_INCREMENT
列生成的值计算方式为MAX(auto_increment_column) + 1 WHERE prefix=given-prefix
。当你想将数据放入有序组时,这很有用。“
但是,由于各种(也许是显而易见的)原因,我想从MyISAM切换到InnoDB,因为我需要在某些地方进行事务处理。
有什么办法可以实现这种效果InnoDB?
我在这个问题上发现了一些帖子,其中许多人建议在插入之前写入锁定表。我对此并不是很熟悉,但是对于这个问题,这不会是一次表大小写的修改吗?如果可能的话 - 我有一个Owner.current_pet_counter
作为助手字段,我宁愿写安全交易(我从未做过)。
所以其他可接受的解决办法是...
其实我也不需要“作用域” ID是实际键的一部分。我的实际数据库设计使用了一个单独的“永久链接”表,它使用了这个'功能'。我目前使用它作为缺失事务的解决方法。我想下面的替代:
Pet(id, ownerFK, scopedId, name, age), KEY(id), UNIQUE(ownerFK, scopedId)
Owner(id, name, current_pet_counter)
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT @new=current_pet_counter FROM Owner WHERE id = :owner_id;
INSERT Pet(?, :owner_id, @new, "Pluto", 21);
UPDATE Owners SET current_pet_counter = @new + 1 WHERE id = :owner_id;
COMMIT;
我还没有在MySQL的交易/ transactionvars工作,所以我不知道会不会有这一个严重的问题。 注意:我不想重复使用曾经给宠物一次的id
。这就是为什么我不使用MAX()
。 此解决方案是否有任何警告?
我明白了你的观点。我的实际数据库设计有点不同,我也不需要它成为主键的一部分。我用目前正在评估的解决方案更新了这个问题。 – 2009-04-11 16:34:48