how to allow orphan recordsets in many-to-many bridge tables - many-to-many

I have a problem that I can't seem to solve.
I have table: Software
and table: PC
they both have many to many relationship between each other, that is, one PC can have many Software and One Software can have many PC's
the link table is: soft-pc
The table soft-pc also has licensing information like, product keys.
now the problem is, when a software is deleted from a PC the record is deleted from the soft-pc table. Now I want to be able to un-associate software from PC and still have them in soft-pc table.
Is that possible?

Now I want to be able to un-associate software from PC and still have them in soft-pc table.
This is the core of the problem. At the moment, the relation predicate for the soft-pc table - that is, what it means for there to be a particular record in this table - is that the software in question is on the PC in question. If you now want to say that it's possible for there to be a record in this table when there isn't that software on that PC, you are going to have to decide what the new relation predicate is. Which is to say:
What does it mean for there to be a record in the soft-pc table?

You will need to remove cascading deletes from the relationship, after that, two possibilities occur to me:
Add a deleted date to soft PC
Move the PC ID to another column - this will only work if the unique key is not PCID + Soft ID.
I would be inclined to go with #1.
EDIT re additional post
If you wish, you can have a junction table with all possible PC-Soft combinations and a code to indicate whether or not the software is installed, uninstalled, never-to be-installed etc, and a date at which the status occurred. There is a lot to be said for this approach.

Related

Relationship database design - object specific many to many, do I solve with self join table or new table

