MySQL relations with restrictions - mysql

I have this table structure and simple relationships:
and sample data in the table:
Company
Company names are unique and should not be repeated:
+------------+---------------+
| Company_ID | Company_name |
+------------+---------------+
| 1 | Company_name1 |
+------------+---------------+
| 2 | Company_name2 |
+------------+---------------+
Location
(Locations should be assigned to a specific company):
+-------------+------------+-------------------------+
| Location_ID | Company_ID | Location_name |
+-------------+------------+-------------------------+
| 1 | 1 | Company1_Location_name1 |
+-------------+------------+-------------------------+
| 2 | 1 | Company1_Location_name2 |
+-------------+------------+-------------------------+
| 3 | 2 | Company2_Location_name1 |
+-------------+------------+-------------------------+
| 4 | 2 | Company2_Location_name2 |
+-------------+------------+-------------------------+
Data
The data in the table should depend on the selected company, and the locations should be only those that occur in the company:
+---------+-------------+------------+------------+------+
| Data_ID | Location_ID | Company_ID | data_value | date |
+---------+-------------+------------+------------+------+
| 1 | 1 | 1 | 5 | date |
+---------+-------------+------------+------------+------+
| 2 | 2 | 1 | 2 | date |
+---------+-------------+------------+------------+------+
| 3 | 3 | 2 | 3 | date |
+---------+-------------+------------+------------+------+
| 4 | 2 | 1 | 1 | date |
+---------+-------------+------------+------------+------+
| 5 | 4 | 2 | 6 | date |
+---------+-------------+------------+------------+------+
| 6 | 4 | 2 | 7 | date |
+---------+-------------+------------+------------+------+
The main dependencies that should be met:
Company names should be unique and attempts to add the same company should be blocked
Location names should be assigned to a specific company, but they may repeat and a location may appear in several companies but have a different Location_ID
Adding values to the date table should depend on:
company (we choose a specific company for which we add values)
locations (locations must depend on company)
For example:
When adding values for a company with Company_ID = 1, I should only be able to add Location_ID that occur under that company.
If I want to add a value in the data table for Company_name1 then the only available values for the Location_ID column in the data table, should be: Company1_Location_name1 and Company1_Location_name2 and I can't have values there from another company (i.e. Company2_Location_name1 and Company2_Location_name2)
At the moment it works badly:
when adding values to the data table I can select a company, but then I have locations available and I can add values that do not make sense - for Company_name1 I can add a location from Company_name2 but it should be blocked.
How can I solve such a problem? Add some additional table which will be responsible for particular pairing?

Depends what database you use.
A simpler way would be to just create a unique constraint on the table field, this will also enforce it for updates too and remove the need for a trigger. Just do:
Example for MSSQL:
ALTER TABLE [dbo].[Company]
ADD CONSTRAINT [Company_name] UNIQUE NONCLUSTERED
(
[CompanyID], [Company_name]
)
and then you'll be in business. You will be not able to add 2 company with the same name.
You can find another examples here : Trigger to prevent Insertion for duplicate data of two columns
This is exacly what you are looking for :)
#EDIT 1
OK so if you want example for MARIADB here we go :
Create unique Contraint - Using a CREATE TABLE statement
The syntax for creating a unique constraint using a CREATE TABLE statement in MariaDB is:
CREATE TABLE table_name
(
column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
CONSTRAINT constraint_name UNIQUE (uc_col1, uc_col2, ... uc_col_n)
);
table_name
The name of the table that you wish to create.
column1, column2
The columns that you wish to create in the table.
constraint_name
The name of the unique constraint.
uc_col1, uc_col2, ... uc_col_n
The columns that make up the unique constraint.
In your example :
CREATE TABLE Company
( Company_ID INT(11) PRIMARY KEY AUTO_INCREMENT,
Company_name VARCHAR(250) NOT NULL,
CONSTRAINT company_name_unique UNIQUE (Company_name)
);
In this example, we've created a unique constraint on the Company table called company_name_unique. It consists of only one field - the Company_name field.

Related

Two foreign keys reference one table and null able foreign key

