cakephp model has 0 or 1 relationship - mysql

In cakephp, I have Company and Profile model. I would like to establish Company has 0 or 1 Profile relationship. Is it appropriate to use Company hasOne Profile, and Profile belongsTo Company? Is there any implication I need to be aware of? The table's schema is below. Thanks.
create table companies (
id char(36) NOT NULL,
type int(10) NOT NULL,
primary key (id)
);
create table profiles (
id char(36) NOT NULL,
company_id char(36) NOT NULL,
provider_contact varchar(255) NULL,
primary key (id),
unique key (company_id),
foreign key (company_id) references companies(id)
);

Yes you can use the hasOne/belongsTo Relationship, if a Company has no Profile the sub-array will be empty.
In your profiles table you should use company_id to follow the Cake naming conventions.

To follow CakePHP's conventions, the field needs to be company_id, not companies_id.
The foreign key constraint is up to you. I typically don't add them. The unique constraint seems incorrect. This would imply that there can only be one profile per company. Which is not the same as a company can have 0 or 1 profiles.

Stick to conventions.
You need to adjust your schema to do that
create table companies (
id int(11) NOT NULL,
type int(11) NOT NULL,
primary key (id)
);
create table profiles (
id int(11) NOT NULL,
company_id int(11) NOT NULL,
provider_contact varchar(255) NULL,
primary key (id),
unique key (company_id),
foreign key (company_id) references companies(id)
);
It is company_id as others have mention. And also, ids have to be ints, and autoincremental. It's a pain to have them as chars.

Related

db design: Two "1 to many" relationship?

