Designing a rudimentary Shopping Cart database - sql

create table [User]
(
UserId int primary key identity(1,1),
FirstName nvarchar(256) not null,
LastName nvarchar(256) not null,
)
create table Product
(
ProductId int primary key identity(1,1),
UnitPrice decimal(18,2) not null, //For catalog purposes.
Name nvarchar(1000) not null,
Description nvarchar(max) not null,
Stock int not null
)
create table [Order]
(
OrderId int primary key identity(1,1),
UserId int foreign key references [User](UserId),
ProductId int foreign key references Product(ProductId),
UnitCost decimal(18,2) not null, //How much it actually cost when the person bought it.
ItemCount int not null,
Subtotal decimal(18,2) not null
)
create table OrderDetail
(
OrderDetailId int primary key identity(1,1),
?
I'm stuck on the database design of the order system.
A user can choose n products to add to a order request. Any suggestions?
Following some advice given here, how would this feel? Any pitfalls?
create table [User]
(
UserId int primary key identity(1,1),
FirstName nvarchar(256) not null,
LastName nvarchar(256) not null,
)
create table Product
(
ProductId int primary key identity(1,1),
UnitPrice decimal(18,2) not null,
Name nvarchar(1000) not null,
Description nvarchar(max) not null,
Stock int not null
)
create table [Order]
(
OrderId int primary key identity(1,1),
UserId int foreign key references [User](UserId),
DateOfOrder datetime not null
)
create table OrderDetail
(
OrderDetailId int primary key identity(1,1),
OrderId int foreign key references [Order](OrderId),
ProductId int foreign key references Product(ProductId),
UnitCost decimal(18,2) not null,
ItemCount int not null,
Subtotal decimal(18,2) not null
)

Typically, you'd have the Order table with the top-level order information (who, when etc) and then an OrderItem (or OrderDetail) table which has a row for each product that forms part of the order including columns like:
OrderId
ProductId
Quantity
etc
Good candidate for a PK on this OrderItem/OrderDetail table would be on OrderId + ProductId.
So where you have columns like ProductId, UnitCost, ItemCount etc in the Order table, those are in the wrong place and should be in the OrderItem/OrderDetail table.
Update:
To set up a compound PK, you can do:
create table OrderDetail
(
OrderId int foreign key references [Order](OrderId),
ProductId int foreign key references Product(ProductId),
...other columns...,
CONSTRAINT PK_OrderDetail PRIMARY KEY(OrderId, ProductId)
)

Related

Direct relation in SQL

I'm a beginner in SQL and I'm trying to make a small database, but I was asked to make a direct relation between OrderNumber in Orders table and CustomerNumber in Customers table, aren't I using a direct relation in here?.
Here is my code:
Customers table:
CREATE TABLE Customers
(
CustomerNumber VARCHAR(25) PRIMARY KEY NOT NULL,
CustomerName VARCHAR(50),
Phone INT NOT NULL,
Country VARCHAR(50),
City VARCHAR(50),
State VARCHAR(50),
PostalCode VARCHAR(5) NOT NULL
);
Orders table:
CREATE TABLE Orders
(
OrderNumber VARCHAR(25) ,
CustomerNumber VARCHAR(25) PRIMARY KEY NOT NULL,
ProductName VARCHAR(200) NOT NULL UNIQUE,
OrderDate DATE NOT NULL,
requiredDate DATE NOT NULL,
Status VARCHAR(50)
);
I believe, you probably want something like this:
CREATE TABLE Customers
(
CustomerNumber INT PRIMARY KEY NOT NULL,
CustomerName VARCHAR(50),
Phone INT NOT NULL,
Country VARCHAR(50),
City VARCHAR(50),
State VARCHAR(50),
PostalCode VARCHAR(5) NOT NULL
);
CREATE TABLE Orders
(
OrderNumber INT PRIMARY KEY NOT NULL,
CustomerNumber INT NOT NULL FOREIGN KEY REFERENCES Customers(CustomerNumber),
ProductName VARCHAR(200) NOT NULL UNIQUE,
OrderDate DATE NOT NULL,
requiredDate DATE NOT NULL,
Status VARCHAR(50)
);
Changed the datatype of CustomerNumber and OrderNumber to INT
Made Orders.CustomerNumber a foreign key with a relation to the Customer table (CustomerNumber column)

Create a SQL table from an ERD, implementing all constraints

This is the ERD diagram from which I'm to write a SQL query for:
Sql Server
Product Table
CREATE TABLE product
(
productid INT PRIMARY KEY IDENTITY(1, 1),
productname VARCHAR(50),
unitprice NUMERIC(17, 2)
)
Orders Table
CREATE TABLE orders
(
orderid INT PRIMARY KEY IDENTITY(1, 1),
OrderDate Datetime,
productid INT,
FOREIGN KEY (productid) REFERENCES product(productid)
)
This is for Oracle. You can create PRODUCT table similarly without FOREIGN KEY:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderDate date,
ProductID int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder FOREIGN KEY (ProductID)
REFERENCES PRODUCT(ProductID)
);
CREATE TABLE product
(
ProductId int,
ProductnName varchar(50) not null,
UnitPrice NUMERIC(10, 2)
CONSTRAINT PRIMARY KEY (ProductId)
)
CREATE TABLE orders
(
orderid int auto_increment,
OrderDate Datetime,
ProductId int,
CONSTRAINT PRIMARY KEY (orderid)
CONSTRAINT FOREIGN KEY (ProductId) REFERENCES product(ProductId)
)

