Database design for editable table - sql

I have to design an application which will store products with default values, in a table called default_products .
This application will be used by customers (or users) who should be able to use the products from the default_products table, with their default value, but they should also be able to :
edit and customize the default values of such product records for
their own personal use - without affecting the product records of
the other customers.
add their own products, but these products should not be visible to other users.
One solution I could imagine would be:
one default_products table containing all the default products with their default values
one custom_products table with all the products crated by the users, and also a copy of the default product the user would have customized,
and a boolean field like is_update to indicate if it is an update
from a default_product record
A function which looks first for the updated product records from the custom_product table, then queries the default_products table and
returns records from the default_product table + only the updated and
custom products for that user from the custom_product table.
Example:
default_product
- id
- name
- price
custom_product
- default_product.ID
- custom_price
I want the query to return: default_product.ID, default_product.name, custom_product.price only if there is a record in custom_product corresponding to the product in default_prduct, otherwise return: default_product.ID, default_product.name, default_product.price.
Any idea if this is any good? Or does anybody have any easier way to do?

How you approach this depends on whether the user has a copy of the default, or an alias to the default. That is, once a user has selected a product, do they see updates to the name and price of the default?
If it's an alias, you could have a products table to store products, and a user_products table to store which products the user has selected and any customization.
products:
id
name not null
price not null
user_products:
id
user_id not null
product_id
name
price
user_products.name and user_products.price are allowed to be null. If null, they will use the value from products. You do this using coalesce which will pick the first non-null value.
If a user wants to add their own product, user_products.product_id is null. Do a left join to ensure a result.
select
coalesce(up.name, p.name) as name,
coalesce(up.price, p.price) as price
from user_products up
left join products p on p.id = up.product_id
where user_id = ?
The disadvantage is the two tables have to be maintained in sync, and queries have to be written to coalesce each field. This might be a use case for table inheritance, if your database supports it.
If it's a copy, have a single table with a user_id column which can be null.
products:
id
user_id
name not null
price not null
When products.user_id is null these are the defaults available to anyone.
When a user selects a product, its values are copied to a new row with that user_id. Once a product is selected by a user they do not see future changes to the default. This may or may not be desirable.
You can optionally include an original_product_id column to remember which default product the user copied from.
The advantage is only one table needs to be maintained and the queries are simple.

Related

Delete an item (row) from table but keep the unused ID number for a future insertion

I have a database with an "inventory" table which contains products from a shop. Each product is identified using an ID number set in the "ID" column of the table.
I want to be able to delete a product from the table, but keeping the deleted product's id number for future product insertions into the database.
As a demonstration I inserted 4 items and named all of them "test"
And just as an example I named the "deleted" product as "vacio" (empty in spanish) to show the one that i deleted.
Now, if want to add another product in the future, the id number 2 is unused and I want to add the product with that id number instead of 4 (following the given example).
The DELETE query is no good since it erases the id number as well so its a no go.
I thought about checking for the first row of the table that contains the value "vacio" and using the UPDATE query in all fields except id but this doesnt feel "classy" and is not very efficient as It should have to update values a lot of times.
Is there some nice way of doing this?
I would not actually recommend reusing old identifiers. For one, this prevents you from using the auto_increment feature, which mean that you need to manually handle the column for each and every insertion: this adds complexity and is not efficient. Also, it might cause integrity issues in your database if you have other tables referencing the product id.
But if you really want to go that way: I would go for the deletion option. If there are foreign keys referencing the column, make sure that they have the on delete cascade option enabled so data is properly purged from dependent tables when a product is dropped.
Then, you can fill the first available gap the next time your create a new product with the following query:
insert into products(id, categoria, producto)
select min(id) + 1, 'my new category', 'my new product'
from products p
where not exists (select 1 from products p1 where p1.id = p.id + 1)
You could have a new column ESTADO where you handle if a record is active (1) or inactive (0). Then, to obtain only "undeleted" records you just have to filter by the new column. That way, you also prevent changing the product name to "vacio", which might be useful in the future.

Manually inserting record into linked table MS ACCESS

New to VBA and Access so hope I can explain this correctly.
I have two tables , Orders and Deliveries.
Orders include OrderNo, CustomerName, CustomerAddress, CustomerContact and so on.
Deliveries include DeliveryNo, OrderNo, DeliveryDate, DeliveryType and so on.
I have created a relationship between these two tables linking them between OrderNo as I require the CustomerName when creating a Delivery from an Order.
However sometimes a Delivery is manually inserted into the table using a form. A CustomerName is required for this record but there is now no corresponding OrderNo.
I am not sure how to set up my table to accommodate manual entries.
Appreciate the help, thanks
It sounds like the business requirement is to be able to insert deliveries into the delivery table without a corresponding order number. If this is the case, you need to relax the constraints on the table and remove relationship between Delivery.OrderNo and the Orders table. Otherwise, you could populate this field with a special number (0 or -1) to indicate no order in this circumstance if you need to enforce the foreign key relationship for other reasons. It all depends on how you wish to enforce the business logic.
What if you just added a CustomerName field to the form?
For what I understood of your question, you use the Orders table to generate the Deliveries, so for each order in the Orders table you would add/generate a record to the Deliveries table. Now, when you add a delivery manually(using the form) I suppose there is no order associated with it, hence no Customer Name. In that case the only solution would be to add a field called CustomerName to the mentioned form (I suppose the person who is manually inserting the Delivery knows the name of the customer) and any other field you need, and if your business logic requires it you can create a "virtual" Order with the same OrderNo as the inserted delivery.

