no foreign key in table if engine is MyISAM - php

why i cannot create foreign key in my table payments.
crate table students(
text char(5)NOT NULL,
id int(11)NOT NULL AUTO_INCREMENT,
name varchar(250),
level varchar(250),
PRIMARY KEY (text,id)
)ENGINE=MyISAM;
the oder table is
crate table payments(
p_id int(11)NOT NULL AUTO_INCREMENT,
amount varchar(250),
id int
PRIMARY KEY (p_id)
FOREIGN KEY (id) REFERENCES students(id)
)ENGINE=MyISAM;

Because MyISAM does not support foreign keys. The FK declarations are parsed, but otherwise ignored. You need to use InnoDB tables for real FK support.

Related

Referencing multiple tables in mysql

How do I reference multiple tables for one table ?
In the assignment, I have to create 5 tables with each table having INT id:
Owners, homes, home_owners, installation, house_type.
Owners can have multiple homes and homes can have multiple owners.
Home needs to have installations and house_type(both need to be VARCHAR type).
I wrote this to sql but it returns an
error: errno: 150 "Foreign key constraint is incorrectly formed"
CREATE TABLE owners (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE homes (
id INT AUTO_INCREMENT PRIMARY KEY,
created DATETIME,
modified DATETIME,
home_types_group VARCHAR(255) NOT NULL
);
CREATE TABLE home_owners (
id INT AUTO_INCREMENT PRIMARY KEY,
created DATETIME,
modified DATETIME,
owners_num INT NOT NULL,
FOREIGN KEY owners_num_key (owners_num) REFERENCES owners(id)
);
CREATE TABLE installation (
id INT AUTO_INCREMENT PRIMARY KEY,
brands VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME,
FOREIGN KEY brands_key (brands) REFERENCES homes(home_types_group)
);
CREATE TABLE types (
id INT AUTO_INCREMENT PRIMARY KEY,
types VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME,
FOREIGN KEY brands_key (types) REFERENCES homes(home_types_group)
);
The problem is here:
CREATE TABLE installation ( id INT AUTO_INCREMENT PRIMARY KEY, brands VARCHAR(255) NOT NULL, created DATETIME, modified DATETIME, FOREIGN KEY brands_key (brands) REFERENCES homes(home_types_group) )
REFERENCES homes(home_types_group) : this is wrong, you can only reference a primary or unique column of some table for making foreign key. But home_types_group column is neither primary nor unique. Change it to id clumn of homes table
Try this
CREATE TABLE installation ( id INT AUTO_INCREMENT PRIMARY KEY, brands
int, created DATETIME, modified DATETIME, FOREIGN KEY fk_id(brands)
REFERENCES homes(id) );
CREATE TABLE types ( id INT AUTO_INCREMENT PRIMARY KEY, types int,
created DATETIME, modified DATETIME, FOREIGN KEY brands_key (types)
REFERENCES homes(id) );
You can create a foreign key by defining a FOREIGN KEY constraint when you create or modify a table. In a foreign key reference, a link is created between two tables when the column or columns that hold the primary key value for one table are referenced by the column or columns in another table
Here REFERENCES homes(home_types_group) is wrong so you should change it to homes(id), you can only reference a primary or unique column of some table for making foreign key.and both keys data type should be same that is
brands VARCHAR(255) NOT NULL
types VARCHAR(255) NOT NULL
are wrong it should be int

Why a can't connect my tables in MySQL?

shippings table structure
I want to connect in to another table like this(I got "1215 error"):
CREATE TABLE goods_and_shippings (
good_id INT NOT NULL,
s_date DATE NOT NULL,
shipping_id INT NOT NULL,
PRIMARY KEY (good_id),
FOREIGN KEY (s_date) REFERENCES shippings(s_date)
)
Connected columns have same data types as you can see (both DATE and NOT NULL) and all tables use InnoDB engine. But I have this snippet and it works:
CREATE TABLE goods_and_shippings (
good_id INT NOT NULL,
s_date DATE NOT NULL,
shipping_id INT NOT NULL,
PRIMARY KEY (good_id),
FOREIGN KEY (shipping_id) REFERENCES shippings(shipping_id)
)
All tables are empty for now. Here is query for creating shippings:
CREATE TABLE shippings (
shipping_id INT NOT NULL,
s_date DATE NOT NULL,
driver_id INT NOT NULL,
start_place VARCHAR(50) NOT NULL,
end_place VARCHAR(50) NOT NULL,
car_id INT NOT NULL,
price DECIMAL(5,2) NOT NULL,
PRIMARY KEY (shipping_id, s_date)
)
Here alters I've used after:
ALTER TABLE shippings ADD CONSTRAINT fk_car_id FOREIGN KEY (car_id) REFERENCES cars(car_id);
ALTER TABLE shippings ADD CONSTRAINT fk_driver_id FOREIGN KEY (driver_id) REFERENCES drivers(driver_id);
What's wrong in my queries? How to fix this and connect goods_and_shippings.s_date and shippings.s_date?
In general, foreign key references are to unique or primary keys. However, this condition is relaxed for INNODB, as explained in the documentation:
InnoDB permits a foreign key to reference any index column or group of
columns. However, in the referenced table, there must be an index
where the referenced columns are listed as the first columns in the
same order.
So, you can have a foreign reference to shipping_id because it is the first key in the primary key, but not to date. However, I would advise you to set up your foreign key relationships to complete primary keys. And, I usually have an auto-incrementing primary key in all tables, to facilitate such relationships.

PHP MySQL Error creating table: Cannot add foreign key constraint

I am trying to write a PHP script to create 2 tables in the same database, which should be linked through a 1 (table category) to many (table page) relationship. Hence, primary key 'category_id' from the 'category' table should be the foreign key in the table 'page'.
The table 'category' creates successfully without problems:
$sql="CREATE TABLE category(
category_id SMALLINT NOT NULL AUTO_INCREMENT,
category VARCHAR(30) NOT NULL,
PRIMARY KEY (category_id),
UNIQUE (category)
)ENGINE=InnoDB DEFAULT CHARSET=utf8";
Then I am trying to create the second table 'page':
$sql="CREATE TABLE page(
page_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
category_id SMALLINT UNSIGNED NOT NULL,
title VARCHAR(100) NOT NULL,
description TINYTEXT NOT NULL,
content LONGTEXT NOT NULL,
date_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (page_id),
FOREIGN KEY (category_id) REFERENCES category (category_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8";
And I get the following error:
Error creating table: Cannot add foreign key constraint
Could you please tell me what's wrong with my code? Thanks a lot in advance.
Per the MySql manual at http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html:
Corresponding columns in the foreign key and the referenced key must have similar data types.
The size and sign of integer types must be the same.
The problem is that you're specifying your foreign key as UNSIGNED, while your primary is not. Make sure that your foreign key matches the specifications of its parent.
From the MySQL Using FOREIGN KEY Constraints documentation:
Corresponding columns in the foreign key and the referenced key must have similar data types. The size and sign of integer types must be the same.
In your page table, the category_id is SMALLINT UNSIGNED, but in category it's just SMALLINT. They need to be exactly the same.
The columns used for your foreign key must have a matching specification. Here you have one category_id column signed, while the other is unsigned. Change one.
you problem is the UNSIGNED in category_id.
try to remove it
try
$sql="CREATE TABLE page(
page_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
category_id SMALLINT NOT NULL,
title VARCHAR(100) NOT NULL,
description TINYTEXT NOT NULL,
content LONGTEXT NOT NULL,
date_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (page_id),
FOREIGN KEY (page.category_id) REFERENCES category (category.category_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8";

Creating composite foreign key on a primary key

I have a table called events with event_id as a primary key and a table person with person_id as a primary key.
I want to have a table that contains two columns event_id and person_id as foreign keys to the above two primary keys.
I am able to create a foreign key something like this:
create table pe(
event_id INTEGER UNSIGNED UNIQUE,
person_id INTEGER UNSIGNED UNIQUE,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id)
);
but I cannot insert values like:
----------------------
event_id person_id
----------------------
1 1
1 2
2 1
2 2
----------------------
For that I need a composite foreign key.
I am not able to decide how to do that. Any suggestions or help are much appreciated!
Thanks a lot!
You need to make the combination of event_id and person_id unique. I'd just make the combination the primary key, as follows:
create table pe(
event_id INTEGER UNSIGNED,
person_id INTEGER UNSIGNED,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id),
PRIMARY KEY (event_id, person_id)
);
Because you have set individual unique key for each column. Here's how to enforce composite unique key,
create table pe
(
event_id INTEGER UNSIGNED,
person_id INTEGER UNSIGNED,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id),
UNIQUE (event_id, person_id) // <<== or it could be PRIMARY KEY
);
I played around with this schema to check what you were trying to do:
CREATE TABLE `events` (
`event_id` int(11) NOT NULL AUTO_INCREMENT,
`event_name` varchar(255) NOT NULL,
PRIMARY KEY (`event_id`),
UNIQUE KEY `event_name_UNIQUE` (`event_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`person_id` int(11) NOT NULL AUTO_INCREMENT,
`person_name` varchar(225) DEFAULT NULL,
PRIMARY KEY (`person_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `pe` (
`event_id` int(11) NOT NULL,
`person_id` int(11) NOT NULL,
PRIMARY KEY (`event_id`,`person_id`),
KEY `fk_events_has_person_person1` (`person_id`),
KEY `fk_events_has_person_events` (`event_id`),
CONSTRAINT `fk_events_has_person_events` FOREIGN KEY (`event_id`) REFERENCES `events` (`event_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_events_has_person_person1` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I think your confusion lies in where you put the UNIQUE property. Each event and person needs to be unique. That is guaranteed by the primary key in the respective tables and you can also add a UNIQUE constraint in, for example, a column like person_name to ensure actual values are unique. There was nothing wrong with your foreign keys; the problem was that you added UNIQUE constraints to each field of the interim table. That's a mistake. If you want to ensure that each row of the interim table is unique then you need to add a composite primary key or as JW suggested a composite UNIQUE constraint.

Mysql and FK's Problem

i'm having trouble with some tables here.
i have this table:
CREATE TABLE `smenuitem` (
`nome` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`url` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`tipo` CHAR(4) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`ordemmenu` INT(10) NULL DEFAULT NULL,
`codparent` INT(10) UNSIGNED NOT NULL,
`codmenuitem` INT(10) UNSIGNED NOT NULL,
`codmodulo` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`codmodulo`, `codmenuitem`, `codmenuitem2`),
CONSTRAINT `FK_smenuitem_smodulos` FOREIGN KEY (`codmodulo`) REFERENCES `smodulos` (`codmodulo`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
And an second one:
CREATE TABLE `smenuitememp` (
`codempresa` INT(10) UNSIGNED NOT NULL,
`codmodulo` INT(10) UNSIGNED NOT NULL,
`codmenuitem` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`codmenuitem`, `codempresa`, `codmodulo`)
)
COLLATE='utf8_unicode_ci'
My problem it's i need to make an FK between codmenuitem
i have this sql command that are resulting on an error:
ALTER TABLE `smenuitememp` ADD CONSTRAINT `FK_smenuitememp_smenuitem` FOREIGN KEY (`codmenuitem`) REFERENCES `smenuitem` (`codmenuitem`);
When i try to execute it's return this error:
Someone has an idea?
Update... i was trying to solve the problem, and got an new question... T_T
CREATE TABLE `smenuitem` (
`nome` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`url` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`tipo` CHAR(4) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`ordemmenu` INT(10) NULL DEFAULT NULL,
`codparent` INT(10) UNSIGNED NOT NULL,
`codmenuitem` INT(10) UNSIGNED NOT NULL,
`codmodulo` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`codmodulo`, `codmenuitem`),
INDEX `codmenuitem` (`codmenuitem`),
CONSTRAINT `FK_smenuitem_smodulos` FOREIGN KEY (`codmodulo`) REFERENCES `smodulos` (`codmodulo`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
I solved the problem creating an index at the main table. But i don't know why i was having trouble without this index. If someone could ask me i would apreciate!
The foreign key column(s) must reference column(s) comprising a left-most prefix of the primary key or a unique key in the parent table.
In other words, the following examples work in InnoDB:
CREATE TABLE Foo ( a INT, b INT, c INT, PRIMARY KEY (a,b,c) );
CREATE TABLE Bar ( x INT, y INT );
ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(b,c); -- WRONG
ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,c); -- WRONG
ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,b); -- RIGHT
ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(b); -- WRONG
ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(a); -- RIGHT
You got an error because you're trying to do the equivalent of (x) references Foo(b).
Your column codmenuitem is the second of three columns in the primary key of the parent.
It would work if smenuitememp.codemenuitem were to reference smenuitem.codmodulo, because that column is the leftmost column in the parent table's primary key.
Re your followup question:
Keep in mind the way foreign keys work. Every time you insert or update a row in the child table, it needs to look up a row in the parent table to verify that the value exists in the referenced column. If the column isn't indexed, it'll have to do a table-scan to achieve this lookup, and that would be very expensive, assuming your parent table grows.
If you try to look up a row based on the middle column of a multi-column index, the index doesn't help you. By analogy, it's like searching a telephone book for all people with a certain middle name.
Standard ANSI SQL requires that the referenced column be part of a PRIMARY KEY or UNIQUE KEY, and it requires that the foreign key columns match all the columns of a primary or unique constraint in the parent.
But InnoDB is more permissive. It still requires that the referenced column in the parent table be indexed so the lookup can be efficient, and that the referenced columns be the leftmost in the index. But a non-unique index is okay; it's allowed for a foreign key to reference it.
This can lead to weird cases like a child row that references more than one row in the parent, but it's expected that you will handle such anomalies.
I feel the need to emphasize the last point. You will get anomalous data if you define foreign keys to non-uniquely indexed columns in the parent. This will probably cause your queries to report rows multiple time when you do joins. You should not use this behavior of InnoDB; you should define foreign keys only to parent columns that are unique.

Categories