database design, items and orders tables - sql

I was just after some input on database design. I have two tables, Orders and Items.
The items table is going to be a list of items that can be used on multiple orders, each item has an id
The way i thought to do it at the moment, was in the order to put an array of comma seperated ids for each item in the order.
does that sound like the best way?
also im using linq to entity framework and i dont think id be able to create a relationship between the tables, but i dont think one is needed anyway is there, since the items are not unique to an order
Thanks for any advice

The way I thought to do it at the moment, was in the order to put an array of comma separated ids for each item in the order. Does that sound like the best way?
Absolutely not - It will be MUCH more difficult in SQL to determine which orders contain a particular item, enumerate the items (to get a total, for example), and to add/remove items from an order.
A much better way would be to create an OrderItem table, which has a foreign key back to Order and Item and any other attributes relating to the item in that order - quantity, discount, comments, etc.
As far as EF goes, it will probably create a third entity (OrderItem) that will "link" the two tables. If you don't add any extra properties (which you probably should) then EF will probably create it as a many-to-many relationship between the Order and Item entities.

As far as I have understood from your question (it is not very clear), every Order can have multiple Items and every Item can be used in multiple orders. If this is what you want, you have a many to many relationship, that must be resolved using an intersection entity. This intersection entity has 2 foreign keys, one for item and one for order. Using it, you can identify what items are in a certain order and what orders need a certain item.
As my explanation is very short and very sloppy, I will recommend you the following references:
http://sd271.k12.id.us/lchs/faculty/bkeylon/Oracle/database_design/section5/dd_s05_l03.pdf
Resolve many to many relationship
Also, you proposed design is very bad, as it breaks the first normal form: no attribute can have multiple values. You shoud try to build databases at least in third normal form.

Regarding the database design, you would usually create a third table - ORDER_ITEMS - linking the two tables, containing columns (foreign keys) for order id and item id. You might also want to include a column for quantity.

Related

sql table name, item or items

I name my tables according to what the row describes. So if it describes one comment in one row, I name it "comment".
I have a table with id, created_at, updated_at, name, description, quantity, sample. I am unsure what to name it due to "quantity". I think it can be seen in two ways.
The table describes one specific kind of item. There are x number of this one kind of item. As such the table should be named "item". Similar to fish vs fishes.
The table describes many items in each row due to quantity. As such it should be named "items". The caveat is that there can be 0 or 1 of the item.
I've also entertained the idea that quantity may be describing a subtly different entity and belongs in a separate table.
Ultimately, I think this is a style thing, but I think you should be consistent across your tables rather than trying to come up with a different concept table by table.
Personally I prefer singular because of the inconsistencies of pluralizing words, but a lot of people prefer plural because the table seems to be a collection of things.
In your example, though, I'm not sure why the presence of "quantity" as one of your columns would factor in. A table called "animal" could have a "number_of_legs" column, but I don't think that would change the way you think about the overall table of animals.
Item.
Each row contains a kind of item. A property of the item is the quantity. If each specific item had a separate row, and included a column such as SerialNumber, then Items would be appropriate.
Each row is not exactly describing an item, but an item bundle, right? Either way, don't overthink it.
From your question I would use 'item' because it's gonna be more similar to your other tables.

Site-wide comments with different type of pages and special requirements

I am interested in designing the database (well, I'm only concerned about one table really) for a site with the following requirements:
There is an items page, which lists items. items.xyz?id=t displays the item with ID t. I need the IDs of the items to be consecutive. The first item has ID 1, the second ID 2 and so on. Each item page has comments on that item.
There are other pages, such as objects, where objects.xyz?id=t displays the object with ID t. The IDs here need not necessarily be consecutive (and they can overlap with item IDs, but it's ok if you suggest something that forces them not to overlap). These also have comments.
My question is how to design the Comments table? If I have an EntityID in it that represents the page the comment should be displayed on (be it an item page or an object page), then should I make it so that the ItemID never overlaps the ObjectID by making all ObjectID start from, say, 109 and using a GUID table? (The ItemIDs increase very slowly). Is this acceptable practice?
Right now I'm doing it by having a bunch of nullable boolean fields in each comment: IsItem, IsObjectType1, IsObjectType2, ..., which allows me to know where each comment should be displayed. This isn't so bad since I only have a few objects, but it seems like an ugly hack.
What is the best way to go about this?
I see three solutions (assuming it is impossible or undesired to put Pages and Objects in one table). Either:
Tell the comment which it belongs to by giving it two columns: PageId and ObjectId.
That way you can also give these columns foreign keys to the respective tables and add proper indexes.
Introduce a table 'Entity' that has a unique id, a PageId and an ObjectId. Either columns are optional off course, exactly one of them must be filled, not 0 or both.
This way, you move all the potential garbage of having separate entities to this table, not polluting the Comments table, which should contain just comments. You isolate the mess.
Create a link table between Comments and Items and another table between Comments and Objects. Items and Objects are completely unrelated, and you don't have to pollute the Comments table with a lot of NULL values in multiple columns. When you create a comment, you decide if it links to an Item or an Object by inserting a link in either ItemComments or ObjectComments. Reading comments for an item or object is a matter of two simple joins.
The comments table can then contain only a single EntityId that refers to the Id in the Entity table.
The big advantage to this approach is twofold:
a) You can link other things to the same table too, whichout much hassle.
b) You can add other kinds of Entities and they will automatically support Comments and other things you might add, as mentioned in a).

