Enforcing cross table uniqueness of records in mysql - mysql

I have three tables:
CREATE TABLE A (
id int(11) NOT NULL AUTO_INCREMENT,
adata varchar(255),
PRIMARY KEY (id)
);
CREATE TABLE B (
id int(11) NOT NULL AUTO_INCREMENT,
bdata varchar(255),
a_id int(11) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a_id) REFERENCES A(id) ON DELETE CASCADE
);
CREATE TABLE C (
id int(11) NOT NULL AUTO_INCREMENT,
cdata varchar(255),
b_id int(11) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (b_id) REFERENCES B(id) ON DELETE CASCADE
);
Elements of C (associated with B's) must be unique only for a given A. I.e., the combination of (cdata and b_id.a_id) must be unique.
I realize that I could add another column (pointing to A) to the C table and create a unique key. Is there any way to enforce uniqueness without adding another column to C?

Related

Should Keys be INDICES or compound PRIMARY KEY

I have a schema with a parent and child table.
A parent record, may have many children (1 to many)
To link these, a third table has the PRIMARY KEY of the parent, and child records.
Should this linking table, have a compound PRIMARY KEY?
Or, should this simply be two FOREIGN KEYS, each with an INDEX()?
CREATE TABLE parent(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
CREATE TABLE child(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
So, should the linking table be like..
CREATE TABLE parent_child_link(
parent_id INT NOT NULL,
child_id INT NOT NULL,
INDEX(parent_id),
INDEX(child_id),
FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE,
FOREIGN KEY (child_id) REFERENCES child(id) ON DELETE CASCADE
) ENGINE=INNODB;
Or should this be
CREATE TABLE parent_child_link(
parent_id INT NOT NULL,
child_id INT NOT NULL,
PRIMARY KEY(parent_id, child_id)
) ENGINE=INNODB;
Since its one to many and not many to many, adding a parent_id to the child table is sufficient.

SQL - CONSTRAINT to link two tables

I don't understand how to link two tables together. This is an example:
CREATE TABLE IF NOT EXISTS itemStatus (
id int(11) AUTO_INCREMENT PRIMARY KEY,
name varchar(64) NOT NULL UNIQUE KEY
);
CREATE TABLE IF NOT EXISTS itemData (
id int(11) AUTO_INCREMENT PRIMARY KEY,
title varchar(64) NOT NULL,
status_id int(11) DEFAULT NULL,
CONSTRAINT `fk_id` FOREIGN KEY (`id`) REFERENCES `itemStatus` (`id`),
);
I'm calling the row "status_id" but I don't reference this anywhere, so it can't link the two. For this example, should should my "CONSTRAINT" line read in order to be correct?
A FOREIGN KEY in one table points to a PRIMARY KEY in another table.
Take a look at:
http://www.w3schools.com/sql/sql_foreignkey.asp
So it should be:
CREATE TABLE IF NOT EXISTS itemStatus (
id int(11) AUTO_INCREMENT PRIMARY KEY,
name varchar(64) NOT NULL UNIQUE KEY
);
CREATE TABLE IF NOT EXISTS itemData (
id int(11) AUTO_INCREMENT PRIMARY KEY,
title varchar(64) NOT NULL,
status_id int(11) DEFAULT NULL,
CONSTRAINT `fk_id` FOREIGN KEY (`status_id`) REFERENCES `itemStatus` (`id`)
);
FOREIGN KEY (status_id) => Field in the table will REFERENCES itemStatus (id)
Constraint can't have "," when it's the last:
(...) REFERENCES itemStatus (id),
So the structure should be:
CONSTRAINT <<CONSTRAINT_NAME>> FOREIGN KEY (<<COLUMN_IN_THE_TABLE>>) REFERENCES `<<ANOTHER_TABLE>>` (`<<ANOTHER_TABLE_COLUMN_ID>>`)
Looks like you're very close. Try this instead:
CONSTRAINT `fk_id` FOREIGN KEY (`status_id`) REFERENCES `itemStatus` (`id`)
Your constraint is linking two primary keys (id of table 1 with id of table 2).
It should be something like this:
CREATE TABLE IF NOT EXISTS itemData (
id int(11) AUTO_INCREMENT PRIMARY KEY,
title varchar(64) NOT NULL,
status_id int(11) DEFAULT NULL,
CONSTRAINT `fk_id` FOREIGN KEY (`status_id`) REFERENCES `itemStatus` (`id`)
);

Errno:150 in MySQL Database

Have an error in my SQL code, but could not understand, where it is. Please, help me to solve that. Here is my code:
CREATE TABLE IF NOT EXISTS Records (
record_id int(11) NOT NULL AUTO_INCREMENT,
record_year year(4) NOT NULL,
record_quarter int(1) NOT NULL,
profit_tax int(11) NOT NULL,
PRIMARY KEY (record_id, record_year, record_quarter),
UNIQUE(record_year, record_quarter)
);
CREATE TABLE IF NOT EXISTS ProductsList (
product_id int(11) NOT NULL AUTO_INCREMENT,
product_name varchar(24) NOT NULL,
PRIMARY KEY (product_id)
);
An error is in that table:
CREATE TABLE IF NOT EXISTS RecordsProducts (
recordproduct_id int(11) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (recordproduct_id),
FOREIGN KEY (record_id) REFERENCES Records (record_id),
FOREIGN KEY (product_id) REFERENCES ProductsList (record_id)
);
referencing column should be INDEX
referencing column should have same data type of referenced column
both referencing, referenced table should be InnoDB
CREATE TABLE IF NOT EXISTS RecordsProducts (
...
...
record_id int NOT NULL, <=== check data type
product_id int NOT NULL,
INDEX(record_id), <===== check INDEXed or not
INDEX(product_id), <====
FOREIGN KEY (record_id) REFERENCES Records (record_id),
FOREIGN KEY (product_id) REFERENCES ProductsList (record_id)
) ENGINE = InnoDB; <=== add 'ENGINE=InnoDB' explicitly

Foreign key constraints seem ignored by mysql

I am just making a foreign key reference of parent table in a child table. When I try to delete the row from the parent table whose reference is there in child table, surprisingly it allows me to delete it. I have tried to create child table explicitly by writing on delete restrict and also without it, but to no help. Any ideas why this is happening? Below is the code I am using while creating the tables.
CREATE TABLE region
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
);
CREATE TABLE aggregator
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
);
CREATE TABLE gateway
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
region_id int ,
aggregator_id int ,
is_public boolean DEFAULT 0 NOT NULL,
FOREIGN KEY (region_id) REFERENCES region(id),
FOREIGN KEY (aggregator_id) REFERENCES aggregator(id)
);
Both parent and child table need to be INNODB tables.
Try:
CREATE TABLE region
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
) ENGINE=INNODB;
CREATE TABLE aggregator
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
) ENGINE=INNODB;
CREATE TABLE gateway
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
region_id int ,
aggregator_id int ,
is_public boolean DEFAULT 0 NOT NULL,
FOREIGN KEY (region_id) REFERENCES region(id),
FOREIGN KEY (aggregator_id) REFERENCES aggregator(id)
) ENGINE=INNODB;
Do mean to say that if you delete parent table and child table deletes automatic? If yes then once go through cascading rules.