Ambiguous column name 'ProductNumber'

Can't figure out why my question 3 is getting the error mentioned above.
Below is my code
/* Question 1 */
CREATE TABLE CUSTOMERS
(
CustomerID INT PRIMARY KEY,
CustFirstName VARCHAR(50) NOT NULL,
CustLastName VARCHAR(50) NOT NULL,
CustStreetAddress VARCHAR(50) NOT NULL,
CustCity VARCHAR(50) NOT NULL,
CustState VARCHAR(26) NOT NULL,
CustZipCode INT NOT NULL,
CustAreaCode INT NOT NULL,
CustPhoneNumber VARCHAR (26) NOT NULL
);
CREATE TABLE EMPLOYEES
(
EmployeeID INT PRIMARY KEY,
EmpFirstName VARCHAR(50) NOT NULL,
EmpLastName VARCHAR(50) NOT NULL,
EmpCity VARCHAR (50) NOT NULL,
EmpState VARCHAR(26) NOT NULL,
EmpZipCode INT NOT NULL,
EmpAreaCode INT NOT NULL,
EmpPhoneNumber VARCHAR(26) NOT NULL,
EmpBirthDate DATE NOT NULL
);
CREATE TABLE ORDERS
(
OrderNumber INT PRIMARY KEY,
OrderDate DATE NOT NULL,
ShipDate DATE NOT NULL,
CustomerID INT NOT NULL,
EmployeeID INT NOT NULL,
FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEES(EmployeeID),
FOREIGN KEY(CustomerID) REFERENCES CUSTOMERS(CustomerID)
);
CREATE TABLE CATEGORIES
(
CategoryID INT PRIMARY KEY,
CategoryDescription VARCHAR(255) NOT NULL
);
CREATE TABLE PRODUCTS
(
ProductNumber INT PRIMARY KEY,
ProductName VARCHAR(50) NOT NULL,
ProductDescription VARCHAR(255) NOT NULL,
RetailPrice INT NOT NULL,
QuantityOnHand INT NOT NULL,
CategoryID INT NOT NULL,
FOREIGN KEY(CategoryID) REFERENCES CATEGORIES (CategoryID)
);
CREATE TABLE ORDER_DETAILS
(
OrderNumber INT NOT NULL,
ProductNumber INT NOT NULL,
QuotedPrice INT NOT NULL,
QuantityOrdered INT NOT NULL,
PRIMARY KEY (OrderNumber, ProductNumber),
FOREIGN KEY (OrderNumber) REFERENCES ORDERS(OrderNumber),
FOREIGN KEY(ProductNumber) REFERENCES PRODUCTS(ProductNumber)
);
CREATE TABLE VENDORS
(
VendorID INT PRIMARY KEY,
VendName VARCHAR(100) NOT NULL,
VendStreetAddress VARCHAR(50) NOT NULL,
VendCity VARCHAR(50) NOT NULL,
VendState VARCHAR(26) NOT NULL,
VendFaxNumber VARCHAR(50) NOT NULL,
VendWebPage VARCHAR(100) NOT NULL,
VendEmailAddress VARCHAR(100) NOT NULL
);
CREATE TABLE PRODUCT_VENDORS
(
ProductNumber INT NOT NULL,
VendorID INT NOT NULL,
WholeSalePrice INT NOT NULL,
DaysToDeliver INT NOT NULL,
PRIMARY KEY(ProductNumber, VendorID),
FOREIGN KEY(ProductNumber) REFERENCES PRODUCTS(ProductNumber),
FOREIGN KEY(VendorID) REFERENCES Vendors(VendorID)
);
/* QUESTION 2 */
SELECT
OrderDate, CustFirstName, CustLastName
FROM
CUSTOMERS C, ORDERS O
WHERE
C.CustomerID = O.OrderNumber;
/* QUESTION 3 */
SELECT
ProductNumber, WholeSalePrice, VendName
FROM
PRODUCTS P, PRODUCT_VENDORS PV, VENDORS V
WHERE
P.PRODUCTNUMBER = PV.ProductNumber AND PV.VendorID = V.VendorID;
I got the error
Ambiguous column name 'ProductNumber'
Because there are two table have column name of ProductNumber in your query you need to tell DB engine which column you want to get.
Also, use JOIN instead of , comma CROSS JOIN, because Join is more clear than a comma on the relationship between the two tables
SELECT PV.ProductNumber, WholeSalePrice, VendName
FROM PRODUCTS P
JOIN PRODUCT_VENDORS PV ON P.PRODUCTNUMBER = PV.ProductNumber
JOIN VENDORS V ON PV.VendorID = V.VendorID;
Your query stipulates SELECT ProductNumber From two tables that both have ProductNumber. In the SELECT columns list, prefix ProductNumber with the table name from which you want to receive the data.
also, Have a look at your question 2. I don't think you really want to join customer id to order number, and you should use JOIN syntax intead of joining in the WHERE clause
Ambiguous error means that you are calling a certain field in which exist in both Table and the SQL has no idea where to get it. See, with your query, you're just literally calling the ProductNumber field in which the SQL has no idea where to get it since there are ProductNumber fields on both Tables, and you didn't specify any table.
so it is better when you have same column in multiple tables use table preface 1st then column like table1.col1,table2.col2
so in your case
SELECT p.ProductNumber, WholeSalePrice, v.VendName
FROM PRODUCTS P join
PRODUCT_VENDORS PV on P.PRODUCTNUMBER = PV.ProductNumber //
join VENDORS V on PV.VendorID = V.VendorID //use join instead your's

