I'm getting an error while creating the following tables in MySQL.
Here's the error:
ERROR 1005 (HY000): Can't create table 'Works' (errno: 150)
Could you guys take a look at the foreign keys of Works() and let me know if you see anything weird about them that would cause this error to happen?
Here's my overall schema:
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);
Thanks so much!
Your errors are caused because of incorrect foreign key syntax.
However, I think you should use ID fields instead of doing string composite primary keys. There are a few issues with your method...
It will make it harder for the DB to join tables together compared to using an integer (ID) field to join (harder == more processing time).
It is valid to have multiple people with the same name, even using a middle initial.
What happens if you have to change someone's name? Either because it was stored wrong or they got married or anything... That means you'll have to not only update your
employee
table, but theworks
table and any other table you've used the name as a foreign key.Take a look at this: http://sqlfiddle.com/#!2/2dc8c/3/0
I've added a table ID to each table. It is an
unsigned int
, which means it cannot be negative (because that wouldn't make much sense). It is alsoauto_increment
, which means that each time you add a row to the table, this ID will be auto generated and go up by 1.You would add things to this table like this:
The
null
will become the automatically generated ID. It will be unique for each row.Also, a unique constraint means that the combination of these fields must be unique in the table. However, with a big enough company, I bet two people will have the same name. In real life, i would suggest removing this unique constraint.
I made similar changes to the company table...
Things could be added like:
So... for
works
.... instead of storing the full name of each person and the full company name over and over again in this table, now we only have to store the ID's.You could add things to
works
like this:Since John Smith was our first employee, his Employee_ID would be 1. To verify that, just try
select * from Employee where FirstName='John' and LastName='Smith'
. Taco Bell would also get company_id = 1. By inserting those values intoworks
, that means John now works at Taco Bell.I would also suggest you add fields like
start_date
andend_date
andjob_title
to your works table. And you would want to pay special consideration to any unique constraints for this table, too. People can work for the same company more than once. They can also have different jobs.When you want to get your data back out, you would use a query like this:
which is just a fancy way of saying this:
Some notes on database things...
Choose a naming convention and stick to it! If you want to use
CamelCase
, use it everywhere. Ifyou_want_to_use
underscores in your names, use them everywhere. There are tons of naming conventions to pick from: prefixing attributes (columns/fields) with the table name, using common abbreviations (or not), where capitalization is used (or not)... this mostly comes down to personal preference but there are articles out there about the pros and cons about using certain ones. Last note, _just because you can use spaces in a name,__ doesn't mean you should.`Almost all`
databases let[you use spaces]
in names if you want but it can cause a lot of issues later.Table names should not be plural. This is a pet-peeve of mine and here's why: We know a table will hold many records... many people/persons, many employees, multiple companies, multiple entries of whatever type or kind. Each row describes just one of these things. Sometimes it just doesn't even make sense to have the name be plural. Other times, it is questionable - like the
works
table. If you sometimes make it plural, and sometimes make it singular, it can get confusing later. By just making it all singular, it still makes perfect sense, and you aren't switching back and forth or having to look up the exact name when writing queries.Datatypes are important and try to be consistent across tables for similar fields (like all
id
s the same type; make all boolean fields all bits or integers or whatever, just make them the same). There are different sizes of integer types you can choose from. Think about size, performance and what is appropriate for your needs. Decide if you really need a nvarchar or if a varchar is okay.Include an
ID
field that is unique for the row in every table. The easiest way to do this is to use anauto_increment
(mysql) oridentity(1,1)
(sql server) field so the database keeps track of it for you. These values can be reset or reseeded if you need it.Learn to use normalization.
Learn what transactions do and why they are important... even if you don't use them.
Learn about the different kind of joins. This is one of the best explanations I have ever seen. The main thing to pay attention to is if the join should be an outer or inner join.
Learn about SQL Injection and more importantly, how to prevent it (that link is for PHP).
If you're using PHP, don't use the old
mysql_
class. Instead, usePDO
orMySQLi_
. Info...The big thing about databases is data integrity, validation and sanitization. Users will want to put all kinds of sloppy, dirty data into your tables. Is it MO or Missouri? Female, F, woman, girl, or yes? Is the salary 15.00 an hour, 50k annually, or 3,000 a paycheck? Is it 12/31/2013, 31/12/2013, 12-31-13, Dec 31, 2013 or december thirty-fist two thousand and thirteen?
Decide if you want to allow
NULL
or not. It makes things more complicated because of triple state logic and you will need to check for it later. Some people decide to just use an empty string instead. NULL is more of a state than an actual value and it means undefined or unknown - the value could be anything. I use null because an empty string is sometimes a valid value for a field. For example, settingMiddle_Initial
to equal an empty string could mean the person doesn't have a middle initial or it could mean you just don't know what it is. To me, these things are different. To other people, the difference doesn't matter. Just consider numbers... is 0 the sames as unknown?If nothing else, just be consistent.
Appart from having the columns NULLABLE for your PRIMARY KEY, the error you are getting is not about that, but about the multiple columns on your FOREIGN KEY and missing the columns that are referenced in the original tables. You should do:
The primary key column cannot be NULL, you need to set it to NOT NULL (not allowing null values), something like this
This will resolve the issue but its a bad practice to have Primary Key on varchar values, I think you should add an Identity column in each table to use as a primary key, and create check constraints on other columns to enforce your business rules .