Multiple values in the same column in database - sql

I am doing an order food online. But I am wondering if I can have 2 values in a same column. Or is there any way I can do something like that?
The DB structure:
id | product_code | product_name | price
Sample data:
1 | 'A01' | 'Chicken Fired Rice' | 6.50 10.50
So let say the chicken fried rice has two sizes regular for $6.50 and large for $10.50. Is there any idea how I can create a DB like this?
Thank you.

It's bad idea, your db design violates the first normal form: https://en.wikipedia.org/wiki/First_normal_form.
With this violation it will be much harder to write select against such table.

Don't store information like that in price column it violates the First Normal Form, It will be difficult to parse the data
I will go with two tables
One to store the product information and another table to store the price.
Product table
Create table Product
(
Product_Id int, --Auto generated
product_code varchar(10),
product_name varchar(100)
)
Price Table
Create table Price
(
Price_Id Int, --Auto Generated
Product_Id int, --Foreign key column referred from product table
Size varchar(20),
Price Decimal(10,2)
)
or If it is always two size then you can create single table with two column's to store Price of Regular and Large size.
Create table Product
(
Product_Id int, --Auto generated
product_code varchar(10),
product_name varchar(100),
Regular_size_price Decimal(10,2),
Large_size_price Decimal(10,2)
)

That is bad design from a DB perspective. To help you avoiding problems like this, there are a set of rules call Normal Forms.
There are many ways to work around this problem.
One is to add another column to your table "size" for example and insert to rows one for a small and another for large.
In case you really want to use that design, I'm sure you could same a String with comma separated values and pipes and use to creativity to break this String to size prices. :)

There are several ways; one is using a JSON field, something that's not universally supported. Though this is not a good idea in most situations, including yours.
Normalization is the process of breaking your database structures into logical relational parts (tables). For example:
Products: id | code | name
Prices: product_id | size | price
This way you can have any number of prices for any given product; product_id is a foreign key, a reference to the id field of a product. There's certainly other information that could/should/will be added to such a table structure, but this is the basis of the sort of flexibility you're asking for.

Related

Storing updates from different updaters in the History table

I have a table "AvailableProducts" with following fields:
StoreID int,
ProductID int,
ProductPrice decimal,
IsAvailable bit
The ProductPrice can be changed either by sales person in the store or it can be updated by a price update from the brand.
Now to store the history of price changes, I've created a history table as follows:
Table ProductPriceHistory
UpdateID int,
StoreID int,
ProductID int,
ProductPrice decimal,
IsAvailable bit,
UpdatedBy int,
UpdatedAt datetime
The problem I am facing is that keeping BrandID or SalesPersonID (That made the changes to price) in the UpdatedBy field is wrong design.
I can modify it to something like this:
Table ProductPriceHistory
UpdateID int,
StoreID int,
ProductID int,
ProductPrice decimal,
IsAvailable bit,
BrandId int,
SalesPersonID int,
UpdatedAt datetime
This would allow me to reference the updating entity by a foreign key in the Brand and SalesPerson Tables using the Id fields. But it would also lead to many empty or null column values since only one entity i.e. either brand or SalesPerson can update the price at given time.
I could also create two different history tables to save updates made by SalesPerson and Brands separately but this solution doesn't look appealing.
Any suggestions for improvement in this design as I would like the history for this table to be maintained in a single table. Thanks :)
You could create an ObjectType table with 2 items:
CREATE TABLE [dbo].[ObjectType](
[ObjectTypeId] [int] NOT NULL,
[ObjectTypeName] [nvarchar](100) NULL)
GO
INSERT INTO dbo.ObjectType VALUES (1, 'Brand')
INSERT INTO dbo.ObjectType VALUES (2, 'SalesPerson')
Then add a new column ObjectTypeId to table ProductPriceHistory
ALTER TABLE ProductPriceHistory
ADD ObjectTypeId int
You could write log for many kinds of item not only for SalesPerson and Brands
This is a common question - it's often asked in relation to the object orientation concept of polymorphism.
There are 3 standard solutions - you've identified two of them; the final one is to model the common fields in a single table, and have separate tables for the variant data. That would have tables "sales_update" and "brand_update", with foreign keys on updateID back to the update history table.
There is no elegant solution - the relational model simply doesn't support this use case particularly nicely. You need to look at the rest of your system, and pick the solution that's easiest in your case. Usually, that's the "one table stores everything model" - but your situation may be different.

