How to implement an Aggregation in SQL? (This is not about GroupBy) - mysql

In the scope of a university project I am supposed to implement an aggregation of my database.
I'm given a Entity-Relationship model which looks similar to this one:
Now I'm supposed to implement a SQL-Script which creates a database like this, but I cannot find anything about this topic on google or anywhere else. In the slides of my Professor it says
For example, to represent aggregation manages between relationship works_on and entity set manager, create a schema
manages(employee_id, branch_name, title,manager_name)
Schema works_on is redundant provided we are willing to store null values for attribute manager_name in relation on schema manages
So I tried to just put two tables into my SQL-Script one called works-on and one called manages. In works-on I put all the Primary keys of job, branch and employee and defined them as foreign keys. In manages I put all of these Primary keys and additionally I put manager. Now the problem is that when I use the Reverse-Engineer of MySQL-workbench to create the EER-Model of the database, I don't get anything out of it which has to do with this aggregation. So what am I doing wrong here?
As requested by #Barmar I just wrote the CREATE TABLE-statements that I would've used for this:
CREATE TABLE job
(jobid INT,
PRIMARY KEY(jobid));
CREATE TABLE employee
(employeeid INT,
PRIMARY KEY(employeeid));
CREATE TABLE branch
(branchid INT,
PRIMARY KEY(branchid));
CREATE TABLE manager
(managerid INT,
PRIMARY KEY(managerid));
CREATE TABLE works_on
(jobid INT, KEY(jobid),
branchid INT, KEY(branchid),
employeeid INT, KEY(employeeid));
CREATE TABLE manages
(jobid INT, KEY(jobid),
branchid INT, KEY(branchid),
employeeid INT, KEY(employeeid),
managerid INT, KEY(managerid));
ALTER TABLE works_on
ADD CONSTRAINT FK_workson_employee FOREIGN KEY(employeeid) REFERENCES employee(employeeid);
ALTER TABLE works_on
ADD CONSTRAINT FK_workson_branch FOREIGN KEY(branchid) REFERENCES branch(branchid);
ALTER TABLE works_on
ADD CONSTRAINT FK_workson_job FOREIGN KEY(jobid) REFERENCES job(jobid);
ALTER TABLE manages
ADD CONSTRAINT FK_manages_employee FOREIGN KEY(employeeid) REFERENCES employee(employeeid);
ALTER TABLE manages
ADD CONSTRAINT FK_manages_branch FOREIGN KEY(branchid) REFERENCES branch(branchid);
ALTER TABLE manages
ADD CONSTRAINT FK_manages_job FOREIGN KEY(jobid) REFERENCES job(jobid);
ALTER TABLE manages
ADD CONSTRAINT FK_manages_manager FOREIGN KEY(managerid) REFERENCES job(managerid);

Your ER-Diagram is missing an important information: the cardinality between the manager and the new entity that is built from the other 4 elements job, employee, manager, branch and works-on (this new entity is marked by the square around them).
From the quote on the slides we can deduce that it is a 0..1-relationship,
that means every combination of job, branch and employee (or every entry in works-on) has at most one manager, but does not require one (in contrast to e.g. a composition).
But you will have to verify that cardinality in your actual task.
You can oftentimes implement an ER-diagram in several ways, but the slides imply the following realization:
CREATE TABLE manages
( jobid INT not null,
branchid INT not null,
employeeid INT not null,
managerid INT null,
PRIMARY KEY (jobid, branchid, empoyeeid)
);
I omitted the trivial foreign keys to the tables job, employee, manager and branch.
With this implementation, you do not have an explicit table for the works-on-relation anymore, just like the second statement in your slides says. It is included in the manages table. That's only possible for a 0..1-relation, which is why that cardinality was deducable.
If you want to keep a table for works-on, you would use
CREATE TABLE works_on
( jobid INT not null,
branchid INT not null,
employeeid INT not null,
PRIMARY KEY (jobid, branchid, empoyeeid)
);
CREATE TABLE manages
( jobid INT not null,
branchid INT not null,
employeeid INT not null,
managerid INT not null,
PRIMARY KEY (jobid, branchid, empoyeeid),
FOREIGN KEY (jobid, branchid, employeeid)
REFERENCES works_on (jobid, branchid, employeeid)
);
Again, I omitted the trivial foreign keys.
To simplify the foreign key (and maybe to emphasize that the combination is considered a new entity), you can, as #Barmar proposed, add an additional (usually auto-increment) key to the works_on-table and use this value in the manages-table, although the slides do not do this here.
In case you need to implement a 0..n-relation (several manager can manage a specific works-on-combination), you cannot absorb the works-on-relation in the manages-relation anymore (so you need both tables), and to respect the n, you will have to include managerid in the primary key, PRIMARY KEY (jobid, branchid, empoyeeid, managerid) (but still need to keep the FOREIGN KEY (jobid, branchid, employeeid)).