How to Relate 2 table with each other with 2 foreign keys

Here is my code it generates Foreign key conflict error
CREATE TABLE tblProducts
(
ProductID int NOT NULL IDENTITY PRIMARY KEY,
ProductName nvarchar(30) NOT NULL,
BatchID int NOT NULL FOREIGN KEY REFERENCES tblBatches (BatchID)
)
CREATE TABLE tblBatches
(
BatchID INT NOT NULL IDENTITY PRIMARY KEY,
BatchCode nvarchar(20) NOT NULL,
Quantity int NOT NULL,
BatchMnf Date NOT NULL,
BatchExp Date NOT NULL,
PurchaseRate int NOT NULL,
SalesRate int NOT NULL,
ProductID int NOT NULL FOREIGN KEY REFERENCES tblProducts (ProductID)
)
You cannot do that. This is a circular reference.
This is a bad design but if you want to do that, you need to make foreign key columns Nullable.
CREATE TABLE tblProducts
(
ProductID int NOT NULL IDENTITY PRIMARY KEY,
ProductName nvarchar(30) NOT NULL,
BatchID int NULL FOREIGN KEY REFERENCES tblBatches (BatchID)
)
CREATE TABLE tblBatches
(
BatchID INT NOT NULL IDENTITY PRIMARY KEY,
BatchCode nvarchar(20) NOT NULL,
Quantity int NOT NULL,
BatchMnf Date NOT NULL,
BatchExp Date NOT NULL,
PurchaseRate int NOT NULL,
SalesRate int NOT NULL,
ProductID int NULL FOREIGN KEY REFERENCES tblProducts (ProductID)
)
Then you need to update reference fields after inserting records in tblBatches and tblProducts.
The good design says you need to create a bridge table like this:
CREATE TABLE tblProductsBatch
(
ID int NOT NULL IDENTITY PRIMARY KEY,
ProductID int NOT NULL,
BatchID int NOT NULL
)
And after inserting product and batch, you need to insert a record in this table to link rows to each other.

T-SQL: CHECK constraint not working

I have the following T-SQL schema. The problem I am having is that the check constraint on the Download table is not working. I am still able to insert records into that table that contain NULL values for both ProductId and CategoryId. Why is this so?
I want both the ProductId and CategoryId columns to allow NULL values, but for any given record only one of these are allowed to be set to NULL, the other needs to be a corresponding Id of the Category or Product table.
CREATE TABLE Category (
Id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
Description nvarchar(100) NULL,
ParentCategoryId int NULL
CONSTRAINT fk_CategoryId_CategoryId FOREIGN KEY (Id) REFERENCES Category(Id)
)
GO
CREATE TABLE Product (
Id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
Title nvarchar(100) NOT NULL,
TagLine nvarchar(MAX) NOT NULL,
Description nvarchar(MAX)NULL,
CategoryId int NOT NULL,
ImageUrl nvarchar(255) NULL,
Keywords nvarchar(200) NOT NULL
CONSTRAINT fk_ProductCategoryId_CategoryId FOREIGN KEY (CategoryId) REFERENCES Category(Id)
)
GO
CREATE TABLE Download (
Id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
Title nvarchar(100) NOT NULL,
Description nvarchar(MAX) NULL,
CategoryId int NULL,
ProductId int NULL,
DownloadUrl nvarchar(255) NOT NULL,
CONSTRAINT fk_DownloadCategoryId FOREIGN KEY (CategoryId) REFERENCES Category(Id),
CONSTRAINT fk_DownloadProductId FOREIGN KEY (ProductId) REFERENCES Product(Id),
CONSTRAINT chk_ReferencesCategoryOrProduct CHECK (ProductID != NULL AND CategoryId != NULL)
)
GO
Use:
CONSTRAINT chk_ReferencesCategoryOrProduct CHECK (ProductID IS NOT NULL
OR CategoryId IS NOT NULL)
NULL isn't a value -- it's a placeholder for the lack of a value. Which is why you need to use specific syntax to check for it.