When creating a foreign key do I also need to include the fields from the linked table?

Apologies, this is quite a fundamental part of SQL and I'm sure it's a question that has been asked before, I just can't find an example that relates to mine enough for me to understand it. Almost all the resources I find are things like employee/manager relationships which I think I understand but can't apply to my situation!
I am using MSSQL Server 2008. I am creating a database which has 3 tables. It will be used for a simple web application that allows people to record which cars they have double parked in front of (thus blocking in), so that the owner of the blocked car knows who to contact if they want to move the car.
Cars - Details about people's cars.
People - who can own at least one
car.
ParkedCars - This is where I'm getting stuck.
See below:
CREATE TABLE dbo.Cars
(
Pk_Car_Id INT PRIMARY KEY,
Manufacturer VARCHAR(55),
Model VARCHAR(55),
Colour VARCHAR(50),
RegistrationNo VARCHAR(10)
);
CREATE TABLE dbo.People
(
Pk_People_Id INT PRIMARY KEY,
FirstName VARCHAR(55),
LastName VARCHAR(55),
Extension INT,
Fk_Car_Id INT FOREIGN KEY REFERENCES Cars(Pk_Car_Id)
);
CREATE TABLE dbo.ParkedCars
(
PK_ParkedCars_Id INT PRIMARY KEY,
FK_Car_Id INT FOREIGN KEY REFERENCES dbo.Cars(Pk_Car_Id),
FK_People_Id INT FOREIGN KEY REFERENCES dbo.People(Pk_People_Id),
DateParked datetime
);
My question is - when creating the ParkedCars table, do I need to reference things like people.FirstName or Cars.RegistrationNo as a column of their own? Or can I do what I have done above and just create foreign key columns? So the table may look something like this when populated with data:
+------------------+-----------+--------------+--------------------+
| PK_ParkedCars_Id | FK_Car_Id | FK_People_Id | DateParked |
+------------------+-----------+--------------+--------------------+
| 2 | 1 | 5 | 19/2/2016 08:33:00 |
+------------------+-----------+--------------+--------------------+
| 3 | 4 | 2 | 19/2/2016 08:48:33 |
+------------------+-----------+--------------+--------------------+
Then I can just select the relevant fields from each table and display the results.
I did try a similar method but every time I tried to insert any data, it got stuck because one of the keys was set to null while inserting that particular row. It didn't allow any further data to be inserted into any table.
Please can someone explain the best way to tackle this kind of thing?
Thanks
As #Arvo stated, your schema looks good..
(Maybe with minor tweaks, for example, I'm not sure you need the FK_People_Id field in the "parked_cars" table since the "People" table relates to the "Cars" table anyways).
If you're having trouble with NULL keys, I would suggest looking into "OUTER JOINS", if you're not familiar with the subject already, and see if that helps you.
Also, make sure that when you write SELECT statement that contain the "parked_cars" table, you'll probably want to call the "cars" table TWICE!!!
Here's an example, (hope it'll work):
SELECT parked.ParkedCars_id, c1.RegistrationNo, p1.FirstName, p1.LastName,
parked.Fk_Car_id, c2.RegistrationNo, p2.FirstName, p2.LastName
FROM dbo.ParkedCars AS parked
LEFT OUTER JOIN dbo.Cars c1
ON parked.ParkedCars_Id = c1.Pk_Car_Id
LEFT OUTER JOIN dbo.People p1
ON c1.Pk_Car_Id = p1.Fk_Car_Id
LEFT OUTER JOIN dbo.Cars c2
ON parked.Fk_Car_Id = c2.Pk_Car_Id
LEFT OUTER JOIN dbo.People p2
ON c2.Pk_Car_Id = p2.Fk_Car_Id;
Based on comments and whatnot else looks like you have to redesign your schema somewhat.
First, don't use FK_Car_ID in People table, but use FK_People_ID in Car table. This solves problem for someone having multiple cars; opposite situation (car has multiple owners) is unlikely. Well, if you need to specify all possible users of said car, then you have to create 'junk' table (People_Car_Relation), linking to both car and people.
Second, you don't have to use FK_people_ID in Parked_Cars table at all - it is enough to link to Car only.
Third, create primary key fields as identity(1,1) - this way they fill themselves and you don't have to calculate ID values beforehand.
Then remember - never use insert statement without specified fields list. Currently you are attempting to insert record with specific (duplicate) primary key value, which doesn't succeed.
Always use next syntax for inserts:
insert into dbo.parkedcars(fk_car_id, fk_people_id, dateparked) values(...)
this way you can be sure that your SQL code does what you intend it to do.