Being new to relational database design, I am trying to clarify one piece of information to properly design this database. Although I am using Filemaker as the platform, I believe this is a universal question.
Using the logic of ideally having all one to many relationships, and using separate tables or join tables to solve these.
I have a database with multiple products, made by multiple brands, in multiple product categories. I also want this to be as scale-able as possible when it comes to reporting, being able to slice and dice the data in as many ways as possible since the needs of the users are constantly changing.
So when I ask the question "Does each Brand have multiple products" I get a yes, and "Does each product have multiple brands" the answer is no. So this is a one to many relationship, but it also seems that a self-join table might give me everything that I need.
This methodology also seems to go down a rabbit hole for other "product related" information such as product category, each product is tied to one product category, but only one product category is related to a product.
So I see 2 possibilities, make three tables and join them with primary and foreign keys, one for Brand, one for Product Category, and one for Products.
Or the second possibility is to create one table that has the brand and product category and product info all in one table (since they are all product related) and simply do self-joins and other query based tables to give me the future reporting requirements that will be changing over time.
I am looking for input from experiences that might point me in the right direction.
Thanks in advance!
Could you ever want to store additional information about a brand (company URL, phone number, etc.) or about a product category (description, etc.)?
If the answer is yes, you definitely want to use three tables. If you don't, you'll be repeating all that information for every single item that belongs to the same brand or same category.
If the answer is no, there is still an advantage to using three tables - it will prevent typos or other spelling inconsistencies from getting into your database. For example, it would prevent you from writing a brand as "Coca Cola" for some items and as "Coca-Cola" for other items. These inconsistencies get harder and harder to find and correct as your database grows. By having each brand only listed once in it's own table, it will always be written the same way.
The disadvantage of multiple tables is the SQL for your queries is more complicated. There's definitely a tradeoff, but when in doubt, normalize into multiple tables. You'll learn when it's better to de-normalize with more experience.
I am not sure where do you see a room for a self-join here. It seems to me you are saying: I have a table of products; each product has one brand and one (?) category. If that's the case then you need either three tables:
Brands -< Products >- Categories
or - in Filemaker only - you can replace either or both the Brands and the Categories tables with a value list (assuming you won't be renaming brands/categories and at the expense of some reporting capabilities). So really it depends on what type of information you want to get out in the end.
If you truly want your solution to be scalable you need to parse and partition your data now. Otherwise you will be faced with the re-structuring of the solution down the road when the solution grows in size. You will also be faced with parsing and relocating the data to new tables. Since you've also included the SQL and MySQL tags if you plan on connecting Filemaker to an external data source then you will definitely need to up your game structurally.
Building everything in one table is essentially using Filemaker to do Excel work and it won't cut it if you are connecting to SQL, MySQL, etc.
Self join tables are a great tool. However, they should really only be used for calculating small data points and should not be used as pivot points or foundations for your reporting features. It can grow out of control as time goes on and you need to keep your backend clean.
Use summary and sub-summary reporting features to slice product based data.
For retail and general product management solutions, whether it's Filemaker/SQL/or whatever the "Brand" or "Vendor" is it's own table. Then you would have a "Products" table (the match key being the "Brand ID").
The "Product Category" field should be a field in the "Products" table. You can manage the category values by building a standard value list or building a value list based on a "Product Category" table. The second scenario is better for long term administration.

Need optimized sql advice

So i have this database full of tables like suppliers, clients, stores, store_users, services(of each store), repairs, etc etc (a database of a IT brand that repairs computers at each store).
In the "repairs" table i have fields regarding the client, hardware, breakdown, condition and state of the repair("started", "waiting for client answer", "delivered" and others).
Everytime there are changes in the repair, for example: user1 received the repair order and inserted the repair into the system. user2 tested harddisk, RAM, etc for problems, found major disk problem so it needs to be replaced.
This information will change many fields in the "repair" but i need something like another table "interventions" to know what changed and who did what in each time there was an edit to the repair.
The only idea i had was to make a new table "interventions" with all the fields from the "repairs" table and every time someone edited the repair it would copy it to the intervention with a id_repair and a id_user linked.
PS: Users are the store's employees
It sounds like your "repair" table needs to be renamed to "interventions" and what you currently see as the "repair" table changed to a view which shows the most recent intervention.

MySQL: how to do row-level security (like Oracle's Virtual Private Database)?

Say that I have vendors selling various products. So, at a basic level, I will have the following tables: vendor, product, vendor_product.
If vendor-1 adds Widget 1 to the product table, I want only vendor-1 to see that information (because that information is "owned" by vendor-1). Same goes for vendor-2. Say vendor-2 adds Widget 2, only vendor-2 should see that information.
If vendor-1 tries to add Widget 2, which was already entered by vendor-2, a duplicate entry for Widget 2 should not be made in the product table. This means that, somehow, I need to know that vendor-2 now also "owns" Widget 2.
A problem with having multiple "owners" of a piece of information is how to deal owners editing/deleting the data. Perhaps vendor-1 no longer wants Widget 2 to be available to him/her, but that doesn't necessarily apply for vendor-2.
Finally, I want the ability to flag(?) certain records as "yes, I have reviewed this data and it is correct" such that it then becomes available to all the vendors. Say I flag Widget 1 as good data, that product should now be seen by all vendors.
It seems that the solution is row level security. The problem is that I'm not too familiar with its concepts or how to implement it in MySQL. Any help is highly appreciated. Thanks.
NOTE: this problem is somewhat discussed here: Database Design: use composite key as FK, flag data for sharing?. When I asked the question, I wasn't sure how to phrase the question very well. Hopefully, I explained my problem better this time.
Mysql doesn't natively support row level security on tables. However, you can sort of implement it with views. So, just create a view on your table that exposes only the rows you want a given client to see. Then, only provide that client access to those views, and not the underlying tables.
See http://www.sqlmaestro.com/resources/all/row_level_security_mysql/
You already suggested a vendor, product and vendor_product mapping table. You want vendors to share the same product if they both want to use it, but you don't want duplicate products. Right?
If so, then define a unique index/constraint on the natural key that identifies a product (product name?).
If a vendor adds a product, and it doesn't exist, insert it into the product table, and map it to that vendor via the vendor_product table.
If the product already exists, but is mapped to another vendor, do not insert anything into the product table, and add another mapping row mapping the new vendor to the existing product (so that now the product is mapped to two vendors).
Finally, when a vendor removes a product, instead of actually removing it, just delete the vendor_product reference mapping the two. Finally, if no other vendors are still referencing a product, you can remove the product. Alternatively, you could run a script periodically that deletes all products that no longer have vendors referencing them.
Finally, have a flag on the product table that says that you've reviewed the product, and then use something like this to query for products viewable by a given vendor (we'll say vendor id 7):
select product.*
from product
left join vendor_map
on vendor_map.product_id = product.product_id
where vendor_map.vendor_id = 7
or product.reviewed = 1;
Finally, if a product is owned by multiple vendors, then you can either disallow edits or perhaps "split" the single product into a new unique product when one of the owning vendors tries to edit it, and allow them to edit their own copy of the product. They would likely need to modify the product name though, unless you come up with some other natural key to base your unique constraint on.
This sounds to me that you want to normalize your data. What you have is a 1 (product) to many (vendors) relationship. That the relationship is 1:1 for most cases and only 1:n for some doesn't really matter I would say - in general terms it's still 1:n and therefor you should design your database this way. The basic layout would probably be this:
Vendor Table
VendorId VendorName OtherVendorRelatedInformation
WidgetTable
WidgetId WidgetName WidgetFlag CreatorVendor OtherWidgetInformation
WidgetOwnerships
VendorId WidgetId OwnershipStatus OtherInformation
Update: The question of who is allowed to do what is a business problem so you need to have all the rules laid out. In the above structure you can flag which vendor created the widget. And in the ownership you can flag what the status of the ownership is, for example
CreatorFullOwnership
SharedOwnership
...
You would have to make up the flags based on your business rules and then design the business logic and data access part accordingly.

Access 2010: multiple "problem inserts" for one user

I know the title looks a little faque, but my technical english is not as good as would it to be.
My question. I'm designing a kind of work order form with access database. The pretty standard database I can manage, but my problems starts when I want multiple entries for one customer.
For example:
Customer Chris with Id 1 has a problem, he has a BSOD which is fixed. Customer Chris has a new problem some weeks later with his videocard, which will be fixed later ofcourse (;-))
The info above needs to be stored in the access database. Do I need a second table? I really don't have a idea.
You need at least two tables, one for customers and one for problems. The problem table should include such information as customer id, date fixed and fix applied. You may also want to include the engineer, in which case you will also need an employees table, and so it grows.
You may wish to read http://r937.com/relational.html