Improvement on database schema

I'm creating a small pet shop database for a project
The database needs to have a list of products by supplier that can be grouped by pet type or product category.
Each in store sale and customer order can have multiple products per order and an employee attached to them the customer order must be have a customer and employee must have a position,
http://imgur.com/2Mi7EIU
Here are some random thoughts
I often separate addresses from the thing that has an address. You could make 1-many relationships between Employee, Customer and Supplier to an address table. That would allow you to have different types of addresses per entity, and to change addresses without touching the original table.
If it is possible for prices to change for an item, you would need to account for that somehow. Ideas there are create a pricing table, or to capture the price on the sales item table.
I don't like the way you handle the sales item table. the different foreign keys based on the type of the transaction is not quite correct. An alternative would be to replace SalesItem SaleID and OrderId with the SalesRecordId... another better option would be to just merge the fields from InStoreSale, SalesRecord, and CustomerOrders into a single table and slap an indicator on the table to indicate which type of transaction it was.
You would probably try to be consistent with plurality on your tables. For example, CustomerOrders vs. CustomerOrder.
Putting PositionPay on the EmployeePosition table seems off to... Employees in the same position typically can have different pay.
Is the PetType structured with enough complexity? Can't you have items that apply to more than one pet type? For example, a fishtank can be used for fish or lizards? If so, you will need a many-to-many join table there.
Hope this helps!

Advanced SQL Update query

I'm trying to create a sql update query for a stored procedure but I'm getting lost in trying to figure out how to to do it.
Here is what I'm trying do:
The table I'm wanting to update has 3 columns: product_item_id, rel_product_item_id, and sequence. This table is called "ProductRelationship".
I also have another table called ProductDetails. This table also contains a column called product_item_id as well as a column called "sku".
I want the user to be able input the sku number that updates the rel_product_item_id column with the corresponding product_item_id number from the ProductDetails table.
So on the front-end, the user is inputting a sku, but in the backend, the product_item_id number is getting updated in the database based on the sku the user entered.
Basically its cross-referencing the sku number on the details table, finding the appropiate product item id number and inserting that id number in the table instead of the user-inputted sku number.
update ProductRelationship
set rel_product_item_id = (select product_item_id
from ProductDetails
where sku = #UserInput)
where product_item_id = #ValueSetOnPage

Table Design For Multiple Different Products On One Order

If I were to have an online shopping website that sold apples and monitors and these were stored in different tables because the distinguishing property of apples is colour and that of monitors is resolution how would I add these both to an invoice table whilst still retaining referential integrity and not unioning these tables?
Invoices(InvoiceId)
|
InvoiceItems(ItemId, ProductId)
|
Products(ProductId)
| |
Apples(AppleId, ProductId, Colour) Monitors(MonitorId, ProductId, Resolution)
In the first place, I would store them in a single Products table, not in two different tables.
In the second place, (unless each invoice was for only one product) I would not add them to a single invoice table - instead, I would set up an Invoice_Products table, to link between the tables.
I suggest you look into Database Normalisation.
A question for your data model is You need a reference scheme will you use to identify products? Maybe SKU ?
Then identify each apple as a product by assigning an SKU. Likewise for monitors. Then use the SKU in the invoice item. Something like this:
product {sku}
key {sku};
invoice_item {invoice_id, sku}
key {invoice_id, sku} ;
apple {color, sku}
key {color}
key {sku};
monitor {size, sku}
key {size}
key {sku};
with appropriate constrains... in particular, the union of apple {sku} and monitor {sku} == product {sku}.
So Invoice table has a ProductID FK, and a ProductID can be either an AppleID (PK color) or MonitorID (PK resolution)?
If so, you can introduce a ProductTypeID with values like 0=apple, 1=monitor, or a isProductTypeApple boolean if there's only ever going to be 2 product types, and include that in the ProductID table PK.
You also need to include the ProductTypeID field in the Apple table and Monitor table PK.
I like name-value tables for these...It might be easier to redesign so it goes 'Product' and then 'product details'...product details holds the product id, the detail type and then the value. This would allow you to hold apples and monitors in the same table regardless of identifying attribute (and leave it open for other product to be added later on).
Similiar approach can be taken in the invoice table...have a 'product_type' column that tells you which table to look into (apple or monitor) and then a 'product_id' that references whatever ID column is in the apple/monitor table. Querying on a setup like this is a bit difficult and may force you to use dynamic sql...I'd only take this route if you have no control over doing the redesign above (and other answers posted here refer to)
First solution is preferential I would think...change the design on this db to the name value pair with the products and you'll save headaches writing your queries later.