Can a table title be a Primary Key?

I'm trying to retrofit some tables to an existing database. The existing database has equipment numbers and I'm trying to add in tables with more information on that equipment. Ideally, I'd like to make the table titles the ID numbers and set those as the PK of that table, making the ID numbers in the equipment list the FK.
Is it possible to set the table title as the PK? Here's an example of one of the tables, and I'd like to make "E0111" the PK.
CREATE TABLE E0111(
EQUIPMENT Varchar(200),
MAINTENANCE varchar(200),
CYCLE varchar(200)
);
No you can't do this because the primary key needs to be unique for every row of your table. If you "could" use the table name as the primary key it would be the same for every row.
You should use a unique column in your table as the primary key.
Also, I have no idea how you could achieve this with SQLite or any DBMS.
First thing before I even get anywhere near answering the question about the table names being primary keys, we need to take a step back.
You should NOT have a table for each piece of equipment.
You need an Equipment table, that will store all of your pieces of Equipment together. I assume you have that already in the existing database.
Hopefully it is keyed with a Unique Identifier AND an Equipment Number. The reason for having a separate Unique Identifier, is that your database server uses this for referential integrity and performance - this is not a value that you should show or use anywhere other than inside the database and between your database and whatever application you are using to modify the database. It should not typically be shown to the user.
The Equipment Number is the one you are familiar with (ie 'E0111'), because this is shown to the User and marked on reports etc. The two have different purposes and needs, so should not be combined into a single value.
I will take a stab at what your Equipment table may look like:
EquipmentId int -- database Id - used for primary key
EquipmentName Varchar(200) -- human readable
EquipmentDescription Text
PurchaseDate DateTime
SerialNumber VarChar(50)
Model Varchar(200)
etc..
To then add the Maintenance Cycle table as you propose above it would look like:
MaintenanceId int -- database Id - used for primary key this time for the maintenance table.
EquipmentId int -- foreign key - references the equipment table
MaintenanceType Varchar(200)
DatePerformed DateTime
MaintenanceResults VarChar(200)
NextMaintenanceDate DateTime
To get the results about the Maintenance Cycle for all equipment, you then JOIN the tables on the 2 EquipmentIds, ie
SELECT EquipmentName, EquipmentDescription, SerialNumber, MaintenanceType DatePerformed
FROM Equipment
JOIN MaintenanceCycle ON Equipment.EquipmentId = Maintenance.EquipmentId
WHERE EquipmentName = 'E0111'
You cannot make the name of the table a primary key.
All primary keys should be unique and a table column not table name. This is the general rule of thumb for a priamry key. There are plenty of resources on the internet about Primary keys.
Here are just afew:
http://www.w3schools.com/sql/sql_primarykey.asp
http://database-programmer.blogspot.co.uk/2008/01/database-skills-sane-approach-to.html
The name of a table should be descriptive of what is hold within it. See that data table as a drawer where you shall label what it contains.
In my humble point of view, the ID of an equipement shall only be labeled as-is on the equipement in question. Otherwise, in your database, it shall be the table Equipments that prevails with the ID of each piece of equipment you have.
Then, if you have other equipment-related information to save, add another table with the kind of information it shall contains, with the ID of the related equipment for which this information is saved.
For example, let's say we hold a maintenance schedule over your equipment.
Equipments
-----------------------------------------------------
Id | Description | Location | Brand | Model
-----------------------------------------------------
1 | Printer/Copier| 1st Floor | HP | PSC1000
Maintenances
---------------------------------------------------------
Id | Description | Date | EquipmentId | EmployeeId
---------------------------------------------------------
Note that the EmployeeId column shall be there only if one requires to know who did what maintenance and when, for instance.
MaintenanceCycles
--------------------------------------------
Id | Code | Description | EquipementId
--------------------------------------------
1 | M | Monthly | 1
This way, every equipment can have its cycle, and even multiple cycles per equipment if required. This lets you the flexibility that you need for further changes.

Constraint to table column name (postgresql)

