0

我有一张员工表:

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

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

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。还有两件事,该表上没有外键约束,并且 manager 列中有几个 NULL 值。现在,我想创建一个包含所有经理的经理表。我会做这样的事情;

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

但; 这不起作用,我得到一个错误。有人可以解释为什么吗?已搜索答案,但找不到任何好的解释。提前致谢。

错误:

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

3 回答 3

0

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

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

必须满足这些条件才能不出现错误 150:

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

另一个问题是您在同一列上创建外键和主键

希望这可以帮助

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

于 2013-02-14T11:48:33.443 回答
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

于 2013-02-14T11:52:26.620 回答
0

想做的事情是有道理的。你怎么做的没有。您需要更改数据库识别经理的方式。现在,它通过employee.manager 中的值来识别经理。完成后,它将通过 Mgr 中的行来识别经理。

首先确保您有可用的数据。查找不再在员工表中的 ID 号。尝试这个。

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

返回的每一行都代表一个错误——一个经理的 ID 号,在员工中没有对应的行。您必须先解决这些问题,然后才能取得很大进展。

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

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

使用查询填充 Mgr。这些方面的东西应该起作用。

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

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

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

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