【问题标题】:SQL Foreign key constraintsSQL 外键约束
【发布时间】:2013-01-30 03:46:35
【问题描述】:

我有一张员工表:

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) 

【问题讨论】:

  • 错误说明了什么?
  • 哦,对不起。忘记补充了。它说:
  • 错误 1005 (HY0000): 无法创建表 johnson.mgr (errno: 150)
  • johnson.mgr 是什么?尝试使用 [dbo].mgr
  • 我的数据库被称为 johnson,所以我假设该表获得了 johnson.mgr 或其他位置。

标签: mysql foreign-keys


【解决方案1】:

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

您需要像下面这样更改员工表的定义,

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) 
);

并从Mgr表定义中删除Foreign Key子句

【讨论】:

  • 但是这种安排并不意味着 manager 表中的所有 manager 都是 manager,这意味着 employee 表中的所有 manager 都是 manager 表中的 manager,反之亦然。跨度>
  • 请重新访问架构,这听起来让我很困惑
【解决方案2】:

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

因此请检查您是否为 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

【讨论】:

  • 啊哈,这就是原因。我的经理表确实包含 NULL 值和不适合候选键的重复值。无论如何,有人知道为什么吗?也许我只是想确保元组确实存在于另一个表列中?还是谢谢!
  • 在mysql中不允许在sqlserver中检查参考链接
  • @user2069136 minesh 是正确的,您不能在同一列上创建主键和外键。
【解决方案3】:

你想做的事情是有意义的。 如何你不这样做。您需要更改数据库识别经理的方式。现在,它通过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 支持可更新视图的程度。这可能是不可能的。

【讨论】:

  • 你完全正确,我确实想用我的经理表来识别我的经理,并从员工表中引用该表。其他任何事情都只会很奇怪。但是,employee.manager 表中没有任何在employee.number 表中不存在的元组。虽然有几个 NULL 值。例如,已尝试将这些更改为 0,但仍然无法正常工作。也不能删除employee.manager,因为这是查看谁是谁的经理的方式。无论如何,谢谢,我想我必须查看架构。
猜你喜欢
  • 2013-04-10
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 2011-12-11
  • 2015-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多