I'm implementing a product database using the single table inheritance (potentially later class table inheritance) model for product attributes. That's all working fine and well but I'm trying to figure out how best to deal with product variants whilst maintaining referential integrity.
Right now a simplified version of my main product table looks like this:
CREATE TABLE product (
id SERIAL NOT NULL,
name VARCHAR(100) NOT NULL,
brand VARCHAR(40) NOT NULL,
color VARCHAR(40)[] NOT NULL
)
(color is an array so that all of the standard colors of any given product can be listed)
For handling variants I've considered tracking the properties on which products vary in a table called product_variant_theme:
CREATE TABLE product_variant_theme (
id SERIAL NOT NULL,
product_id INT NOT NULL,
attribute_name VARCHAR(40) NOT NULL
)
Wherein I insert rows with the product_id in question and add the column name for the attribute into the attribute_name field e.g. 'color'.
Now feel free to tell me if this is an entirely stupid way to go about this in the first place, but I am concerned by the lack of a constraint between attribute_name and the actual column name itself. Obviously if alter the product table and remove that column I might still be left with rows in my second table that refer to it. The functional equivalent of what I'm looking for would be something like a foreign key on attribute_name to the information_schema view that describes the tables, but I don't think there's any way to do that directly, and I'm wondering if there is any reasonable way to get that kind of functionality here.
Thanks.
Are you looking for something like this?
product
=======
id
name
attribute
=========
id
name
product_attribute_map
=====================
product_id
attribute_id
value

SQL - Properties Structure

What is the best way to setup this table structure.
I have 3 tables, one table we'll call fruit and the other two tables are properties of that fruit so fruit_detailed and fruit_basic.
fruit
id | isDetailed
fruit_detailed
id | price | color | source | weight | fruitid?
fruit_basic
id | value | fruitid?
So what I want to do is have a property in fruit called isDetailed and if true, fill the fruit_detailed table with properties like color, weight, source, etc (multiple column). If its false then store in fruit_basic table with properties written in a single row.
Storage sounds quite basic but if I want to select a fruit and get its properties, how can I determine which table to join? I could use and IF statement on the isDetailed property and then join like that but then you have two different types of properties coming back
How would you create the tables or do the join to get the properties? Am I missing something?
Personally, I see no need to split the basic and detailed attributes out into separate tables. I think they can/should all be columns of the main fruit table.
I would probably model this like so:
CREATE TABLE Fruits (
fruit_id INT NOT NULL,
CONSTRAINT PK_Fruit PRIMARY KEY CLUSTERED (fruit_id)
)
CREATE TABLE Fruit_Details (
fruit_id INT NOT NULL,
price MONEY NOT NULL,
color VARCHAR(20) NOT NULL,
source VARCHAR(20) NOT NULL,
weight DECIMAL(10, 4) NOT NULL,
CONSTRAINT PK_Fruit_Detail PRIMARY KEY CLUSTERED (fruit_id),
CONSTRAINT FK_Fruit_Detail_Fruit FOREIGN KEY (fruit_id) REFERENCES Fruit (fruit_id)
)
I had to guess on appropriate data types for some of the columns. I'm also not sure exactly what the "value" column is in your Fruit_Basic table, so I've left that out for now.
Don't bother putting a bunch of IDs out there simply for the sake of having an ID column on every table. The Fruits->Fruit_Details relationship is a one-to-zero-or-one relationship. In other words, you can have at most one Fruit_Details row for each Fruits row. In some cases you might have no row in Fruit_Details for a particular row in Fruits.
When you're querying you can simply OUTER JOIN from the Fruits table to the Fruit_Details table. If you get back a NULL value for Fruit_Details.fruit_id then you know that the fruit doesn't have any details. You can always include the Fruit_Details columns, they'll just be NULL if the row doesn't exist. That way you can always have homogeneous resultsets. As you've discovered, otherwise you end up having to worry about different column lists coming back depending on the row in question, which will lead to tons of headaches.
If you want to include an "isDetailed" column then you can just use this:
CASE WHEN Fruit_Details.fruit_id IS NULL THEN 0 ELSE 1 END AS isDetailed
This approach also has an advantage over putting all of the columns in one table because it lowers the number of NULL columns in your database and depending on your data can substantially decrease storage requirements and improve performance.
I'm not sure why you would need to store a basic or detailed list of the fruit in different tables. You should just have 1 table and then leave some of the fields null if the information doesn't exist.
Assuming that value from fruit_basic is the same as price from fruit_detailed, you'd have something like this.
fruit
id | detail_id (fk to fruit_detailed table)
fruit_details
detail_id | price | color | source | weight