You need to give a primary key to the works_on table, and then reference that in the manages table, rather than referencing employee, job, and branch directly.
CREATE TABLE works_on (
works_on_id INT PRIMARY KEY,
jobid INT,
branchid INT,
employeeid INT,
CONSTRAINT jobid FOREIGN KEY REFERENCES job(jobid),
CONSTRAINT branchid FOREIGN KEY REFERENCES brahc(branchid),
CONSTRAINT employeeid FOREIGN KEY REFERENCES employee(employeeid)
);
CREATE TABLE manages (
managerid INT,
works_on_id INT,
CONSTRAINT managerid FOREIGN KEY REFERENCES manager(id),
CONSTRAINT works_on_id FOREIGN KEY REFERENCES works_on(id)
)

Related

Can a primary key of a subclass table be referenced as a foreign key?

I'm currently working on a mysql project for my class and I'm wondering if the PK-FK of a subclass table can be referenced as FK for another table instead of the PK of the parent class.
Let's say I have the subclass table employees written as:
CREATE TABLE employees (
Person_ID int PRIMARY KEY,
Designation varchar(50),
FOREIGN KEY (Person_ID) REFERENCES persons(Person_ID));
As for the parent class,
CREATE TABLE persons (
Person_ID int NOT NULL AUTO_INCREMENT,
Last_Name varchar(255),
Middle_Name varchar(255),
First_Name varchar(255),
PRIMARY KEY(Person_ID));
Let's say I want to create another table works whose FK references Person_ID from the subclass employees, not the parent class persons.
CREATE TABLE works (
project_ID PRIMARY KEY,
date_started date,
FOREIGN KEY (Person_ID) REFERENCES employees(Person_ID));
Thanks!
Yes, that's technically possible (I guess you tested that already) and is logically also OK in such a case as yours. In fact referencing persons would be wrong if, logically, only employees can take part in the "works on" relation -- the FK constraint wouldn't ensure that they're only employees.
It is no Problem, but you have always check if the id exist.
Ring connection can cause problems.
CREATE TABLE persons (
Person_ID int AUTO_INCREMENT,
Last_Name varchar(255),
Middle_Name varchar(255),
First_Name varchar(255),
PRIMARY KEY(Person_ID));
✓
CREATE TABLE employees (
Person_ID int PRIMARY KEY,
Designation varchar(50),
foreign key (Person_ID) REFERENCES persons(Person_ID));
✓
CREATE TABLE works (
project_ID Int PRIMARY KEY,
date_started date,
Person_ID int,
FOREIGN KEY (Person_ID) REFERENCES employees(Person_ID));
INSERT INTo persons VALUES (NULL,'A','B','C')
INSERT INTO employees VALUES (1,'test')
INSERT INTO works VALUES (1,NOW(),1)
db<>fiddle here

Failed to open the referenced table

