Data normalisation into third normal form - database

I have done data normalization on dummy data and would like to know if I did it correctly. If it is done correctly, I would also like to ask two things below, because it is about 3NF.
1NF: This table should be 1NF.
userId
userName
keyNumber
keyCode
accessGroup
doors
1
Alice
1
1
1
1
1
Alice
1
1
1
2
1
Alice
1
1
1
3
2
Bob
2
2
2
1
2
Bob
2
2
2
2
3
Alice
3
3
2
1
3
Alice
3
3
2
2
2NF: I selected composite key (userID and Doors) as they represent minimal candidate key and got three tables applying FD rule.
Primary_key: userID
userId
userName
keyNumber
keyCode
accessGroup
Primary_key: doors
doors
Primary_key: (userid, doors)
userId
doors
3NF: Applying the rule of transitive dependency on 1st table in 2NF, I got out 4 tables (showing only first two, because the last two remain unchanged)
Primary_key: userID
userId
userName
Primary_key: keyNumber
keyNumber
keyCode
accessGroup
1
1
1
2
2
2
3
3
2
Questions:
Is this database normalisation correct? If not could you point me where I did mistake?
If answer on first question is True: Should the last table in 3NF be transformed into two tables, given it is not in correct Third normal form. Two non-key atributes have FD keycode -> accessGroup

Related

Extend row-level security to a bridging table

I am working on row level security in my database. I have two tables. Row based security is implemented on data_table and only returns rows that the user can see.
data_table:
data_id name role
-----------------------------
1 test USER
2 another ADMIN
3 yep USER
type_table:
type_id name
-----------------
1 this
2 is
3 a
4 type
EXECUTE AS USER = 'USER';
SELECT * FROM data_table;
returns rows 1 and 3 only. If you execute as ADMIN, all of the rows are returned. This is working properly in my database.
However, my issue is my bridging table.
data_type_table:
data_type_id data_id type_id
1 1 2
2 1 3
3 2 1
4 2 2
5 3 1
6 3 4
As of right now
EXECUTE AS USER = 'USER';
SELECT COUNT(data_type_id) FROM data_type_table;
returns 6 because it's looking at all 6 rows in the table. I'm trying to set it up in such a way that user USER will only see rows in data_type_table which are referencing rows where data_table.role = 'USER' (this means that the select count query would return 4). What would be the simplest way to implement something like this?
My data_table will more than likely contain hundreds of thousands of rows. Efficiency could become a problem here.

Is it possible to configure spring boot and to store multiple value (List) in one table (like OneToMany but not with 2 tables)?

You can have OneToMany relation between 2 tables, but You can also have this relation in just one table.
So, in this case, List of some property (column) will be repeated.
Let say, we have Entity with column ID_FIRST_TABLE and list of values ID_SECOND_TABLE for that ID_FIRST_TABLE.
As object it will be object1.listObjects2, and if it can be configured with just one table, it will be simple objectRepository.save(object1) and it will store
GENERATED ID | ID_FIRST_TABLE | ID_SECOND_TABLE | NAME
1 1 1 Name1
2 1 2 Name2
3 2 3 Name3
4 2 2 Name2
In this ONE TABLE is object (FIRST_TABLE) which has property as list of other objects (SECOND_TABLE).
Aobject1(FIRST_TABLE)
.id=1
.List<SECOND_TABLE> -> Bobject1(SECOND_TABLE)
.id=1
.name=Name1
-> Bobject2(SECOND_TABLE)
.id=2
.name=Name2
Aobject2(FIRST_TABLE)
.id=2
.List<SECOND_TABLE> -> Bobject3(SECOND_TABLE)
.id=3
.name=Name3
-> Bobject2(SECOND_TABLE)
.id=2
.name=Name2
So, I want to have just one table where when I save Aobject1 will save 2 records in that table (GENERATED ID 1 and 2).
When I save Aobject2, it will save also 2 records in that table (GENERATED ID 3 and 4).

Database schema for product quantity

I have some issues with creating database schema for a following scenario:
Shop, where you configure your order. Let's say user orders flowers and chocolate. So far I had the following structure:
OrderID FK_Flower FK_Chocolate
1 1 1
Where FK's pointed to the entry in database such as:
Id Name Price
1 Rose 100
The same for chocolate.
However now, there is a change: use can order multiple different flowers. So let's say, he can order 5 Roses, 3 Daisies.
What changes should I make, to solve this issue?
You want a many-to-many relationship.
Change the Orders table to something like this:
Orders:
-------
Id
1
The Flowers table stays the same:
Flowers:
------------------
Id Name Price
1 Rose 100
2 Daisy 120
Create a new table with with the Order and Flower ID's as foreign keys:
Orders_Flowers:
-------------------------
FK_Order_Id FK_Flower_ID
1 1
1 1
1 1
1 1
1 1
1 2
1 2
1 2
This way, the Order with Id = 1, has 5 Roses and 3 Daisies.