Inventory Architecture in Database

This is not a question related to a specific language, rather on the correct methodology of architectural of handling inventory.
Consider the following structure for storing software:
platforms (platformID*, platformName)
titles (titleID*, titleName)
And the following is a joiner table for unique products
products (platformID*, titleID*, releaseDate, notes)
And the following is a table I would like to keep track of my inventory
inventory (platformID*, titleID*, quantityAvailable)
In examples I have seen, others have created a table where each unique copy of a software is stored in a separate line as such:
software(softwareID*, softwareTitle)
inventory(inventoryID*, softwareID*)
I would like to know which approach is preferable? Should I create an inventoryID and thus a row for each unique software copy:
inventory(inventoryID*, platformID*(fk), titleID*(fk))
Or use a table that stores quantity instead, as such:
inventory(platformID*(fk), titleID*(fk), quantityAvailable)
The advantage of having a unique row for each piece of inventory is that later if you want to keep track of things like inventory that's on layover, inventory that's on preorder, inventory that's been sold but could still be returned, etc.
I don't see any real disadvantage to this approach except that it's probably more work which might not pay off if these things aren't really needed.
I also would start with quantityAvailable instead of lines for all the items. But I would still opt for an inventoryId, since cases could occur, where you have to dissect the entries with the same platform/title combination -- with an inventoryId you are more enhanceable in the future.
I would also recommend to add a further column: versionNo --- the version number of a software product. Sometimes you might have differing versions of the same product. When you have this, it is not a good idea to drop the information into the title (for example you want to search for all "Microsoft Office" products regardless of version ...).
Should I create an inventoryID and
thus a row for each unique software
copy?
There is no reason to do this, unless you want to store some information on each unique software copy, such as the date each copy was purchased. This is rarely pracitical in the inventory of software.
Or use a table that stores quantity
instead?
You can also consider adding a quantityAvailable column in your products table, unless you think that eventually you'd want to have many inventories for each title, in order to be able to allocate a quantity of stock that is under special offer, that is soon going to expire, etc.