SQL Schema Entity Design Question - sql

I'm attempting to design a schema for a consignment store's POS system. I have a master item's table and multiple entities that reference it as a foreign key and contain different attributes. The items table contains all of the information that is common to all items, regardless of its type. The entities that reference any given item offer a specific attribute for that given item type. For example, a "split" item needs an asking price, while a store item needs a cost price.
While this design technically works and enforces only one item in the items table, I'd like to be able to maintain that any given item is only referenced by ONE of these entities. The concern is that I don't want a "split" item to also me considered a "store" item accidently. Is there any way to enforce this through schema design?
The ERD is here: http://randywestergren.com/pos-erd.pdf
The tables in question are phppos_items, phppos_items_entity_split, phppos_items_entity_store, etc.
Thanks in advance!

It seems like you're determining whether or not a item is a "split" or a "store" type by which related row exists. Instead, how about adding a type field to the items table? It won't prevent the other related row from actually existing, but it will let you know definitively that it's an error.

Create a secondary table:
typed_items (poorly named)
{
PK: item_key - this points to the item
PK: int item_type_id - this type code specified which 'type' of item, ie: store, split
// optional, depending on your key design:
// 1...n FK:
// split_item_id,
// store_item_id,
// etc.., if you reference the items PK in the sub-item-type-detail tables, this
// isnt nessicary. if you are using a synthetic key on the sub-item-type-detail
// tables and no key relationship exists you can use this table as a linking table,
// otherwise its not nessicary
}
Since type items key and the type descriminator id are part of a primary key, you know that your model will not allow an item to belong to 2 different sub-item-type-detail tables.
If you want (paranoid) integrity you can now add a constraint on these type-detail tables that ensures the item's key paired with the constant type descriminator value for that type exists in this table.

Related

How to merge two tables into one DB schema

I'm new to database logic. I have Owners and Borrowers tables for a rental system. Both of them share similar fields like "email, username, password, etc." and also they differ from each other. My question is: How can I merge these similar fields into one table, because I'm pretty sure that my implementation is wrong. Another problem is that I can't properly determine relationship between Items and Item_statuses
When you design your tables, you don't organize them according to the similarities among the titles of the columns, but according to the relations between them.
Your design is working, you may just remove the 'item_statuses' table and create a 'status' column in the 'items' table.
But, let's do some brainstorming to improve the design and consider more of the business logic. We should ask some questions like:
How frequent will the owner be a borrower?
Should I keep track of all the statuses of the item?
If it is frequent for a person to be a borrower and an owner, we will end with duplicated records in our database, so we will make only one table called 'users' with the required fields, and refer the foreign keys in the 'items' table for the users.
If you should keep track of all the statuses of the item, create a separate table called 'items_log' with fields like 'Date' and with a foreign key that references to the item in the items table.
I would also keep track of all the borrowers of the item, so, I can make a 'item_borrowers' table with 'borrower' that references to the user, and 'item' that references to the item with fields like 'Date'.
Also keep in mind that you should store hashed password in the database not plain-text.

Why need to add ID field to products categories of of online shopping database?

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.

How do I limit the items in a "List Box" column based on another column's input in a table in MS Access?

I tried setting up a relationship although I don't know if this is how I'm meant to do it:
Category column settings:
Description column settings:
Linked to the table that contains different type of furniture, "Furniture":
Furniture design:
So what I want to do, is make it so that when you choose a furniture category, you can only choose from furniture descriptions of that category:
I do not think this can be done using only tables — you'll have to create a form that will limit the selection in the descriptions listbox based on the category.
Also, there are a number of problems with your data structure:
I imagine multiple Furnitures can have the same CATEGORY. This means that CATEGORY cannot be the primary key -- a uniquely identifying piece of data -- for Furniture. I would suggest adding a Long number column called FurnitureID. If you make this an Autonumber column, every new record will get a new number by default; otherwise you'll have to insert the number by hand.
Once you have such a column, you should have a corresponding column — AKA the foreign key column — in Stock of the same type (or Long if the FurnitureID is an Autonumber). These two columns should be related in the Relationships window. The relationship means that every1 Stock record must have a related Furniture record with the same data in both records.
Once you've done that, there is no need to repeat the CATEGORY and DESCRIPTION fields between the Stock and Furniture tables. This means no duplicate data, and no potential conflicts.
1. Depending on how the column is defined, it might be possible to have no data in the foreign key column in the Stock record; but this is relatively uncommon

Many-to-Many but sourced from multiple tables

