mySQL database structure - java

I'm kinda stuck in a tricky situation with the mySQL DB design for my webservice.The DB had initially this Structure:
CREATE TABLE IF NOT EXISTS `Disease` (
`Name` varchar(20) NOT NULL,
`Age` int(10) unsigned NOT NULL,
`Descriptin` text NOT NULL,
`Sex` varchar(10) NOT NULL,
`Ethnicity` varchar(20) NOT NULL,
PRIMARY KEY (`Name`,`Sex`,`Ethnicity`),
KEY `Sex` (`Sex`),
KEY `Ethnicity` (`Ethnicity`)
)
ALTER TABLE `Disease`
ADD CONSTRAINT `Disease_ibfk_1` FOREIGN KEY (`Sex`) REFERENCES `Sex` (`Sex`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `Disease_ibfk_2` FOREIGN KEY (`Ethnicity`) REFERENCES `Ethnicity` (`Ethnicity`) ON DELETE CASCADE ON UPDATE CASCADE;
So basically Disease(Name,Age,Description,Sex, Ethnicity ) Where Sex and Ethnicity are foreign keys to two tables named Sex and Ethnicity because they can have more than one value.
Now to the question I need to add another Column called Symptoms which will be multivalued but I cant declare it as a foreign key, what i need is this:
example of a row
Disease(Name="DiseaseName",Age="40",Description="is caused by...",Sex="male",Ethnicity="Caucasian",Symptoms"Headache,sorethroat,fever")
So basically i need Symptoms to contain a String of Array but apparently I cant do it since its an RDBMS
Thanks all for you time and efforts!

Don't do that. Instead, normalize your data model: Make a new table "Symptoms", constrained with foreign key "Disease", and make one record for each symptom.
Whenever you start thinking about putting collections of data into a single field, you're effectively trying to build your own mini database inside the database. Thinking that you can outperform and outwit your RDBMS is optimistic at best and most likely leads to unmaintainable code later on.
By the way, does Sex really have to be looked up in a separate table? For micro-categories like that you might like to consider some sort of enum type.

You can accomplish the "array of strings" you're looking for by normalizing your data. Add a new key column to your 'Disease' table. Then create a child table called 'Symptom'. Insert a record for each string with a foreign key back to the 'Disease' table parent record.

In case you didn't notice you misspelled Description in your table creation query.

You need a m:n relation:
Table: Disease
Name
Sex
Ethnicity
Table: Symptoms
ID
Name
Table: Disease_has_Symptoms
Name (FK to Disease)
Sex (FK to Disease)
Ethnicity (FK to Disease)
ID (FK to Symptoms)
(Maybe it's easier to add an ID-column to Disease and reference that inside Disease_has_Symptoms)

Related

How to generate a unique "id" for a model and its relations?

Lets say i have three entities: Order, OrderLine, OrderLineInfo
Now I would like to generate an id which I can store on the Order so next time another order is created I can take a look in the database and see if an identical order was created. Identical means same stuff and quantity. Without the id I would have to select all orders, lines and so on and do a compare.
Is there some kind of best practice for generating an id like this?
A couple of examples of using UNIQUE
CREATE TABLE hr.persons(
person_id INT IDENTITY PRIMARY KEY,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
email VARCHAR(255),
UNIQUE(email) //#cannot have two records that share the same email
);
CREATE TABLE hr.persons(
person_id INT IDENTITY PRIMARY KEY,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
email VARCHAR(255),
UNIQUE(first_name, last_name) //#cannot have two records that share the same first_name and last_name
);
I would recommend using a method similar to or even hashCode(). Implement it for all three entities including exactly the data you need for your identity check.
Finally add a column to your Order entity table holding the hashcode value and put an index on it (no unique one except you want to prohibit two identical orders in your database). Now you can simply look for an identical order searching for that hashcode.
Make sure the columns value is always up to date. If the ORM is using getter and setters you may delegate the getter to use hashCode() and simply ignore the setter.
Don’t forget to override equals() if you use hashCode() to not break the Java language contract!

How I create table with PRIMARY and FOREIGN KEY compose [duplicate]

I've read the rather cool styled BNF grammar for the SQLite create table statement
found here: http://www.sqlite.org/lang_createtable.html
I was wondering how I'd go about creating a link table between these
I have one table, lets say, houses, and another electrical_items.
I want to create a link table to have the house_id and the item_id as a composite key, but I'm not sure how I'd go about doing it, it doesn't appear to allow a primary key to be a foreign key ?
N.B I want a third field pap_tested which stores the date the electrical item in the house was pap_tested so this linking table via composite primary key seems the best approach.
Either of these should work for your association table:
create table house_items (
house_id integer not null,
item_id integer not null,
foreign key (house_id) references houses(id),
foreign key (item_id) references electrical_items(id),
primary key (house_id, item_id)
)
create table house_items (
house_id integer not null references houses(id),
item_id integer not null references electrical_items(id),
primary key (house_id, item_id)
)
You'll probably want separate (single column) indexes on house_items.house_id and house_items.item_id as well.
Just to complement the first answer, it's a good practice to add a name to constraints, like the code below:
create table house_items (
house_id integer not null,
item_id integer not null,
constraint house_items_pk primary key (house_id, item_id),
constraint house_items_house_fk foreign key (house_id) references houses(id),
constraint house_items_items_fk foreign key (item_id) references electrical_items(id));
There is no prohibition about a PRIMARY KEY not also being a FOREIGN KEY for those designs that require this kind of relation. Your problem isn't one of those, however, since the natural PRIMARY KEY in the linking table is a composite of the two columns, each a FOREIGN KEY back to one of the other tables.
I create a table with two foreign keys and options of on update cascade and on delete cascade.
CREATE TABLE category_subcategory
(
category_subcategory_id INTEGER PRIMARY KEY,
category_id INTEGER NOT NULL,
subcategory_id INTEGER NOT NULL,
FOREIGN KEY(category_id) REFERENCES categories(id) ON DELETE CASCADE ON
UPDATE CASCADE,
FOREIGN KEY(subcategory_id) REFERENCES subcategories(subcategory_id) ON
DELETE CASCADE ON UPDATE CASCADE
);

IDENTITY vs BIGINT regarding _ROWID_

My understanding is that the only difference between
CREATE TABLE T(ID IDENTITY PRIMARY KEY);
and
CREATE TABLE T(ID BIGINT IDENTITY);
is that the latter is more efficient since the ID column is the row id and as such corresponds the _ROWID_ pseudo-column.
Also, if I do
CREATE TABLE T(ID IDENTITY);
then ID doesn't correspond to _ROWID_ and it isn't even a primary key at all.
Are these assumptions correct?
As suggested I did some tests.
It turns out that all the three statements appear to be equivalent.
ID is always the primary key and corresponds to the _ROWID_ column.
After all, I went with a fourth variant:
CREATE TABLE T(ID BIGINT AUTO_INCREMENT, CONSTRAINT KEY_NAME PRIMARY KEY (ID));
This has the advantage that the primary key's name can be specified.
In the other cases the name was automatically generated, something along the lines of CONSTRAINT_0.
All of this with H2 1.4.190.

How to check for 3NF?

I have created a simple CRUD application database schehme. However, before implementing it I want to check if it is in 3NF:
CREATE TABLE person (
person_id int not null,
name char(30) not null,
student_no int,
staff_no int,
student_fieldOfStudy char(30),
staff_department char(30),
staff_position char(30),
faculty char(30),
PRIMARY KEY (person_id),
CONSTRAINT student_unique UNIQUE (student_no),
CONSTRAINT staff_unique UNIQUE (staff_no)
);
CREATE TABLE university (
university_id int not null,
foundationDate datetime not null,
university_name char(30) not null,
city_name char(30) not null,
country_name char(30) nut null,
PRIMARY KEY (universityID),
CONSTRAINT univ_unique UNIQUE (university_name, city_name)
);
CREATE TABLE course (
course_id int not null,
course_code char(20) not null,
lecturer_name char(30) not null,
lecture_day datetime not null,
faculty char(30) not null,
lecture_room char(30),
lecturer_id int,
student_id int,
FOREIGN KEY (student_id) REFERENCES Persons(person_id),
FOREIGN KEY (lecturer_id) REFERENCES Persons(person_id)
)
From my opinion it is in 3NF. I would appreciate your reply!
It's difficult to comment on a database design without knowing what business rules are supposed to be in force. You need to determine that from your own analysis of the business domain. Without that information all we can do is make some assumptions and guesses based on a list of table and column names.
The person table looks problematic. Are the student and staff columns supposed to be nullabale? It looks to me like you are maintaining two distinct types of person in one table. Probably better to create distinct tables for each of those person subtypes and just have the attributes that are common to both student and staff in the person table.
The concept of 3NF is based on relations and dependencies which permit only values, never nulls. If you have nulls then you don't have a relation that satisfies 3NF. Further, if staff_no is supposed to be a determinant for the staff attributes then it is a non-key determinant (because it's nullable). Nullable uniqueness constraints are a bad idea for multiple reasons and you should try to avoid them.
From a very short glimpse, the course table looks VERY non-3NF.
It lacks a key
Unless there is only one course per lecturer, then lecturer_id is not the key, so lecturer_name shouldn't be there
I guess there can be more than one student per course as well; in that case, student_id belongs somewhere else
Does a lecture room belong to one and only one faculty?
Isn't course_code dependent on course_id?
Just to get you started...

What is the application/utility of Foreign Key in MySQL?

Allow my to elaborate on the question with an example. I am writing from the
perspective that
(1) bytecodes should not be used to implement the logic already
implemented (hopefully more efficiently) in the database engine (e.g., if we
need to filter out 20 lines out of 500 coming out as the result of an SQL query,
we should be writing a better where clause), and that
(2) I have only a conceptual
understanding of foreign keys (e.g., they automatically create, manage and enforce
the constraints required to maintain data integrity across different tables).
Now, lets consider a simple schema with 4 tables and 15 columns in them
as follows (assume all columns are not null):
people
pid bigint autoinc PK
fname varchar(32)
lname varchar(32)
dob date
sex char(1)
addyID bigint FK to address(aid)
relationship
relof bigint FK to people(pid)
relto bigint FK to people(pid)
relis tinyint
address
aid bigint autoinc PK
street varchar(128)
zipcode int FK to z2cs(zip)
z2cs
zip int PK
city varchar(64)
state char(2)
Expectations (Please answer True/False to the following 6)
It is possible to create the table relationship as above with foreign keys
pointing to different rows of the same table
Adding a row to relationship throws SQLException if either relof or relto
is missing in people
If we add a row to address, we do not need to check if the zipcode is there in z2cs -
missing zip throws an SQLException
Attempt to delete a row from address throws an exception if aid is used in people
Attempt to delete a row from people causes error if pid is used in relationship in
either of the columns relto or relof
An SQL statement exists that lets you find which columns in a table are foreign keys
and which table(column) do they refer to (I know "describe tablename" doesn't do it,
although I feel that it should)
If the answer to any of the above is false, can you please guide me to finding
what exactly is the contract for foreign keys in MySql. Thank you.
PS: If you answer True to [6], would you please share what is that statement.
Bonus question (unrelated to FK):
How would you write the create statement for the relationship table that satisfies the following constraints:
relof and relto cannot be the same
Combination of relof and relto is unique, i.e.,
if their is a row with [relof=584,relto=7823], you cannot insert another row with
either [relof=584,relto=7823] or [relof=7823,relto=584]
1. It is possible to create the table relationship as above with foreign keys pointing to different rows of the same table
NO, a FK can only point to one row. But a row can be referenced by many other rows, like, an adress can be referenced by many people.
2. Adding a row to relationship throws SQLException if either relof or relto is missing in people
YES.
3. If we add a row to address, we do not need to check if the zipcode is there in z2cs - missing zip throws an SQLException
YES.
4. Attempt to delete a row from address throws an exception if aid is used in people
YES, if there is no Cascade Delete in the FK, which then automatically would delete the
entry in people instead of failing.
5. Attempt to delete a row from people causes error if pid is used in relationship in either of the columns relto or relof
YES, see 4.
6. An SQL statement exists that lets you find which columns in a table are foreign keys and which table(column) do they refer to (I know "describe tablename" doesn't do it, although I feel that it should)
AFAIK. There should be an information schema in MySQL where you can query the information from.
B1. relof and relto cannot be the same
Use a Trigger on update or insert to validate this. PostgreSQL knows CHECK constraints, which might ba also available in MySQL, but else a trigger is your choice.
B2. Combination of relof and relto is unique
A combined UNIQUE INDEX on both columns is your friend here.

Categories