One or four tables? (db structure)

Items are connected to:
one or more "region" and/or
one or more "county" and/or
one or more "city" and/or
one or more "place".
My question is how I should set up the relations:
id | thingID | regionId | countyId | cityId | placeId
or
4 tables?
id | thingId | regionId
id | thingId | countyId
id | thingId | cityId
id | thingId | placeId
or is there perhaps another better solution?
I may be overthinking this, but I think there's probably a relationship between "region", "county", "city" and "place" - an item that belongs to a "place" should also belong to the city, county and region.
You can solve this in both the designs you provide - but you need a fair amount of additional logic. In the first solution, you need to make sure that every time you insert a record, you populate the location from "left to right" - a record with only "place" is not valid.
In the second solution, you need to populate all relevant rows - an item in Chelsea must also have records for London, Middlesex and South East England.
There's another way...
Table: location
ID Name Parent
------------------------
1 South East England null
2 Middlesex 1
3 London 2
4 Chelsea 3
5 Kent 1
6 Canterbury 5
Table: item
Id name
-----------------
1 Posh Boy
2 Cricket ground
3 Rain
Table: item_location
ItemID LocationID
--------------------
1 4 //Posh boy in Chelsea
2 2 // Cricket ground in Middlesex
3 1 // Rain in the South East of England.
The second option is clearly better. It's a many-to-many relationship for each of these categories, and that's what the second option describes.
The first option would result in some very odd data. If you had a ThingId that was associated to all of the different types once, you would have one row that had all the columns filled in. Then if your ThingId needed to be tied to an additional city, you would have another row that had only the cityId filled in, with the other columns remaining null.
A table design that results in a lot of null values is usually (not always) a sign that your model is flawed.

Database Designing and Normalization issue

I have a huge access mdb file which contains a single table with 20-30 columns and over 50000 rows and
i have some thing like this
columns:
id desc name phone email fax ab bc zxy sd country state zip .....
1 a ab 12 fff 12 w 2 3 2 d sd 233
2 d ab 12 fff 12 s 2 3 1 d sd 233
here I have some column values related to addresses repeating is there a way to normalize the above table so that we can remove duplicates or repeating data.
Thanks in advance.
Here's a quick answer. You just need to move your address fields to a new table (remove dups) and add a FK back to your primary table.
Table 1 (People or whatever)
id desc name phone email fax ab bc zxy sd address_id
1 a ab 12 fff 12 w 2 3 2 1
2 d ab 12 fff 12 s 2 3 1 2
3 d ab 12 fff 12 s 2 3 1 2
4 d ab 12 fff 12 s 2 3 1 1
Table 2 (Address)
address_id country state zip .....
1 d sd 233
2 e ac 123
Jim W has a good start, but to normalize even further, make your redundant address elements into separate tables as well.
Create the tables for which address data is repeated (Country, State, etc.) Once you have your data tables, you'll want to add columns such as StateID, CountryID, etc. to the Address table.
You now have options for fixing the existing data. You can be quick and dirty and use Update statements to set all the newly created ID fields to point to the right data table.
UPDATE Addresses SET StateID=1 WHERE STATE='AL'
You can do this fairly quickly as a batch .sql file, but I'd recommend a more programmatic solution that rolls through the Address table and tries to match the current 'State' to an entry in the new States table. If found, the StateID on the Address table is updated with the id from the corresponding row in States.
You can then delete the old State field from the address table, as it is now normalized nice and neatly into a separate States table.
This process can be repeated for all redundant data elements. However, IMO db normalization can be taken too far. For example, if you have a commonly used query that, after normalization, requires 10 joins to accomplish, you may see a performance reduction. This doesn't appear to be the case here, as I think you're on the right track.
From a comment above:
#Lance i wanted something similar to that but here is the problem i have raw data coming in the form of single table and i need to refine and send it to two tables i can add address in table 2 but i m not undertanding how would you insert the address_id in table 1
You can retrieve the newly created ID from the address table using ##IDENTITY, and update the address_ID with this value.

Resources