Can't figure out what's wrong with foreign key constraint statement

This is the error message from show engine innodb status; when I try to create the table:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
110628 16:56:07 Error in foreign key constraint of table test/menu_items:
foreign key(id_menu)
references menus(id)
on update cascade
on delete cascade,
foreign key(id_item)
references items(id)
on update cascade
on delete cascade,
primary key(id_menu, id_item)
) engine=InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
These are the relevant SQL statements:
create table if not exists menus (
id mediumint unsigned not null auto_increment,
id_restaurant mediumint unsigned not null,
name varchar(50) not null,
description varchar(255) default null,
foreign key(id_restaurant)
references restaurants(id)
on update cascade
on delete cascade,
primary key(id)
) engine=InnoDB;
create table if not exists items (
id mediumint unsigned not null auto_increment,
id_restaurant mediumint unsigned not null,
name varchar(50),
description text,
type enum('appetizer','salad','soup','entree','dessert','drink','other'),
price decimal(4,2),
foreign key(id_restaurant)
references restaurants(id)
on update cascade
on delete cascade,
primary key(id)
) engine=InnoDB;
create table if not exists order_items (
id_order bigint unsigned not null,
id_item mediumint unsigned not null,
item_name varchar(50),
item_description text,
item_price decimal(4,2),
notes varchar(1024),
quantity smallint unsigned,
foreign key(id_order)
references orders(id)
on update cascade
on delete cascade,
foreign key(id_item)
references items(id)
on update cascade
on delete cascade,
primary key(id_order, id_item)
) engine=InnoDB;
Removing menu_items.id_menu and corresponding foreign key / primary key allows the SQL statements to be parsed properly.
Why can't I make a foreign key reference to menus(id) from menu_items?
You've got a mismatch of datatypes:
create table order_items (
id_order bigint unsigned not null, -- BIGINT
create table items (
id mediumint unsigned not null auto_increment, -- MEDIUMINT
but order_items.id_order references items.id, so they should be the same.
Try changing order_items id_order to medium int:
order_items (
id_order mediumint unsigned not null,