這是我當前數據庫的摘錄(改表名字更容易理解):作用域/複合代理鍵在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