I'm currently working on an ASP.Net MVC project for a software engineering class. My goal is to create a small online game rental system. I currently have a 3 tables, Movies, Games and Registrants; and I'm using LINQ-to-SQL to define each of these tables as classes for my model. So far I've created models for Movies and Games, what I would like to do when creating the Registrant model is create a relationship between Registrants and Movies and Games. What I've tried so far is to define a foreign key between the ID (the primary key in the Registrant table) and a registrantID field in both the Movies and Games. What I realized is that if I were to remove an instance of a registrant, it will delete the associated movie and/or game from the other tables. What I'm thinking of doing is creating two separate models defining rentedGames and rentedMovies and creating a relationship between those and the Games and Movies table in order to try and model a registrant renting/returning/buying movies or games from the store.
In Summary:
What I have so far:
3 tables: Registrants, Movies and
Games.
LINQ-to-SQL models for my
inventory of movies and games.
What I'm trying to setup:
A model for a registrant renting/returning a movie and/or game, when a game is rented/returned, a flag is placed next to the item in the inventory to indicate its status.
Question:
Will adding separate tables to model
a rented movie/game prevent items
defined in my inventory models from
being deleted?? i.e. when a customer returns a rented movie, the rentedMovie instance is deleted, but not the movie is is referring to in the movie inventory.
Is there such a thing as a related
table having a status flag set on the
related entry, as opposed to the
entry being deleted, whenever the
associated entry in the other table
is modified?? i.e. when a customer returns a rented movie, the rentedMovie instance sets a flag in the movie it refers to that it's available for rent, the rentedMovie instance is then deleted.
I'd go about this a bit differently. First, is there a real reason to treat a Movie and a Game as separate entities? Why not have a RentableItem that can be either a movie, a game, a game machine, a Blue-Ray player, or whatever? You'd key it by an item_id field, and it would have the expected metadata (title, type, genre, rental_class, and so on).
Then you need to model the fact that a Registrant rents one or more RentableItems. This can be done with a Rental table, whose rows each connect one rented RentableItem with a particular Registrant (that is, the Rental is keyed by a rental_id and it has a foreign key to RentableItem.item_id and a foreign key to Registrant.registrant_id. The Rental would also have the due date, a "returned" flag, the price of the rental, etc.
Then you know a RentableItem is not in the store if there is a Rental record whose item_id is the same as the RentableItem's and whose "returned" flag is false. You never have to modify the RentableItem table itself, just the Rental table.
You're right to create separate tables for rentedGames and rentedMovies, since this model now allows for more than one movie or game of the same type being rented at the same time, which is surely more realistic than having only one instance of a particular movie or game.
This will prevent the deletion of the parent record, when the link record (rentedMovie, say) is deleted. But this deletion of the parent movie should not be happening anyway if you've set up your relationship to not 'cascade delete', and you allowed the registrantID field in the original Movies or Games tables to be nullable.
To answer your second question (which I realise assumes only one movie/game for any particlar title): the way this is normally done, if you're using link tables, which is what you want to do, is simply to delete the rentedMovie/Game record. The absence of a link record for any Movie or Game is all your code needs to determine in order to know that that movie or game is now rentable (again).
I know you're doing this for a class / practice, so this may not be relevant, but consider that having the rental history for things is often very useful. Because of this, you may not want to delete the rented records, but instead just mark the item as returned.
Consider:
TABLE RentalTransaction:
RentalTransactionID integer PK NOT NULL
CustomerID integer FK NOT NULL
RentedOn datetime NOT NULL
DueDate datetime NOT NULL
<..any other fields you may need..>
TABLE RentalItems:
RentedID integer PK NOT NULL
RentalTransactionID integer FK NOT NULL
RentedItemID integer FK NOT NULL
RentedQty integer NOT NULL
RentalRetuned datetime NULL
You can see if any individual item is out or not by if it's RentalReturned field is null or not. If it is nonull, then you know the item is back, and now you can aggregate rental data to see how often it goes out, what the average length of rental is, etc, etc. You would have to build in some checks to make sure you weren't renting more copies of an item than you actually have and other such things, but I think this is overall a more flexible start to a schema. It may also be overly complicated for what you're doing, but I wanted to at least bring the idea up.
Do you really want to delete the rentedMovie instance? How will you report on how many movies a person has rented etc?
I'd suggest rethinking your model slightly. You need somewhere to store people data, somewhere to store item data and somewhere to store people/item data as a first step.
Ignore the difference between movies and games for now - that becomes a process of normalisation once you've defined your underlying structure.
As a simple starting point you should have:
Persons 1..1 ---- 1..* Hires 0..* ---- 1..1 Items
where the Hires table is a linking table between the two others with a combined key made up of personID, ItemID and a time-stamp of some description (to allow re-renting of the same movie).
You can then look at having a separate table for item types etc.
First thing to consider is that a movie is actually two entities, title and media. Title is "Lord of the Rings", while media is a DVD you take home. One title can have many media (copies), while one media has one title. Rental table has a row for each media-rental, this table gets a new row each time a bar code is scanned on rental, while DateReturned is populated upon return. Status field in the Media table tracks the in/out status for each disc/game.
If you feel that you need to track which movies were rented together to a customer, you may find that by DateRented (datetime) or add a ReceiptNumber or ShoppingBasketID to the Rental table.
Related
This question is about design decision, hence might be a bit opinionated:
Imagine you are designing database for a car dealer where they ONLY auction cars. Some cars are for display only, and some cars are to be sold in auction.
I have a Car entity with 10 attributes: ID, Model, Mode, YearMade, IsDisplayOnly....
Now, I want to add selling price and selling notes to those cars that are for sale (i.e. IsDisplayOnly = false)
I image that there are two ways this can be done:
Add Price and PriceNotes columns into the Car table, knowing that they are always null for IsDisplayOnly = true cars, and those that haven't been sold at auction yet.
Add a new table SaleInfo with 3 columns: CarID, Price, PriceNotes where CarID is the PK and also FK pointing to the ID column in the Car table.
Which option would align most with the best schema design practice? Why?
You should have one car for cars and the attributes of cars. You should have a separate table for the cars for auction.
Why? These are different entities. Your problem definition suggests an auction table. That auction table should have a foreign key references to the cars that are available for auction. A separate table ensures that that foreign key reference is valid.
There are some other reasons that are not apparent in your simplified example. Notes and prices might change over time, so they should be going into a history table. Display cars have other attributes, like the period of time when they are on display and how they are ultimately disposed of. This suggests that they too have particular attributes.
My advice would be to use three tables:
-The first to store all the makes and models of the cars. As well as their costs(eg Honda something or other selling for X amount of money)
-The second to store the details of the individual vehicles, containing a foreign key to the primary key of one of the Make/Model stored in the first table, as well as individual details such as the color, VIN no. etc. As well as whether they can be sold or not.
-The third table would contain the details of each individual purchases, linked to the table containing each individual vehicle, this would be linked to the table containing the details of each individual vehicle, with each purchase connected to a single instance. On the table of vehicles.
The advantages for this layout is that you are actually going to end up using less storage space in the long run, as instead of having the same three fields (The make, model and year) repeating for every vehicle, you will only have a single field to represent that data instead of multiple redundant fields. Another advantage will be searching, as if you are searching for details of individual vehicles of the same brand/type, you will be able to search using only one field, the key linked to the table containing the make and model. This would drastically decrease search times and improve the effectiveness of the system overall.
I am working on an app that tracks which tv shows you are watching and which episodes from that show you have watched.
Currently I have can track which users are watching which shows, this is relatively simple and it is structured like so:
table structure
So I have a User table which has a primary key id that identifies that user and some other info about that user which is not relevant.
Following this I have another table TV_SHOWS which stores a user_id as a foreign key some information about the show and crucially a field called user_watching that gives a boolean value as to whether the user is watching that show.
How it works is this, when the user clicks a button to add the show a row is inserted into the TV_SHOWS table with the all the information and user_watching = true at some point the user may wish to stop watching so they can click another button that will simply update the user_watching = false.
Now I wish to expand on this idea so that users can track which seasons and episodes of a tv show they have watched, a tv show is comprised many seasons and each season is comprised of many episodes in most cases.
I would like some help with how best to structure this database schema.
I initially thought that I could just expand along the same lines I had previously for instance:
I simply add two id's for the season and episode, in that way I can tell if a user has watched a season by seeing if they have watched all the episodes in that season and if they have watched a show by checking if they have watched all the seasons in the show, but I don't think this seems like good practice.
I could try and do a one table for shows, another for seasons and a final for episodes but I am not sure where I would "track" is a user had watched one of those, would it have to be in that specific table or would I need another table to track it?
Short answer: I think the latter design is a better option from a scalable design perspective.
Longer Answer:
The latter option with show <--> season <--> episodes separated into individual tables is closer to a textbook design. Third Normal Form, I think. The idea being that you want to reduce redundant data as much as possible, as to minimize storage space. Minimizing redundant data is a general best practice. By separating the three you are able to keep attributes that are specific to the each topic from being replicated.
For example, let's assume you track TV Show attributes like title, description or an average ranking. If you maintain a single table with show/season/episode, then the TV Show attributes should technically be replicated (i.e. redundant) for every season and every episode in order to maintain a table constraints. Conversely, separating out the TV show attributes avoids the redundant attribute data. It also helps to allow the attributes set to grow/change overtime.
This design practice though comes with a computational cost as you need to JOIN the structures together depending upon the use cases. For example, if you always need to know show title, season X, and episode title (attributes from each of the tables), then you'll need to develop the necessary join logic to obtain those attributes. This cost can be mitigated using a View, which opens another set of decisions.
To your comment on the need for two keys. Following the three table design, you'll likely want a primary key of some sort on each table. If you structure the episode table with reference key to the season (and maybe the show), then you should only need to use the episode key as you can de-reference the season and TV show from the episode using join logic. In effect, the episode should be enough to figure out the season and TV show from the linking.
-- User USR exists.
--
user {USR}
PK {USR}
-- TV show SHW exists.
--
show {SHW}
PK {SHW}
-- Season number SEA# of show SHW exists.
--
season {SHW, SEA#}
PK {SHW, SEA#}
FK {SHW} REFERENCES show {SHW}
-- Episode number EPI# of season number SEA#
-- of show SHW, in duration of DUR_E minutes, exists.
--
episode {SHW, SEA#, EPI#, DUR_E}
PK {SHW, SEA#, EPI#}
FK {SHW, SEA#} REFERENCES season {SHW, SEA#}
-- User USR watched DUR_W minutes of episode number EPI#
-- of season number SEA# of show SHW.
--
user_show {USR, SHW, SEA#, EPI#, DUR_W}
PK {USR, SHW, SEA#, EPI#}
FK1 {SHW, SEA#, EPI#} REFERENCES
episode {SHW, SEA#, EPI#}
FK2 {USR} REFERENCES user {USR}
Note:
All attributes (columns) NOT NULL
PK = Primary Key
FK = Foreign Key
Using suffix # to save on screen space.
OK for SQL Server and Oracle, for others use _NO.
For example, rename EPI# to EPI_NO.
I am just started to learn about relational database. When I studied the database of online shopping websites, I found that many examples create a category table and added ID field to the category name. I don't know why they need to create a category table and use category ID as a foreign key to relate products table. What will happen if I remove the category table and add the category name directly to the products table?
What I think is a lot of cases that you want a website menu showing your categories. This menu allows people to view your categories (Men Clothing, Women Clothing, Kids, Accessories) and once they click it they can see the products relevant to them.
If you put the category name to the product, it is very hard for you to update your menu content as you need to loop, group the category in the product table. Also, it is harder to update the category name in product table as a category name could be in lots of product records,
Whereas if you have a category table, you just need to maintain the category table (view what you have in the category table and update DB record if you want your menu change).
In long term maintenance, category table is desired.
In a case I have come over that I would like an empty category which just to show in the website menu (a menu item which contains no product) which is not possible if I do not have a category table.
By inserting just the category name you may complete your POC but you need to understand what is Normalization and why it is needed.
First normal form (1NF) : An entity type is in 1NF when it contains no repeating groups of data.
Second normal form (2NF) : An entity type is in 2NF when it is in 1NF and when all of its non-key attributes are fully dependent on its primary key.
Third normal form (3NF) : An entity type is in 3NF when it is in 2NF and when all of its attributes are directly dependent on the primary key.
Source
What will happen if I remove the category table and add the category name directly to the products table?
Suppose you store the category with each product, and one day your boss tells you that you misspelled a category name. Which one?
"Theater" he says. Or did he say "theatre?" Which is correct? You check and find about "theater" and "theatre" are used close to evenly among the products that have either one.
So which spelling did your boss mean is the mistake, and which one is correct?
If you store the correct spelling in one place, in its own categories table, then you can be sure. You can correct it, and all the products that reference it will implicitly get the correction.
That's an argument for normalization, but keep in mind using an integer id is only a convention. It has nothing to do with normalization. You can use a string as a primary key of a table, and therefore you can use a string as a foreign key in a table that references it.
It's okay to use a non-integer for key columns. As long as there is one instance that stores the canonical value, it satisfies the goal of normalization -- that is to reduce data anomalies.
I need help getting this table "Route Sheet" to 3rd Normal form. I was doing it in class but my teacher keeps telling me that some things are wrong and I want to see how you really need to normalize this in the E-R Model. Any help with the just the final process would be appreciated, I really need to learn this before my exam. (I need to use foreign keys and primary keys too)
Note: There can be more vehicles, more than one type of vehicles and more drivers.
Here is a pic: http://i60.tinypic.com/so0chy.png
Here is what i have done so far of the E-R model in powerdesigner: http://i62.tinypic.com/2zoyse0.png
The arrow means many (if no arrow it means one), so i would be one to many.
Let's look at what you have. Think about which pieces of data are in a one to many relationship or a many to many relationship. Those will indicate the need for more tables. First you have vehicles; that would be one table. You have vehicle types; that would be a lookup table that is a parent to the vehicle table as there will be many vehicles for each type.
Now you have drivers. Depending on the information you have about drivers, you may need separate tables for things like addresses or phone numbers if a driver can have more than one.
Then you have trip data which would include the pk for both the vehicle and driver (Assumption one vehicle, one driver per trip; if that is not true, then another table will be needed) as well as the start and stop times.
Then you have the details about the trips which go into the trip detail table but some of those things are going to be lookups from other tables.
Such as customers (there is another set of tables there as customers are likely to have more than one possible address, so customers and customer addresses).
Also you probably need a product table that defines the products you have available for delivery. In the detail table, though, you need the product_id and then add the quantity and price if you need those. This is because those are historical values and you can't use the price in the product table as that changes over time, but you need a record of what it actually was at that point in time.
It also appeared there were some other values that would make sense as lookup tables that are parents of the trip detail table.
Im trying to figure out what the appropriate way to setup a database would be given this scenario:
I am creating a Movie / TV database. A movie may have multiple genres and a tv show may have multiple genres.
Essentially what I am wondering is if you have a Movie table, TV table... should you:
have a MovieHasGenre table consisting of a foreign key to the Movie table and a regular field for the genre value
or
have a MovieHasGenre table AND a Genre table where the MovieHasGenre has two foreign keys, one pointing to the Movie in the Movie table the other pointing to the Genre in the Genre table
Im really not sure if this is something standardized or just involves preference. Do we have concerns with speed as it seems removing the Genre table is one less join.
Go with option 2.
It's useful to store each Genre once, and make reference to it via the MoveHasGenre table. That way, if you have other attribute columns for a genre, you don't have to store those attribute redundantly on each row where a given genre is mentioned.\
Re your comment:
Another case is if you want to change the spelling of a genre, and have it apply to all rows that reference it, with no chance you forget some.
Option 2 is how you will normalize your data.
The problems with option 1 is data redundancy. Opposed to using a few bytes of data to store and INT you are using a potentially large value to store the name of the genre. The other problem like Bill said is that you have the potential for data inconsistency since you will have to update multiple fields if a genre changes instead of just one column.
However, what you have in option 1 is a denormalized version of option 2 which would have performance benefits over option 2 but I would imagine, given the seemingly small size of this database, that there won't be a significant performance change.