How MySQL one to many and one to one relationships are defined? - mysql

I was referring these to Hibernate tuts: 1, 2.
I was not able to understand how one to one and one to many relationships are defined in MySQL tables.
This is SQL for one to many relationship:
CREATE TABLE `Cart` (
`cart_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`total` decimal(10,0) NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `Items` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`cart_id` int(11) unsigned NOT NULL,
`item_id` varchar(10) NOT NULL,
`item_total` decimal(10,0) NOT NULL,
`quantity` int(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `cart_id` (`cart_id`),
CONSTRAINT `items_ibfk_1` FOREIGN KEY (`cart_id`) REFERENCES `Cart` (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
This is SQL for one to one relationship:
-- Create Transaction Table
CREATE TABLE `Transaction` (
`txn_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`txn_date` date NOT NULL,
`txn_total` decimal(10,0) NOT NULL,
PRIMARY KEY (`txn_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
-- Create Customer table
CREATE TABLE `Customer` (
`txn_id` int(11) unsigned NOT NULL,
`cust_name` varchar(20) NOT NULL DEFAULT '',
`cust_email` varchar(20) DEFAULT NULL,
`cust_address` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`txn_id`),
CONSTRAINT `customer_ibfk_1` FOREIGN KEY (`txn_id`) REFERENCES `Transaction` (`txn_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
If eyes are ok, I dont see any difference between two. Is it like this relationship cardinality constraints are implemented only at hibernate level and are not enforced by database? Or my eyes are missing something?

It's actually possible to define 1:1 relationships in SQL. There are two ways:
The child table has the same PK as the parent table, with the same values. This column is also an FK to the parent table.
The child table has a different PK. It also has a FK that points to the parent table, and this FK has a UNIQUE constraint.
If you noticed, in both cases the FK is UNIQUE (it's the PK, or has a UNIQUE constraint), and that's the key aspect. It's not possible the create a second row in the child table that has the same parent.
The case you included in your question opted for strategy #1.

Related

Interpretation of model diagram for allocation of foreign/primary keys

https://imgur.com/a/HAlSO7z
I am totally confused as to what I should identify as the primary key for the flatpack components table. For the flatpack components, there is a multiplicty relationship with both of the other tables, although intuitively I am leaning toward the component table because that seems more relevant, and the multiplicity is 0 to Many to 1, as opposed to the Many to 1 associated with flatpack components.
I have tried a composite key of both flatpackID and componentNo, but have ran into errors whilst trying to populate the table with sample data.
At present, I have the following tables:
CREATE TABLE `flatpack_apn` (
`flatpackid` INT(11) NOT NULL AUTO_INCREMENT,
`name` TINYTEXT NOT NULL,
`colour` TEXT NULL DEFAULT NULL,
`flatpacktype` ENUM('Office','Kitchen','Bedroom','General') NOT NULL,
`unitprice` DECIMAL(5,2) NULL DEFAULT NULL,
PRIMARY KEY (`flatpackid`)
)
COLLATE='hp8_english_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2217
;
CREATE TABLE `component_apn` (
`componentno` INT(11) NOT NULL AUTO_INCREMENT,
`description` VARCHAR(30) NOT NULL,
PRIMARY KEY (`componentno`)
)
COLLATE='hp8_english_ci'
ENGINE=InnoDB
AUTO_INCREMENT=20
;
For the flatpackcomponents_apn table (the table in contention) I have tentatively put the following code:
CREATE TABLE `flatpackcomponents_apn` (
`flatpackid` INT(11) NOT NULL DEFAULT '12',
`componentno` INT(11) NOT NULL DEFAULT '23',
`quantity` INT(10) NOT NULL,
PRIMARY KEY (`componentno`, `flatpackid`),
INDEX `flatpackid` (`flatpackid`),
INDEX `componentno` (`componentno`),
CONSTRAINT `flatpackcomponents_apn_ibfk_1` FOREIGN KEY (`flatpackid`) REFERENCES `flatpack_apn` (`flatpackid`),
CONSTRAINT `flatpackcomponents_apn_ibfk_2` FOREIGN KEY (`componentno`) REFERENCES `component_apn` (`componentno`)
)
COLLATE='hp8_english_ci'
ENGINE=InnoDB
;

What is the cause for MySQL: Errorno 150

Can someone please explain the cause for the following error, 'Can't create table 'Activities' (errno: 150)'
I'm under the understading that the data types and lengths have to be the same, does is have anything to do with the auto increment?
Create Table `LinkMemberActivity` (
`LinkID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`MID` int(11) unsigned NOT NULL,
`AID` int(11) unsigned NOT NULL,
PRIMARY KEY (`LinkID`),
FOREIGN KEY (`MID`) REFERENCES Members(`MID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
)
CREATE TABLE `Activities` (
`AID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(25) DEFAULT NULL,
`MaxCapacity` int(25) DEFAULT NULL,
`StartTime` time DEFAULT NULL,
`EndTime` time DEFAULT NULL,
PRIMARY KEY (`AID`),
FOREIGN KEY (`AID`) REFERENCES LinkMemberActivity(`AID`))
ENGINE=InnoDB DEFAULT CHARSET=latin1 );
You are trying to make a primary key column a foreign key dependent field. This is not only unusual but makes no sense in a datamodel, unless it is part of a composite key. Common practice has a column foreign key dependent on another tables primary key. Not sure what reasons you have for the way you designed your datamodel this way, but you can fix this problem by creating a not null autoincrement column named ID and make this column the primary key. Next remove autoincrement from aid.

mysql won't allow foreign key

Many people had this problem already, but there was no fitting solution in other posts.
I have two tables, one named "sales", the other named "host_flags". I would like to have a foreign key for host_flags.sales_id to sales.id, but mysql won't let me! I have primary indexes defined in each table, so I wonder why...
The host_flags table already has a foreign key on the column host_id, but even when I tried and created the foreign key for the sales id first, it wouldn't let me.
The tables look like:
CREATE TABLE `sales` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
CREATE TABLE `host_flags` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`host_id` int(11) DEFAULT NULL,
`sales_id` int(11) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `host_id6` (`host_id`),
CONSTRAINT `host_id6` FOREIGN KEY (`host_id`) REFERENCES `hosts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `hosts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`creation` datetime NOT NULL,
`lastupdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32225 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
I get this error message:
MySQL said: Can't create table 'primarydata.#sql-191_1' (errno: 150)
Thanks!
Charles
SOLUTION FOUND
All ints of the primary indexes have to be either signed or unsigned - not mixed.
Typically:
I like to declare the FK constraints outside of the table definition after all tables have been constructed.
ALTER TABLE `tbl`
ADD CONSTRAINT `constr`
FOREIGN KEY `fk_id` REFERENCES `ftbl`(`id`)
ON UPDATE CASCADE
ON DELETE CASCADE;
This way I can make sure the problem isn't something like the datatype of tbl.fk_id not being the same as the one of ftbl.id (including UNSIGNED as #Devart said). Or not having declared ftbl.id as unique. Regardless of the order of declaration of the tables.
After i do this i can integrate the constraint back into the table definition and take into account the order in which the tables need to be created to allow the constraint to be added.
You problem:
-- creating the sales table
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-- creating the host_flags table
`sales_id` int(11) DEFAULT NULL,
-- the sales.id is declared as unsigned
-- the host_flags.sales_id is declared signed
Additonally to Recursed's answer:
There is a requirement that foreign keys contstraints' names must be unique in database scope. Maybe changing the name will work?
There is also a huge thread on MySQL community forums about the problem containing several solutions for some specific situations.
Possible two errors:
Reference and referenced columns must have the same type - int(11) unsigned
Unknown referenced table hosts.

Mysql connect tables through foreign key, depends from field type

Mysql database question. There is system with objects(Domains). Each domain has own table. All objects has unique 16 varchar id - guid
CREATE TABLE `guid` (
`guid` varchar(16) NOT NULL,
`obj_type` varchar(45) NOT NULL,
`obj_id` varchar(45) NOT NULL,
`actived` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`guid`)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL,
/*....*/
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `catalog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL,
/*....*/
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
I would like connect table guid(fields: obj_type, obj_id) and domain tables(field:id) through foreign key.
Foreign key relationships involve a parent table that holds the central data values, and a child table with identical values pointing back to its parent. The FOREIGN KEY clause is specified in the child table. The parent and child tables must both be InnoDB tables. They must not be TEMPORARY tables.
CREATE TABLE product
(
id INT(11) NOT NULL auto_increment,
name VARCHAR(150) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES guid (guid )
)
engine=myisam
DEFAULT charset=utf8;

mysql prevent deleting records that is in used

i got 2 tables. product and order_items which contain all the products that were bought.
so how do i create a relationship in mysql whereby if a product exists in order_items, restrict users from deleting it from product table??
thanks
You can do this with Foreign keys with the InnoDB Engine.
ALTER TABLE order_items ADD FOREIGN KEY (`p_id`) REFERENCES `products` (`p_id`);
The ID on products must be a key (it probably already is the primary key).
If you are not using InnoDB, you cannot enforce this with MySQL, but it must be enforced with your application (check whether a record exists in orders first for example).
So with your tables, you run:
ALTER TABLE `order_item` ADD FOREIGN KEY (`bookid`) REFERENCES `book` (`id`);
You're looking for a foreign key. Specifically look at the "Restrict" option.
http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
my table structure:
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`title` varchar(100) NOT NULL,
`description` text NOT NULL,
`author` varchar(100) NOT NULL,
`publisher` varchar(100) NOT NULL,
`edition` int(11) NOT NULL,
`isbn` varchar(13) NOT NULL,
`category` varchar(11) NOT NULL,
`datesubmitted` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
CREATE TABLE `order_item` (
`orderid` int(11) NOT NULL,
`bookid` int(11) NOT NULL,
KEY `Foreign` (`bookid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;