说我有下表:
TABLE: widget
- widget_id (not null, unique, auto-increment)
- model_name (PK)
- model_year (PK)
model_name
和model_year
组成了一个复合键。在另一个表中使用widget_id
作为FK有什么问题吗?
答案 0 :(得分:1)
键是可用于唯一标识表中每一行的任意数量的列。
在您显示的示例中,您的窗口小部件表有两个键:
在标准SQL中,外键可以引用引用表上的任何声明的键(主键或唯一键)。我需要检查MySQL的合规性。
来自foreign keys上的MySQL参考手册:
InnoDB允许外键引用任何索引列或列组。但是,在引用的表中,必须有一个索引,其中引用的列被列为相同顺序的第一列。
作为替代方案,如果您希望使用引用表中的复合键,那么该表中有两列对应于model_name和model_year,然后将外键约束声明为:
ALTER TABLE OtherTable ADD CONSTRAINT
FK_OtherTable_Widgets (model_name,model_year)
references Widgets (model_name,model_Year).
Re InnoDB vs MyISAM,在ALTER TABLE
的文档中InnoDB存储引擎支持FOREIGN KEY和REFERENCES子句,它实现了ADD [CONSTRAINT [symbol]] FOREIGN KEY(...)REFERENCES ...(...)。请参见第13.6.4.4节“外键约束”。对于其他存储引擎,将解析子句但忽略这些子句。 CHECK子句被解析但被所有存储引擎忽略。请参见第12.1.17节“CREATE TABLE语法”。接受但忽略语法子句的原因是为了兼容性,以便更容易从其他SQL服务器移植代码,以及运行创建带引用的表的应用程序。请参见第1.8.5节“MySQL与标准SQL的区别”。
答案 1 :(得分:0)
我没有特定于my-sql的经验,但通常使用数据库建模
理解主键和辅助键之间的区别非常重要。 即使很多db(我确实知道Oracle确实)允许指定一个唯一的(简单的或复合的)密钥作为FK目标,这也不被认为是最佳实践。改为使用PK。
对于辅助密钥的FK应仅用于与不受您控制的表格相关联。
在你的特定情况下,我肯定会FK到widget_id:这是因为widget_id应该是你的PK,并且复合体只是唯一的(当然不是null)。这会导致在mane情况下获得更好的性能,因为您只在查询中加入一列,并且通常被认为是最佳做法(google'代理键'以获取更多信息)
答案 2 :(得分:0)
如果没有可以使用的列,MySQL将在列上创建一个索引:
InnoDB需要外国索引 键和引用键,以便 外键检查可以快速而不是 需要进行表扫描。在里面 引用表,必须有一个 索引所在的外键列 被列为第一列 同样的顺序。创建了这样的索引 在引用表上自动 如果它不存在。 (这是在 与一些旧版本形成鲜明对比 必须创建哪些索引 明确地或创造外国的 关键约束会失败。) index_name,如果给定,则用作 如前所述。
http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
答案 3 :(得分:0)
假设您有两张桌子。第一个表格如下:
TABLE: widget
- model_name (PK)
- model_year (PK)
- widget_id (not null, unique, auto-increment)
如果你想创建另一个引用第一个表中唯一记录的表,它应该是这样的:
TABLE B: sprocket
- part_number (PK)
- blah
- blah
- model_name_widget (FK to widget)
- model_year_widget (FK to widget)
- blah
使用复合主键,您必须在FK引用中包含所有键字段,以确保您唯一地指定记录。