我应该多么避免在SQL中使用代理主键?
简短的故事
我遇到了一个技术问题,涉及到一个第三方库,我发现自己很难找到简单的解决办法,除了创建一个替代键(尽管我其实根本不需要它)。我在网上读了很多文章,劝告不要使用替代键,所以我有点困惑,不知道我这样做是否合适。
长篇故事
我需要指定一个主键,因为我在使用SQLAlchemy这个对象关系映射工具(ORM),它是需要主键的。我不能简单地在__mapper_args__
中设置主键,因为这个类是用classobj构建的,我还没找到办法在主键定义中引用一个尚未存在的类的字段。另一个问题是,主键的自然对应是一个复合键,但这个复合键对我使用的MySQL版本来说太长了(而且一般来说,使用这么长的主键也是个坏主意)。
3 个回答
我在一个数据库中使用替代键,并且用sqlalchemy进行反射操作。这样做的好处是,你可以更轻松地管理表格或模型中的外键和关系。而且,关系型数据库管理系统(rdbms)能更有效地处理数据。不过,缺点是可能会出现数据不一致的问题,比如重复数据。为了避免这种情况,一定要在你的自然键上使用唯一约束。
现在,我从你的长篇故事中了解到,由于mysql的限制,你无法强制执行这种唯一性。对于长的复合键,mysql会出现问题。我建议你换用postgresql。
使用替代键可以让你在本来应该避免重复的情况下,还是出现了重复。没错,所以你应该同时使用替代键和自然键,而不是只用替代键。你似乎犯的错误不是在于使用替代键,而是认为表格只需要一个键。确保你创建所有需要的键,以保证数据的完整性。
不过,在这种情况下,似乎是ORM软件的缺陷(显然不能使用复合键)才是真正导致你问题的原因。很遗憾,像这样的软件限制让你不得不创建一些本来不需要的键。也许你可以考虑换用其他软件。
我在使用ORM(对象关系映射)的时候,总是会创建替代键(surrogate keys),或者说我让ORM帮我创建它们。替代键能解决很多问题,而且不会引入什么(主要的)问题。
所以,你已经意识到网上有一些“论文”提到避免使用替代键的合理理由,并且可能有更好的方法来处理这个问题。
现在,在你的源代码里写上“# TODO: 找个办法避免使用替代键
”,然后去做其他的工作吧。