SQL外键约束

时间:2013-02-14 10:54:36

标签: mysql foreign-keys

我有一张员工表:

create table employee
(number integer primary key,
 name varchar(20),
 salary integer,
 manager integer,
 birthyear integer,
 startyear integer);

如果经理列是员工经理的员工编号,即几行看起来像这样:

number | name               | salary | manager | birthyear | startyear |

    32 | Smythe, Carol      |   9050 |     199 |      1929 |      1967 |
    33 | Hayes, Evelyn      |  10100 |     199 |      1931 |      1963 |
    35 | Evans, Michael     |   5000 |      32 |      1952 |      1974 |

所以要澄清一下,Michael Evans的经理是Carol Smythe。还有两件事,这个表上没有外键约束,管理器列中有几个NULL值。 现在,我想创建一个包含所有管理器的Managers表。我会做这样的事情;

create table Mgr(
 Mgr_id INTEGER PRIMARY KEY,
 bonus INTEGER,
 FOREIGN KEY (Mgr_id) REFERENCES employee(manager)); 

BUT;这不起作用,我得到一个错误。有人可以解释一下原因吗?找了答案,但找不到任何好的解释。提前致谢。

ERROR:

ERROR 1005 (HY0000): Can´t create table johnson.mgr (errno: 150) 

3 个答案:

答案 0 :(得分:0)

外键中的对应列和引用的键必须具有相似的内部数据类型,以便可以在不进行类型转换的情况下对它们进行比较。整数类型的大小和符号必须相同。字符串类型的长度不必相同。对于非二进制(字符)字符串列,字符集和排序规则必须相同。

因此,请检查您是否为managerId表提供了正确的数据类型。

必须满足这些条件才能得到错误150:

  1. 这两个表必须是ENGINE = InnoDB。
  2. 这两个表必须具有相同的字符集。
  3. 父表和FK列中的PK列必须是相同的数据类型。
  4. 父表和FK列中的PK列(如果它们具有定义排序规则类型)必须具有相同的排序规则类型;
  5. 如果外键表中已有数据,则FK列值必须与父表PK列中的值匹配。
  6. 另一个问题是您在同一列上创建外键和主键

    希望这有帮助

    参考http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html

答案 1 :(得分:0)

您正尝试在同一字段和表格上创建主键和外键。

您需要更改员工表的定义,如下所示

create table employee
(number integer primary key,
 name varchar(20),
 salary integer,
 manager integer,
 birthyear integer,
 startyear integer
FOREIGN KEY (manager) REFERENCES Mgr(Mgr_id) 
);

Foreign Key表定义中删除 Mgr 子句

答案 2 :(得分:0)

你想做什么是有道理的。 你如何这样做不会。您需要更改数据库识别管理器的方式。现在,它通过employee.manager中的值来识别经理。完成后,它将按经理中的行识别经理。

确保您首先拥有可用的数据。查找不再在employee表中的id号。试试这个。

select manager 
from employee 
where manager not in (select number 
                      from employee);

返回的每一行都代表一个错误 - 一个经理的身份证号码,员工身上没有相应的行。在你取得很大进展之前,你必须先解决这些问题。

修复这些错误后,创建表格Mgr。

create table Mgr (
  Mgr_id INTEGER PRIMARY KEY,
  bonus INTEGER NOT NULL DEFAULT 0,
  FOREIGN KEY (Mgr_id) REFERENCES employee(manager)
); 

使用查询填充经理。这些方面的东西应该有效。

insert into Mgr (Mgr_id) 
select distinct manager 
from employee;

使用正确的奖金值更新该表格。如果您没有将数据存储在某个地方,您可能必须手动执行此操作。

就数据库而言,您可以删除employee.manager列。并且应该删除该列,但现在不行。您必须考虑将认为您可以通过查看employee表来识别经理的应用程序代码会发生什么。

  • 您可以删除列,让应用程序失败,直到它们被修复。
  • 您可以警告所有应用程序开发人员,例如,3月1日将进行这些更改,他们最好准备好代码。
  • 您可以进行更改,保留列,警告应用程序开发人员,并采取措施防止更改employee.manager。
  • 您可以进行这些更改,重命名employee表,并创建具有旧结构的可更新视图(您需要加入员工和经理)和名称“employee”。这个选项接近理想 - 它不需要更改应用程序代码 - 但我不确定MySQL支持可更新视图的程度。这可能是不可能的。