我在MySQL中创建以下表时遇到错误。
这是错误:
ERROR 1005 (HY000): Can't create table 'Works' (errno: 150)
你们可以看看Works()的外键吗?如果你看到任何会导致这个错误发生的奇怪事情,请告诉我吗?
这是我的整体架构:
create table Employee(
Lastname varchar(10),
FirstName varchar(10),
MidInitial char(1),
gender char(1),
street varchar(10),
city varchar(10),
primary key(Lastname, FirstName, MidInitial));
create table company(
company_name varchar(20),
city varchar(10),
primary key(company_name));
create table Works(
Lastname varchar(10),
FirstName varchar(10),
MidInitial char(1),
company_name varchar(20),
salary numeric(8,2),
primary key(Lastname, FirstName, MidInitial, company_name),
foreign key(Lastname, FirstName, MidInitial) references Employee,
foreign key(company_name) references company);
非常感谢!
答案 0 :(得分:3)
您的错误是由于错误的外键语法引起的。
但是,我认为你应该使用ID字段而不是字符串复合主键。您的方法存在一些问题......
与使用整数(ID)字段加入(更难= =更多处理时间)相比,这会使DB更难连接表。
即使使用中间名,也可以有多个同名的人。
如果您需要更改某人的姓名,会发生什么?或者因为存储错误或者他们结婚或者其他事情......这意味着您将拥有不仅要更新您的employee
表,还要更新works
表和您将该名称用作外键的任何其他表。
看看这个: http://sqlfiddle.com/#!2/2dc8c/3/0
我已为每个表添加了表格ID 。这是一个unsigned int
,这意味着它不能是负面的(因为这没有多大意义)。它也是auto_increment
,这意味着每次向表中添加一行时,此ID将自动生成并上升1.
create table Employee (
Employee_ID int unsigned auto_increment primary key,
Lastname varchar(10),
FirstName varchar(10),
MidInitial char(1),
gender char(1),
street varchar(10),
city varchar(10),
unique (Lastname, FirstName, MidInitial)
);
你可以像这样添加这个表:
insert into Employee (Employee_ID, LastName, FirstName, MidInitial)
values (null, 'Smith', 'John', 'K');
null
将成为自动生成的ID。它对于每一行都是唯一的。
此外,唯一约束表示这些字段的组合在表格中必须是唯一的。但是,如果有足够大的公司,我打赌两个人会有相同的名字。在现实生活中,我建议删除这个独特的约束。
我对公司表进行了类似的更改......
create table company(
company_ID int unsigned auto_increment primary key,
company_name varchar(20),
city varchar(10),
unique (company_name)
);
可以添加如下内容:
insert into company values (null, 'Taco Bell', 'Paris');
所以...对于works
....而不是在此表中一遍又一遍地存储每个人的全名和完整的公司名称,现在我们只需要存储ID'秒。
create table Works (
works_id int unsigned auto_increment primary key,
employee_id int unsigned,
compay_id int unsigned,
salary numeric(8,2),
foreign key (employee_id) references Employee (employee_id),
foreign key (compay_id) references company (company_id)
);
您可以像这样添加works
:
insert into Works values (null, 1, 1, '10.00');
由于John Smith是我们的第一个员工,他的Employee_ID将是1.要验证,请尝试select * from Employee where FirstName='John' and LastName='Smith'
。 Taco Bell也会得到company_id = 1.通过将这些值插入works
,这意味着John现在在Taco Bell工作。
我还建议您在工作表中添加start_date
和end_date
以及job_title
等字段。而且你也想特别考虑这个表的任何独特约束。人们可以不止一次为同一家公司工作。他们也可以有不同的工作。
如果要恢复数据,可以使用如下查询:
select FirstName, MidInitial, LastName,
Company_Name,
Salary
from employee
join works
on works.employee_id = employee.employee_id
join company
on works.company_id = company.company_id
这只是一种奇特的说法:
select FirstName, MidInitial, LastName,
Company_Name,
Salary
from employee, works, company
where employee.employee_id = works.employee_id and
company.company_id = works.company_id
关于数据库事物的一些注释......
选择一个命名约定并坚持下去!如果您想使用CamelCase
,请随处使用。如果you_want_to_use
在您的名字中下划线,请在任何地方使用它们。有大量的命名约定可供选择:使用表名称为属性(列/字段)添加前缀,使用常用缩写(或不使用),使用(或不使用)大小写...这主要取决于个人偏好但有有关于使用某些的利弊的文章。最后一点,_因为你可以在名称中使用空格,__并不意味着你应该这样做。 `Almost all`
数据库如果您愿意,可以在[you use spaces]
中使用works
,但以后可能会导致很多问题。
表名不应该是复数。这是我的宠儿,这就是为什么:我们知道一张桌子会有很多记录......很多人/人员,许多员工,多家公司,任何类型或种类的多个条目。每行只描述一个这些东西。有时,将名称复数只是有意义。其他时候,这是有问题的 - 比如id
表。如果你有时把它变成复数,有时会使它变得单数,那么以后就会变得混乱。通过简单地使它变得单一,它仍然是完全合理的,并且你不会来回切换或者在编写查询时必须查找确切的名称。
数据类型非常重要并尝试在类似字段的表之间保持一致(与所有ID
相同的类型; make all boolean fields所有位或整数或其他,只是使它们相同)。您可以选择不同大小的整数类型。考虑尺寸,性能以及适合您需求的内容。确定你是否真的需要nvarchar或varchar是否合适。
包含对每个表中的行唯一的auto_increment
字段。最简单的方法是使用identity(1,1)
(mysql)或mysql_
(sql server)字段,以便数据库为您跟踪它。如果需要,可以重置或重新设置这些值。
学习使用normalization.
了解transactions做了什么以及为什么它们很重要......即使您不使用它们。
了解不同类型的联接。 This is one of the best explanations I have ever seen.要注意的主要事项是连接应该是外连接还是内连接。
了解SQL Injection,更重要的是how to prevent it(该链接适用于PHP)。
如果您使用的是PHP,请不要使用旧的PDO
课程。相反,请使用MySQLi_
或NULL
。 Info...
数据库最重要的是数据完整性,验证和清理。用户希望将各种草率,脏的数据放入表中。是密苏里州还是密苏里州?女,女,女,还是?工资是每小时15.00,每年50k,还是3,000薪水?是2013年12月31日,2013年12月31日,12月31日至13日,2013年12月31日或12月30日 - 二千一十三年?
决定是否允许Middle_Initial
。由于三态逻辑,它会使事情变得更复杂,您需要稍后检查它。有些人决定只使用空字符串。 NULL 更多的是状态而不是实际值,它意味着未定义或未知 - 值可以是任何值。我使用 null ,因为空字符串有时是字段的有效值。例如,将{{1}}设置为等于空字符串可能意味着该人没有中间首字母,或者可能意味着您不知道它是什么。对我来说,这些事情是不同的。对其他人来说,差异并不重要。只考虑数字......与未知数相同吗?
如果不出意外,请保持一致。
答案 1 :(得分:0)
主键列不能为NULL,需要将其设置为NOT NULL(不允许空值),类似这样的
create table Employee(
Lastname varchar(10) NOT NULL,
FirstName varchar(10) NOT NULL,
MidInitial char(1) NOT NULL,
gender char(1),
street varchar(10),
city varchar(10),
primary key(Lastname, FirstName, MidInitial));
create table company(
company_name varchar(20) NOT NULL,
city varchar(10),
primary key(company_name));
这将解决问题,但在varchar值上使用主键是一种不好的做法,我认为您应该在每个表中添加一个Identity列以用作主键,并在其他列上创建检查约束以强制您的业务规则。
答案 2 :(得分:0)
来自您的PRIMARY KEY的列为NULLABLE,您获得的错误与此无关,但是关于FOREIGN KEY上的多个列并且缺少原始表中引用的列。你应该这样做:
CREATE TABLE Works (
Lastname VARCHAR(10) NOT NULL,
FirstName VARCHAR(10) NOT NULL,
MidInitial CHAR(1) NOT NULL,
company_name VARCHAR(20) NOT NULL,
salary NUMERIC(8, 2),
PRIMARY KEY (Lastname,FirstName,MidInitial,company_name),
CONSTRAINT fk_works FOREIGN KEY (Lastname,FirstName,MidInitial)
REFERENCES Employee(Lastname, FirstName, MidInitial),
FOREIGN KEY (company_name) REFERENCES company(company_name)
);