I am supposed to be shipping out a box with variable contents and tracking this in a database. All of my items (the contents of a box) are different types and require different tables to track their respective pieces of information, although each item type has the same length serial number (i.e. PK are the same datatype). And I have a Boxes table.
So each item has a table (~7 tables) plus the box table. I want to create a BoxContents table. I tried to make a many-to-many relationship intermediate table with two columns: one for BoxID and one for ItemBarcode, where BoxID is a FK to the PK on the Boxes table and the ItemBarcode is a FK to each of the PKs on the Items tables (i.e. I tried to link multiple tables to the same column). Unsurprisingly this didn't work. I tried to insert an item and the FK constraint was violated on all but one of the ItemBarcode relationships.
How can I construct my relationships to link several types of items to one box in one table? Is this a logical approach? Do you need more information?
You need a category hierarchy (aka. class hierarchy, subtype hierarchy, inheritance hierarchy...):
There are 3 main strategies for implementing a category hierarchy. If you choose "all classes in one table" or "class per table", then no matter how many kinds of items you have, you only need one "link" table to implement the many-to-many relationship.
My first choice, if the ItemBarcode values are truly unique, would be to:
EDIT: Added description of required triggers.
Add triggers to enforce the barcode uniqueness.
(An insert/update trigger on each item table needs to verify that all (newly) assigned barcodes do not appear in other item tables.)
Use a single BoxId/ItemBarcode table without a FK relation on the barcode side, but with triggers to ensure it remains valid.
(An insert/update trigger on the association table needs to verify that the barcodes exist in the item tables. A delete trigger on each item table needs to prevent, or cascade, deletion of items that are in the association table. An update trigger on the item tables needs to update and changed barcodes in the association table. This last may be integrated into the insert/update trigger in the prior bullet.)
Consider using a view of all items to access common data by ItemBarcode.
My second choice would be n BoxId/ItemBarcode tables for the n item types. Straightforward, but a bit busy. It makes adding a new item type messier than it needs to be.
I would not use a BoxId/ItemTypeId/ItemBarcode table. It denormalizes the data by associating the ItemTypeId and ItemBarcode again, it doesn't allow the use of a FK on the barcode side, and it still requires triggers to ensure integrity.
Don't be afraid of triggers. There are some problems that they can address quite effectively.
Relational databases are not good with this kind of problem. Your basic design is correct - an association table for FKs between the tables.
Your choices are:
Have multiple columns in your association table - one for for each item table
Merge the item data into one item table
I would go option 2.

Recommended structure for table that has FK for 3 other tables

I have a table that will contain information for 3 other tables. The design I have is that this table will have a column that will tell the objects's ID and another column will tell the objects's type (and thus the table that that row refers to).
Two questions:
a) Is that the best design or is there something else more widely accepted?
b) What is the recommend procedure to assure that IDs are valid for the given objects's type?
If I understood your question correctly, each row in your table links to exactly one of the three other tables.
Your approach (type field + one foreign key field) is a valid design, and it's useful if you want to create a general-purpose table that contains meta-information about your data (e.g. a list of records that should be retransmitted for replication).
Another approach, which might be more suitable for real application-level data, would be to have three columns, each being a foreign key to one of the three tables, and to add a constraint that requires exactly two of those fields to be null. The has the following advantages:
The three FKs do not need to have the same data type.
The JOIN syntax becomes more natural (not involving the type field).
You can add referential integrity constraints on those FK columns.
You don't need to ensure correctness of the type field -- in fact, you don't need the type field at all. The type is determined implicitly by the one FK column which is not null.
a) I'm supposing you have a relationship one to many between objects and object types. In a normal design you'd have a reference from the objecttype column in the objects table to the primary key of the object types table
b) I would enforce referential integrity in the relationship properties (this depends on the dbms you are using). It's also up to you to use cascading on updates and deletes. This way, an update or a delete of the primary key on object types table would be reflected on the objects one, updating its foreign key column (object type column) or deleting the registers that have that object type.
The basics of DB schema design are easy, but more complicated situations can be really complicated to figure out what's best. There is a lot of personal subjectivity that can come into play here, and even performance can be a factor in denormalizing a design.
Disclaimer aside, my personal recommendation is to never use a column to store more than one kind of FK, i.e. a column for FKs should store FKs that point only to a single table. If you don't do this, you have to map the cascade of that column's data into multiple sub-select queries inside your code, and it can begin to get more messy than you expected. Your given "Problem No. 2, ensuring validity between type and FK" is just the beginning of a whole world of pain that will cascade throughout your source code.
Assuming you change the design to use one field per FK reference, I would also check whether each FK field in your main "information-holding table" will be fully valid for each record. If not, I would move out the FK columns that will only be applicable some of the time to a separate table.