I am new with SQL and I am not entirely sure why I am getting the error: ERROR 1824 (HY000) at line 5: Failed to open the referenced table 'products'
Operation failed with exitcode 1
Here is my code
drop database if exists cc;
create database cc /*!40100 default character set utf8 */;
use cc;
create table Customers(
CustomerID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
prodID int,
quantity int,
primary key (CustomerID),
foreign key (prodID) references Products(itemID)
);
create table Employees(
EmployeeID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
ManagerID int not null,
primary key (EmployeeID),
foreign key (managerID) references Managers(mgrID)
);
create table Managers(
mgrID int not null,
salary float,
MaxSupervisingCapacity int,
foreign key (mgrID) references Employees(EmployeeID),
primary key (mgrID)
);
You can't create a foreign key that references another table until after you create that other table. In the Customers table you have
foreign key (prodID) references Products(itemID)
but there's no Products table yet. And in Employees you have
foreign key (managerID) references Managers(mgrID)
but the Managers table is created after it.
You need to reorder your table creations. Create Products before Customers.
Also, you can't have circular foreign key relationships. Employees.managerID references Managers and Managers.mgrID references Employees. This creates a chicken-and-egg problem: how would you create the first employee, since it needs a manager, but you can't create the first manager because it needs to refer to an employee.
You can solve this problem by allowing the foreign keys to be null. So you create the first employee with a null manager, then create the manager, then replace the managerID with this ID.
There's also a chicken-and-egg problem when creating these two tables. You can't reference a table that has yet to be created. So leave out the foreign key specification when creating the table, and add it later with ALTER TABLE.
create table Employees(
EmployeeID int not null,
FirstName varchar(255),
LastName varchar(255),
address varchar(255),
phoneNO varchar(11),
ManagerID int not null,
primary key (EmployeeID)
);
create table Managers(
mgrID int not null,
salary float,
MaxSupervisingCapacity int,
foreign key (mgrID) references Employees(EmployeeID),
primary key (mgrID)
);
alter table Employees add foreign key (managerID) references Managers(mgrID);
You can just surround the whole thing with a
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS;
SET FOREIGN_KEY_CHECKS=0;
## all of your schema and inserts
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
This change of the check will cause the engine not to do checks on those keys and just add them as is.
I have Just fixed this problem by Cheking both tables Storage Engine same and by settings the same Attributes for reff tables column.
you can try assigning the "ENGINE = INNODB" of the tables when creating them. One of the drawbacks when creating Foreign keys is that, the foreign keys can only be defined for certain storage engines (like InnoDB). The server accepts foreign key definitions for other storage engines but silently ignores them.
Example:
CREATE TABLE `Customers` (
CustomerID int not null,
FirstName varchar(255),
...
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
As you can see, when the table is finished, it is assigned the Engine = InnoDB and the default charset.
If you want to alter the table, you can do the following:
ALTER TABLE `Customers` ENGINE = InnoDB ;
If it served you, do not forget to approve the answer, you can make life easier for many developers.
I tried everything and nothing didn´t really work for me until I did the most simple thing. Go to SCHEMAS select the one that has de databases you are trying to work with and with right click, select set as default schema. That´s all, it worked perfectly.
Hope it helps

Using of unique column name for each primary and foreign keys in mysql table to avoid ambiguous condition

Which is better method among below:-
Using unique column name for each column, primary and foreign keys among all table.
Example 1:
CREATE TABLE projects (
project_id PRIMARY KEY,
project_name VARCHAR(30)
client_id INT,
fk_project_user_id INT, ( FOREIGN KEY )
projects_created_by INT, ( FOREIGN KEY )
);
CREATE TABLE clients (
client_id PRIMARY KEY,
client_name varchar(20),
fk_client_user_id INT,( FOREIGN KEY )
client_created_by INT, ( FOREIGN KEY )
)
Don't care about the uniqueness of each column name for each primary and foreign keys among all tables.
Example 2:
CREATE TABLE projects (
id PRIMARY KEY,
project_name VARCHAR(30)
client_id INT, ( FOREIGN KEY )
fk_user_id INT, ( FOREIGN KEY )
created_by INT ( FOREIGN KEY )
);
CREATE TABLE clients (
id PRIMARY KEY, (Same as above table)
client_id INT,
client_name varchar(20),
fk_user_id INT, ( FOREIGN KEY ) (Same as above table)
fk_client_id int, ( FOREIGN KEY )
created_by INT ( FOREIGN KEY ) (Same as above table)
);
When we plan database for big ERP having multiple tables and relationships among all? I have used a different name for each key to avoiding ambiguous error when we join two tables.
What is the best solution?
Naming conventions are up to you. Which naming convention you decide to use is not important. What's important is that you follow your own convention consistently, and document it so that other developers know how to understand your code and your schema.
Some people choose to give every table a primary key named id. If every one of their tables must have a column named id, then they can write reusable code for certain queries against any table.
However, this convention does not account for compound primary keys. Also if your query does a join, the query result set may have multiple columns named id unless you define column aliases.
When I design a database, I name my primary key in a descriptive way. projects.project_id for example. This avoids the problem of duplicate column names in a result set of a join. It also makes it more clear what the column means when you see it in a query or a result set.
I like to name the foreign key the same as the primary key column it references, when I can do it without resulting in a conflict.
But consider this example, where there are multiple foreign keys in the same table that reference Users.user_id.
CREATE TABLE Bugs (
bug_id INT PRIMARY KEY,
description TEXT NOT NULL,
reported_date DATETIME NOT NULL,
user_reported_by INT NOT NULL,
user_assigned_to INT,
user_verified_by INT,
FOREIGN KEY (user_reported_by) REFERENCES Users(user_id),
FOREIGN KEY (user_assigned_to) REFERENCES Users(user_id),
FOREIGN KEY (user_verified_by) REFERENCES Users(user_id)
);
You can't assume you can use a common column name, because it's normal to need multiple foreign keys referencing the same table, as in the example above. Therefore you must allow the FK column name to be different from the PK it references.

how to put foreign key in mysql

I want to know how to use a foreign key in a table,
I have a code here:
create table penerbit_buku(
id_buku char(8),
foreign key(id_buku) references buku(id_buku),
id_penerbit char(3),
foreign key(id_penerbit) references penerbit(id_penerbit)
)
Can I use this code instead:
create table penerbit_buku(
id_buku char(8) references buku(id_buku),
id_penerbit char(3) references penerbit(id_penerbit)
)
I have tried both and it succeed, is that correct?
No, MySQL parses but ignores the standard inline REFERENCES syntax.
When you declare a foreign key along with an individual column definition, it accepts the syntax as legitimate SQL, but then does not store the foreign key constraint. There's no error reported, but it's as if you didn't write the foreign key syntax at all.
You must declare foreign keys as table-level constraints (your first example above).
This is a case where MySQL is missing a feature of standard SQL. The issue was reported back in 2004, but never fixed! https://bugs.mysql.com/bug.php?id=4919
The reason for this issue is that historically, foreign key constraints were not supported by MySQL itself, but by the InnoDB storage engine, which was made by another company back then. They had to implement their own parser for CREATE TABLE and ALTER TABLE to support foreign keys, and they didn't feel like going the extra steps to support inline foreign key syntax, when table-level foreign key syntax would work.
The architect of InnoDB posted this response:
[6 Sep 2006 10:03] Heikki Tuuri
This will be fixed in MySQL foreign keys, when they are available for all table types.
The MySQL project is gradually working their way toward integrating foreign keys and similar features directly into the MySQL product. Perhaps in a few more years we'll see better support for standard FK syntax.
EXAMPLE:
CREATE TABLE Orders (
ID int NOT NULL,
Number int NOT NULL,
PersonID int,
PRIMARY KEY (ID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
The foreign key must be referencing a primary key in another table
create table penerbit_buku
(id_buku char(8),
id_penerbit char(3),
foreign key(id_buku) references buku(id_buku),
foreign key(id_penerbit) references penerbit(id_penerbit)
);
I would need to see your other tables to give better help in the code
You can use this:
ALTER TABLE `table1`
ADD CONSTRAINT `FK_table1_table2` FOREIGN KEY (`fk_id`) REFERENCES `table2` (`id`);
first lets look at the description of FOREIGN KEY.
A FOREIGN KEY is a key used to link two tables together.
or
A FOREIGN KEY is a field (or collection of fields) in one table that refers to the PRIMARY KEY in another table.
Usually a table that has the foreign key is the child table. and the other table is the reference or parent table.
Since i Can not see your tables, ill give you different example.
Look at the following two tables:
Persons table:
Personal_id LastName FirstName age
1 pretty bob 20
2 angry jack 30
3 happy sue 28
Order Table:
OrderID OrderNumber Personal_id
1 77895 3
2 44678 3
3 22456 2
4 24562 1
Now look how Personal_id column in Orders table points to Personal_id in persons table.
The Personal_id in persons table is the primary key and the Personal_id in the orders table is the FOREIGN KEY.
now except linking how does foreign key help:
two general ways that i can think of:
1- foreign key is like a constrain that makes sure no action would destroy the links between tables
2- foreign key also acts as a constrain to stop invalid data from being inserted into the foreign key column, as it has to reference to the primary key column in the other table
code example in MySql:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (Personal_id) REFERENCES Persons(Personal_id)
);
code example is SQL-Server/MS Access/ Oracle:
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
OrderNumber int NOT NULL,
PersonID int FOREIGN KEY REFERENCES Persons(Personal_id)
);
Primary key of Orders table is the orderID.
Foreign key of Orders table is what links it to persons table.
Personal_id columns are the columns that link both tables.
Both of the code chunks do the same depends what are you working with.
real world example:
assuming:
customer_Table column to be a primary key in restaurant table and foreign key in orders table.
if a waiter is putting customer_Table number 20 in the machine, and he puts customer_Table 200 by mistake such key does not exist as a primary key in restaurant table so he cant.
Extra:
what if you want to allow naming of the FOREIGN KEY constraint, and define a FOREIGN KEY constraint on many columns?
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
Personal_id int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder FOREIGN KEY (Personal_id)
REFERENCES Persons(Personal_id)
);