I am new to Database tables and relationships .I need some help for the below requirements
Work flow
1. Hospital will have Male Patient
2. Hospital will have Female Patient
3. Hospital Will have Couple Patient but in RegTable it will stored as separate record for male and female.
For the above requirements i have designed the table structure below
Approach 1
RegTable
+-------+---------+---------+
| RegID | Name | Gender |
+-------+---------+---------+
| 1 | XXX | M |
| 2 | XXX | M |
| 3 | Husband | M |
| 4 | Wife | F |
+-------+---------+---------+
RegDetail
+----+------+-------+
| Id | FK_1 | FK_2 |
+----+------+-------+
| 1 | 1 | Null |
| 2 | 2 | Null |
| 3 | 3 | 4 |
+----+------+-------+
FK_1,FK_2 is RegId from Regtable
I have two questions
Is my current approach is correct or Not ?
Is alternative approach is there for the above work flow .
Kindly help me solve this . Thanks in Advance
You don't need 2 tables here.You can do it as shown below.
RegTables - this is the only table you need
Id int PK
Name string
Gender String
PatientType tinyint
Here you can maintain enum Type for separating Single and couple.
public enum PatientType : byte
{
Single=1,
Couple =2,
}
Update :
Treatments table
Id int PK
Name string
RegId int FK --> this is the foreign key referencing RegTables table
I would suggest the third table RegRecords with field
id, note, date. It will contain a registration data without link to RegTable. So you will store links to real people in RegDetail that will have only two fields: FK_KEY_RegRecords and FK_KEY_ RegTable.

Add a temporary column in mysql who's entries are counts of same entries of a table

So I have this database which contains in it a list of files. Files can be updated, but the previous versions are still held on to in case of rollbacks. What I want to know is how would I add a temporary column that contains the number of previous versions for that file.
Essentially, how would I crate a temporary column in mysql who's entries depend on something within the main table?
CREATE TABLE Files(
file_id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
student_id INTEGER,
group_id INTEGER,
submission_number INTEGER,
submission_type VARCHAR(10),
FOREIGN KEY (student_id) REFERENCES Student (student_id) ON DELETE CASCADE,
FOREIGN KEY (group_id) REFERENCES Groups(group_id)ON DELETE CASCADE
);
A submission is defined by its submission_number and submission_type. So submission_type 0 would be an assignment, 1 would be a project, 2 would be a quiz and so on. submission_number would be which assignment of that submission type we are uploading. So for example, the third quiz will have a submission_type =2 and a submission_number = 3. we can update a file, so we can upload a new file with the same submission_type and submission_number. What I want to return is a table which contains the number of times each submission had an upload.
So if i had the following table
+---------+------------+----------+-------------------+-----------------+
| file_id | student_id | group_id | submission_number | submission_type |
+---------+------------+----------+-------------------+-----------------+
| 1 | 10049 | 1 | 1 | assignment |
| 2 | 10032 | 1 | 1 | assingment |
| 3 | 10032 | 1 | 2 | quiz |
| 4 | 10032 | 1 | 3 | assingment |
+---------+------------+----------+-------------------+-----------------+
I would want to return the table
+-------------------+-----------------+-------+
| submission_number | submission_type | count |
+-------------------+-----------------+-------+
| 1 | assignment | 2 |
| 2 | quiz | 1 |
| 3 | assignment | 1 |
+-------------------+-----------------+-------+
Another way to think about it, if submission_number and submission_type were coordinates instead, say x,y then i want to count the number of times the same point appears in the table. So the point (1,assignment) appeared twice thus the count is 2.
You don't need another table just to do that. Just write a query using GROUP BY.
SELECT submission_number, submission_type, COUNT(file_id) FROM Files GROUP BY submission_number, submission_type;
working demo

Get row values from foreign key MySQL

