MySQL的术语“约束”与“外键”的区别?
我在这里查看MySQL文档,并试图理清FOREIGN KEY和CONSTRAINT之间的区别。 我以为FK 是一个约束,但是文档似乎像他们是独立的东西一样谈论他们。
创buildFK的语法是(部分)…
[CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name, ...) REFERENCES tbl_name (index_col_name,...)
所以“CONSTRAINT”子句是可选的。 你为什么要包括它或不包括它? 如果你离开它MySQL是否创build一个外键,但不是一个约束? 还是说它更像是一个“CONSTRAINT”只不过是你FK的一个名字,所以如果你不指定它,你会得到一个匿名的FK?
任何澄清将不胜感激。
谢谢,
阮经天
是的,外键是一种约束。 MySQL对约束有不均衡的支持:
-
PRIMARY KEY
:是表约束和列约束。 -
FOREIGN KEY
:是表约束,但只有InnoDB和BDB存储引擎; 否则parsing,但忽略。 -
CHECK
:已parsing,但在所有存储引擎中都被忽略。 -
UNIQUE
:是表约束和列约束。 -
NOT NULL
:是列约束。 -
DEFERRABLE
和其他约束属性:不支持。
CONSTRAINT
子句允许您明确指定约束条件,以便使元数据更具可读性,或者在要删除约束条件时使用该名称。 SQL标准要求CONSTRAINT
子句是可选的。 如果不发表,RDBMS会自动创build一个名称,名称取决于实现。
通常(不需要MySQL),外键是约束,但约束并不总是外键。 考虑主要的约束,独特的约束等
回到具体的问题,你是正确的,省略CONSTRAINT [符号]部分将创build一个自动生成的FK名称。
不能回答MySQL,但FK的约束。 任何迫使你的数据进入某种条件的东西都是一个约束。 有几种约束,唯一,主键,检查和外键都是约束条件。 也许MySQL有其他的。
有时在命令中允许使用单词,但不要求像DELETE语句中的FROM这样的可读性。
如果我没有错,约束需要索引,所以当你创build一个外键约束时,MySQL也会自动创build一个索引。
到目前为止,我们的CREATE TABLE DDL是这种格式的 – 注意我们使用的UNIQUE KEY和FOREIGN KEY定义语法。
CREATE TABLE my_dbschema.my_table ( id INT unsigned auto_increment PRIMARY KEY, account_nbr INT NOT NULL, account_name VARCHAR(50) NOT NULL, active_flg CHAR(1) NOT NULL DEFAULT 'Y', vendor_nbr INT NOT NULL, create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp, create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp, last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', UNIQUE KEY uk1_my_table(account_nbr, account_name), FOREIGN KEY fk1_my_table(vendor_nbr) REFERENCES vendor(vendor_nbr) );
在这种格式下,MySQL正在自动创build名称为uk1_my_table和fk1_my_table的INDEX-es; 但FK对象名称是不同的 – my_table_ibfk_1(即tablename_ibfk_N – 系统定义)。 所以ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table
将不起作用(因此,令人沮丧和提高警报),因为没有FK数据库对象的名称。
这里是一个替代的DDL格式的constarints(参考: https ://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html): –
CREATE TABLE my_dbschema.my_table ( id INT unsigned auto_increment PRIMARY KEY, account_nbr INT NOT NULL, account_name VARCHAR(50) NOT NULL, active_flg CHAR(1) NOT NULL DEFAULT 'Y', vendor_nbr INT NOT NULL, create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp, create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp, last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', CONSTRAINT uk1_my_table UNIQUE KEY (account_nbr, account_name), CONSTRAINT fk1_my_table FOREIGN KEY (vendor_nbr) REFERENCES vendor(vendor_nbr) );
在这种格式下,MySQL仍然自动创build名称为uk1_my_table和fk1_my_table的INDEX-es,但是FK对象名称并没有什么不同,正如在DDL中提到的那样,它是fk1_my_table。 所以ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table
工作,但是留下了同名的INDEX。
而且,请注意, ALTER TABLE my_table DROP INDEX fk1_my_table
最初将无法工作(当FK尚未被删除时),并显示错误消息,指出正在使用FK! 如果DROP FK命令已经成功执行,则只有DROP INDEX才起作用。
希望这解释和帮助解决混乱。
这可能是MySQL中最令人困惑的topìc。
很多人都说,例如,“PRIMARY KEY”,“FOREIGN KEY”和“UNIQUE”键实际上是索引! (MySQL官方文档包含在这里)
另一方面,许多其他人则说他们是相当有限的(这是有道理的,因为当你使用它们时,你真的对受影响的列施加限制)。
如果他们真的是索引,那么使用约束条件来给它起个名字有什么意义呢,因为当你创build索引时你应该能够使用这个索引的名字?
例:
… FOREIGN KEY index_name(col_name1,col_name2,…)
如果FOREIGN KEY是一个索引,那么我们应该可以使用index_name来处理它。 但是,我们不能。
但如果它们不是索引,而是使用索引来工作的实际限制,那么这是有道理的。
无论如何,我们都不知道。 其实没有人知道