In my situation i have
TABLE vehicles (
id int(11) NOT NULL AUTO_INCREMENT,
transaction_type varchar(45),
PRIMARY KEY (`id`)
/* all other values of vehicle */
)
TABLE Origination(
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
TABLE Additions(
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
So i have this new vehicles table that originate either from Origination, or Additions. The reason it can come from two tables is business needs, it either orginates for the origin or it originates from a special addition after the fact. I'm unsure how to connect a "vehicle" relation to both tables as the id can come from either.
So i added a transaction_type field, where if type is "Additions" join tables based on Additions Id. Else if type is "origination" join on Origination Id.
So i have a Two Key "1 to many" relationship. is this a valid and useable design practice? I am not a database person, but am trying to learn how to handle this is the best way.
From what I understand you want a main table containing ALL your vehicles and two separate tables that add different data to those vehicles. This is how I'd make that work. If you be more specific about what each table does I can be of more help.
TABLE Vehicle (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
/* all other values of vehicle */
)
TABLE Origination (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
TABLE Addition (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
TABLE Vehicle_Origination (
origination_id int(11),
vehicle_id int(11),
FOREIGN KEY (origination_id) REFERENCES Origination (id),
FOREIGN KEY (vehicle_id) REFERENCES Vehicle (id)
)
TABLE Vehicle_Addition (
addition_id int(11),
vehicle_id int(11),
FOREIGN KEY (addition_id) REFERENCES Addition (id),
FOREIGN KEY (vehicle_id) REFERENCES Vehicle (id)
)

errno: 150 "Foreign key constraint is incorrectly formed" Nothing helps

sorry for maybe stupid question, but I stack with my sql query. Tried out many methods to avid it but still have error 150. I've created 3 tables and one with foreighn keys:
Table users
create table users(
id int(11) primary key auto_increment,
unique_id varchar(23) not null unique,
name varchar(50) not null,
cname varchar(50) not null,
email varchar(100) not null unique,
encrypted_password varchar(80) not null,
salt varchar(10) not null,
created_at datetime,
updated_at datetime null
);
Table behaviours
CREATE TABLE behaviours (
id int(2) AUTO_INCREMENT PRIMARY KEY,
bName varchar(100) NOT NULL
);
Table severytys
CREATE TABLE severitys (
id int(2) AUTO_INCREMENT PRIMARY KEY,
severity varchar(10) NOT NULL
);
And here it shows errors:
CREATE TABLE child_behaviours(
id int(11) primary key auto_increment,
name varchar(50) not null,
cname varchar(50) not null,
bName varchar(100) NOT NULL,
severity varchar(10) NOT NULL,
start_at datetime,
stop_at datetime null,
FOREIGN KEY (id) REFERENCES users(id),
FOREIGN KEY (bName) REFERENCES behaviours(bName),
FOREIGN KEY (severity) REFERENCES severitys(severity)
);
Will be really pleasent to have an answer to this issue
You can only create a FK on a column that is both UNIQUE and NOT NULL. This is usually, but not always, the primary key of the referenced table.
If you reference anything other than the PK, you need a really really good reason.
(I'd even add to that, that you need a really really good reason to use anything other than an INT or a couple INTs as a PK...)
Now, child_behaviours has several errors:
Duplication of columns already present in users. If you reference users by its id, there is no need to duplicate the columns.
Reference to behaviors(bName) instead of using its id
same thing for reference to severity
Also, there is the generic mistake of using "id" columns. Please call them "user_id", "severity_id", etc, and then call them the same in your references. This will make your life much easier, and avoid stuff like:
SELECT foo.id AD foo_id, bar.id AS bar_id FROM foo JOIN bar ON ...
You have to refer to a primary key, when building a foreign key
CREATE TABLE child_behaviours(
userId int not null,
behaviourId int NOT NULL,
severityId int NOT NULL,
start_at datetime not null,
stop_at datetime,
FOREIGN KEY (userId) REFERENCES users(id),
FOREIGN KEY (behaviourId) REFERENCES behaviours(id),
FOREIGN KEY (severityId) REFERENCES severitys(id)
);

One to Many/many to many SQL

I am working with mysql and running into a little confusion. I have created two tables academy and courses. I am needing help in determining how to structure the table fields. For example the one to many schema. One academy can offer many courses and a course can be offered with many academies. Is the structure for the tables below correct?
create table academy
(
academy_id int(11) not null auto_increment,
course_id int() NOT NULL ,
name varchar(25) not null,
primary key (id),
);
CREATE TABLE course
(
course_id int(11) not null auto_increment,
course_name VARCHAR(50) NOT NULL ,
primary key (course_id),
foreign key (academy_id) REFERENCES academy (academy_id) on delete cascade
);
Example of desired result
id Name Course
1 The Alamo School 125 Intro to Programming
2 Bearcat High School 125 Intro to Programming
What you really need is a table for the academies, one for the courses and a relationship table where you can store the many-to-many relationships. I leave to you the query to get the result you are looking for :)
CREATE TABLE academy
(
academy_id int(11) not null auto_increment,
name varchar(25) not null,
primary key (id),
);
CREATE TABLE course
(
course_id int(11) not null auto_increment,
course_name VARCHAR(50) NOT NULL ,
primary key (course_id),
);
CREATE TABLE accademy_course
(
academy_id int(11) not null,
course_id int(11) not null ,
primary key (academy_id, course_id),
foreign key (academy_id) REFERENCES academy (academy_id) on delete cascade,
foreign key (course_id) REFERENCES course (course_id) on delete cascade
);

Foreign key for multiple tables and columns?

I have been learning about Foreign keys and I wanted to know if the way I used it is correct in the example below:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (name) REFERENCES items(name),
FOREIGN KEY (id) REFERENCES user(id)
);
Thanks
Now, how can I get maximum information from just the Foreign Key if I use, let's say, PHP?
You don't have to include item name in both tables. This is called a denormalized solution.
You should have it only in the items table and only refer to the id, then if you need the name also you can join it based on the primary key(id).
Otherwise it is totally OK in my opinion.
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (id) REFERENCES user(id)
);
Sometimes when performance is critical you have to use denormalized tables. It can be much faster.
Normalization is important to avoid different anomalies.
If you have tables in a high level normal form then your tables won't be redundant and wont have these anomalies. For example if you have something stored in multiple locations you have to look after to keep all the redundant data up to date. This gives you a chance to do this incorrectly and end up having different anomalies.
In your situation having a foreign key helps you to keep data integrity but without a foreign key for the name you would be able to have items with names in the purchases that are not present in the items table.
This is a kind of anomaly.
There are many kinds of this, best to avoid them as long as you can.
Read more here about anomalies
In some cases you must denoramalize. So store some data redundantly because of performance issues. This way you can save some join operations that could consume much time.
Details of normalization are covered by topics of different normal forms:
NF0, NF1, NF2, NF3 and BCNF
Normal forms in detail
For further details about the mathematical foundations of loseless decomposition to higher normal forms see "Functional dependencies". This is going to help you understand why you can keep the ids "redundant". Virtually they are necessary redundancy, since you need them in order to be able to later rebuild the original dataset. This is going to be the definition for the different normal forms. What level of this redundancy is allowed?
Functional Dependencies
you've got an i_id as a primary key, you don't need to set up a name as a foreign key. and btw foreign key has to reference to unique attribute.
CREATE TABLE `user`(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
`name` TINYTEXT UNIQUE NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
`name` TINYTEXT NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (id) REFERENCES `user`(id)
);

Changing Foreign Key Table Name Isn't Updating Data Properly

I have the following tables:
CREATE TABLE publishers
(
name VARCHAR(50) NOT NULL,
status TINYINT DEFAULT 1 NOT NULL,
CONSTRAINT publishers_pk PRIMARY KEY (name)
);
CREATE TABLE titles
(
id INT NOT NULL AUTO_INCREMENT,
publisher VARCHAR(50),
title VARCHAR(50) NOT NULL,
status ENUM('active', 'announced', 'inactive'),
discount TINYINT NOT NULL,
CONSTRAINT title_pk PRIMARY KEY (id),
CONSTRAINT title_fk FOREIGN KEY (publisher)
REFERENCES publishers (name)
ON DELETE SET NULL
ON UPDATE CASCADE
);
When I change the "name" in publishers, it isn't changing the "publisher" in the titles table. Why is the behavior working this way?
Do you know what engine you are using? I read that MySQL with the default engine will parse the foreign key constraints but not actually do anything with them. Is it possible you're using the MyISAM engine?
http://dev.mysql.com/doc/refman/5.5/en/ansi-diff-foreign-keys.html