One-to-one relationship or One-to-many?

Maybe I need more coffee this morning but here goes...
I have a very simple inventory system. Right now I have two tables: Items and Inventory.
Items
Id
Title
YearReleased
Inventory
Id
ItemId(Foreign key to Items)
Quantity
QuantityOnHand
Each item has one inventory and each inventory belongs to one item. The relationship between the two is one-to-one. However, when I diagram this out, the relationship based on my setup thus far is a one-to-many, due to the auto-incrementing id I have for Inventory.
Now, I could make this one-to-one by eliminating the auto incrementing id in the Inventory table, but this makes me feel dirty. I always use internal id's for primary keys.
I see a few options:
1.) Remove the auto incrementing id field in Inventory and live with the dirty feeling.
2.) Keep the tables as-is.
3.) Merge Items and Inventory into one table: ItemsInventory.
4.) Something else?
If your relationship is really one to one, drop the Id from the Inventory table and use ItemId as PK and FK. Also, name both keys ItemId -- helps.
If you're certain that the mapping will always be 1:1, then merge the two tables into one.
However, are you certain that the relationship will allways be 1:1?
Since many ORMs require a single auto-increment PK, I would:
4) Add a unique index to Inventory.ItemId and it should show as a one-to-one relationship.
Would making ItemId have a constraint to be unique be insufficient? That seems to satisfy your requirements.
If what the table structure you have mentioned is going to remain as it is now, then I think you should merge Items and Inventory into one table: ItemsInventory.
For such small tables it doesn't make sense to partition them vertically. That way you would remove an extra join. Select on a single table is always faster then joins.
I would merge the two tables together my main reason is you will have duplicate data as
well as unnecessary data if you stick with two tables. Querying will also be faster! Looking at the two tables I would merge into one for sure.
Items
Id
Title
YearReleased
Inventory
Id
ItemId(Foreign key to Items)
Quantity
QuantityOnHand
You will have two less collumns full of data if you merge to one table ("ID" ItemID" can be dropped). Writing your logic to retrive and send data to the database will also be easier for you.
I would have this table:
**ItemsInventory**
Id
Title
YearReleased
Quantity
QuantityOnHand
However you must be sure it is a one-one otherwise you may have give yourself a lot of work if the bussiness needs change.
Simon
If you really want to make it a simple inventory system, then merge the tables.
Reasons not to merge the tables/it doesn't stay simple.
How many items will NOT have an inventory record? Your example only shows a few inventory fields and maybe that's all it would ever have. But it the fields you track in inventory grow and there is a large part of items not in inventory, you're going to have a lot of null fields.
How often will inventory get updated? If these fields are a result of other transaction tables (purchases and sales) being updated frequently, no reason to constanatly update the items table just because inventory was purchased or sold. In your current system, users are expecting these values to be real time (If not then they know what isn't up to date since they didn't make the changes.).

Use of null values in related tables with foreign key constraints

I have the following tables:
Cateogories
CategoryID (int) Primary Key
CategoryName (varchar)
Items
ItemID (int) Primary Key
CategoryID (int)
ItemName (varchar)
There is a foreign key constraint on Items.CategoryID. There is a chance that when a new item is created that there will be no category assigned.
Is it better to set Items.CategoryID to allow nulls and deal with the nulls in my code OR better to not allow nulls, set the default CategoryID to 1, and create a dummy record in the Categories table called "Uncategorized" and then deal with that dummy category in my code?
The logically correct way would be for the CategoryID column to be NULL when there is no Category for the item.
If you get trapped by any of the gotchas that are associated with using NULL, then that is most likely a sign that the design hasnt taken account of the fact that items cannot have a category. Fix the design. The NULL will ensure you stick to solving the correct problem.
It depends:
If your items really have no category, then I would allow NULLs, as that is what you have: no CategoryId.
If you want to list all categories, you do not want to display the dummy row, so you would have to ignore that.
If you want to display all items and show the categories, you'd better be aware that there are items without category, so you would use a LEFT JOIN in that case.
If possible, change your application to select a category before actually saving your item.
If you want to treat that Uncategorized category just like the other categories (list them with the other categories, count items assigned to it, select it in lists/dropdowns), then it should get it's own category, and Item.CategoryId should be NOT NULL.
Ideally you'd want to force a category choice before allowing an item to be created. If an item will have no category at any point in the future then you'll need to create a category specifically to deal with that. I personally wouldn't call it "Uncategorized" though as this implies that a user can just chase it up later - which they will forget to do with alarming regularity!
Go for logical consistency or you'll end up in a mess. If that means creating a "Miscellaneous" category then do that and make sure that (a) Users know when to use it and (b) It is reported on regularly to make sure items are categorised correctly.
For simple lookup tables of this type it is almost always better to disallow NULLs and have the unknown value in your lookup table.
Why?
Because the ANSI NULL specifications are inconsistent and very complex. Dealing with nulls greatly increases the likelihood of coding defects, and takes a lot more code to write
Because few developers really understand how NULLs work in all scenarios
Because it simplifies your model and queries nicely. You can join things together nicely with inner joins from either direction with very simple sql.
However, a few cautions:
You may want more than one "dummy" value: one for "unknown" and another for "not assigned". Of course, NULL bundles both into a single value, so you're going above & beyond the minimal standard if you do this.
You will end up sometimes having additional non-key attributes that either must be nullable or carry 'n/a' type values for the dummy rows. For heavily denormalized lookup tables (like warehousing dimensions) you'll probably want nulls allows for these columns because 'n/a' doesn't work well for timestamps, amounts, etc.
If you apply this technique to more than just simple lookup tables it will dramatically complicate your design. Don't do that.
SQL NULLs are tricky, so I think you're better off with a sentinel category.
In this case I believe it's really a matter of personal preference. Either way you'll have to deal with the uncategorized items in your code.
I do not believe that either of the alternatives are very good.
If you choose the NULL approach you will have problems with the gotchas involved in working with NULLs. If you choose to not allow nulls, you will need to handle cases where if you delete a category the item would cascade.
IMO the best design is to have three tables.
Categories
ID
Name
Items
ID
Name
Categories2Items
CategoryID
ItemID
This eliminates the need for NULL (and the gotchas involved) as well as allows you to have uncategorized items, and items which belong to several categories. This design is also in Boyce-Codd Normal form which is always a good thing ..
en.wikipedia.org/wiki/BCNF

using NHibernate on a table without a primary key

I am (hopefully) just about to start on my first NHibernate project and have come across a stumbling block. Would appreciate any advice.
I am working on a project where my new code will run side-by-side with legacy code and I cannot change the data model at all. I have come across a situation where one of the main tables has no primary key. It is something like this:
Say there is an order table and a product table, and a line_item table which lists the products in each order (i.e. consits of order_id, product_id, and quantity). In this data model it is quite possible to have 2 line items for the same product in the same order. What happens in the existing code is that whenever the user updates a line item, all line items for that order are deleted and re-inserted. Since even a compound key of all the fields in the line_item table would not necessarily be unique, that is the only possible way to update a line item in this data model.
I am prepared to guarantee that I will never attempt to update or delete an indivdual line item. Can I make my NHibernate code work in the same way as the existing code? If not, does this mean I (a) I cannot use NHibernate at all; (b) I cannot use NHibernate to map the line_item table; or (c) I can still map this table but not its relationships
Thanks in advance for any advice
I think if you map it as a bag collection on the Order (with inverse="false") it would work.
Collection Mapping
Note: Large NHibernate bags mapped
with inverse="false" are inefficient
and should be avoided; NHibernate
can't create, delete or update rows
individually, because there is no key
that may be used to identify an
individual row.
They warn against it but it sounds like what you want.