What have I done wrong here

I am relatively new to the database world so bear with me. I'm just trying to add foreign key constraints and I keep getting error 1215 "cannot add foreign key constraint".
CREATE TABLE InProcessSamples
(
SampleNumber Int(6),
WorkOrder Int(8),
DueDate Date,
BeginsTesting Date,
FinishedTesting Date,
CONSTRAINT fk_sample_number FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber),
CONSTRAINT fk_work_order FOREIGN KEY(WorkOrder) REFERENCES SamplesReceived(WorkOrder)
);
CREATE TABLE SamplesReceived
(
WorkOrder Int(8) PRIMARY KEY,
SampleNumber Int(6),
RecTimeStamp DateTime,
PartNumber Int(10),
Description Char(36),
CONSTRAINT fk_sample_number FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber),
CONSTRAINT fk_part_number FOREIGN KEY(PartNumber) REFERENCES PartNumbers(PartNumber)
);
CREATE TABLE AllRecords
(
SampleNumber Int(6) PRIMARY KEY,
WorkOrder Int(8),
DueDate Date,
BeginsTesting Date,
FinishedTesting Date,
RecTimeStamp DateTime,
MeasurementOne Double,
MeasurementTwo Double,
PassDielectric Char(3),
PassedAllTest Char(3),
CONSTRAINT fk_work_order FOREIGN KEY(WorkOrder) REFERENCES SamplesReceived(WorkOrder),
CONSTRAINT fk_part_number FOREIGN KEY(PartNumber) REFERENCES PartNumbers(PartNumber)
);
CREATE TABLE PartNumbers
(
PartNumber Int(10) PRIMARY KEY,
Description Char(36)
);
Regardless of whether your design is off or not, you can't declare a foreign key reference to a table you haven't created yet.
CREATE TABLE statements are evaluated in order from top to bottom of your SQL script. As MySQL is trying to create the first table, the second and third tables don't exist yet. So there's nothing for the foreign keys to reference.
You should create tables in an order that allows the referenced table to exist before you create the table that has the foreign key to reference it. In this case, you have a circular dependency, so the only way to do it is to create either SamplesReceived or AllRecords without one of its foreign keys, and then go back afterward and add that foreign key.
CREATE TABLE PartNumbers, because it's needed by SamplesReceived and AllRecords
CREATE TABLE SamplesReceived, because it's needed by InProcessSamples and AllRecords
CREATE TABLE AllRecords, because it's needed by InProcessSamples
ALTER TABLE SamplesReceived ADD FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber);
CREATE TABLE InProcessSamples
That's if the circular reference is really needed.
But as other folks have answered, perhaps your circular reference isn't really a good design.
The circular reference could be needed; what it does in your case is enforce that for every row in SamplesReceived, you must have a matching row in AllRecords, and vice-versa, every row in AllRecords must have a matching row in SamplesReceived.
I don't know why that's important in your application. It might be, but you haven't told us anything about the workflow you're trying to model so I can't tell.
the normalization is all wrong:
this one is good:
Part
---------------
Part_id
Description
then you have redundancies and other issues everywhere...
maybe start with this:
WorkOrder
-------------
workorder_id
Sample
----------
sample_id
workorder_id
part_id
Test
--------------
test_id
description
min_passing_value
max_passing_value
TestResult
---------------
testresult_id
test_id
description
result_value
test_date
sample_id