This may sound simple and dumb but how can I get the values of a foreign key from a table and displaying it?
I have a table named "subjects" which contains different school subjects and one column of it is a foreign key referencing from table named "faculty".
TABLE subjects
___________________________________
| sub_id | sub_faculty | sub_desc |
| 1 | 2 | PHYSICS |
| 2 | 3 | MATH |
| 3 | 4 | HISTORY |
|________|_____________|__________|
TABLE faculty
________________________
| fac_id | fac_name |
| 2 | John |
| 3 | Mark |
| 4 | Johnny |
|________|_____________|
I firstly wanted to check if data exist in the "subject" table and then proceed on displaying the row values of the foreign key.
I have this not so working query as displays both JOHN and JOHNNY. I was using LIKE as it will be for the search feature of the system so hopefully you can help me out on this.
SELECT *
FROM subject, faculty
WHERE subject.sub_desc = 'PHYSICS'
AND subject.sub_year = '4'
AND faculty.fac_name LIKE '%JOHN%'
GROUP BY faculty.fac_id
SELECT *
FROM subject s
join faculty f
on s.sub_faculty = f.fac_id
WHERE s.sub_desc = 'PHYSICS'
AND s.sub_year = '4'
AND f.fac_name LIKE '%JOHN%'

Mysql: Change set column on update condition?

I'm trying to figure out the best way to update one of two fields in a table. I have a personrelationship table and it links two people and I would like to have each person be able to set the relationship type on their end.
PersonRelationship Table
id int
user1_id int
user2_id int
user1_reltype /* boss, manager, etc */
user2_reltype
Depending on whether the current user is either user1_id or user2_id in the table, I need to update the user_reltype accordingly. So basically if current userid is in the user1_id field then update user1_reltype otherwise update the user2_reltype.
Since you want each user to be able to independently manage their half of the relationship, you can simplify your table structure
--------------------------------------
| initiator_id | reltype | target_id |
When a person with ID 5 (the 'initiator') marks person with ID 9 (the 'target') as a friend, the table will contain:
---------------------------------------
| initiator_id | reltype | target_id |
+--------------+----------+-----------+
| 5 | 'friend' | 9 |
If person 9 later initiates a 'boss' connection with person 5, the entry can be created without interfering with the row previously created by person 5:
--------------------------------------
| initiator_id | reltype | target_id |
+--------------+---------+_----------+
| 9 | 'boss' | 5 |
This approach will make your table easy to read and your queries easy to write.
Extra:
If you do not already have it, consider creating another table to track relationship types ('reltype'):
-----------------
| id | type |
+----+----------+
| 1 | 'friend' |
| 2 | 'boss' |
and replace the string reltype's in the relationship table with foreign keys.
---------------------------------------
| initiator_id | reltype | target_id |
+--------------+----------+-----------+
| 5 | 1 | 9 |
| 9 | 2 | 5 |

Store string and foreign key in one column

I'm building a website with a large number of categories, each with its own specific form fields. Because there are so many categories, I wanted to store those form fields in a database.
The categories are stored in a category table:
id | name
-------------
1 | Car info
The fields for that category are stored in a category_field table:
id | fk_id_category | type | label
-------------------------------------------------------------
1 | 1 | text | Your name
2 | 1 | radio | What type of car do your drive?
If a category_field has some predefined options from which the user can choose then these are stored in a category_field_option table:
id | fk_id_category_field | label
-----------------------------------------
1 | 2 | 'Convertible'
2 | 2 | 'Truck'
3 | 2 | 'Minivan'
Now, when a user fills out a form we want to save a reference to this in a form_entry table:
id | fk_id_user | fk_id_category
--------------------------------
1 | 1 | 1
The details of that form entry are saved in a form_entry_details table. However:
If the category_field.type is text we should just save the answer as string
id | fk_id_form_entry | fk_id_category_field | [answer]
-------------------------------------------------------
1 | 1 | 1 | John Doe
If the category_field.type is radio, I want to save a foreign key to the category_field_option
id | fk_id_form_entry | fk_id_category_field | [fk_id_category_field_option]
--------------------------------------------------------------------------
2 | 1 | 2 | 2
How can I solve this? I know I could just store the fk_id_category_field_option as a string, but I need it to actually reference to the category_field_option table since I'm using an ORM (Doctrine 1.2.4).
You can't because the whole idea of foreign keys is to prevent this sort of situation. You either store it as one field without an enforce foreign key or you create two columns, one for the foreign key id (perhaps a default value that relates to 'user defined') and another that takes the user defined info and, probably, defaults to null.