--insert a new customer into automart
--insert into person
--insert into vehicle
--insert into RegisteredCustomer
--transaction --all the inserts should happen or none of them
--should check to make sure the customer doesn't already exist
Use Automart
Go
--this version just does the inserts raw
--it is possible to insert into one or more tables
--even though it errors in another
Create proc usp_AddNewCustomer
--parameters
@LastName nvarchar(255),
@FirstName nvarchar(255),
@LicenseNumber nvarchar(10),
@VehicleMake nvarchar(255),
@VehicleYear nchar(4),
@Email nvarchar(255),
@CustomerPassword nvarchar(20)
As
Insert into Person(Lastname, FirstName)
Values(@lastName, @firstName)
Declare @Personkey int
set @PersonKey=ident_Current('Person')
Insert into Customer.vehicle
(LicenseNumber, VehicleMake, VehicleYear, personKey)
Values(@LicenseNumber, @VehicleMake, @VehicleYear, @PersonKey)
Insert into Customer.RegisteredCustomer
(Email, CustomerPassword, PersonKey)
Values(@Email, @CustomerPassword, @PersonKey)
Go
--test1
exec usp_AddNewCustomer
@LastName ='Nelson',
@FirstName ='Admiral',
@LicenseNumber='FTW100' ,
@VehicleMake='Prius',
@VehicleYear='2014',
@Email='admiral@gmail.com',
@CustomerPassword = 'password'
Select * From Person
Select * From Customer.Vehicle
Select * From Customer.RegisteredCustomer
--version two
--this version adds a transaction and a
--try catch
Go
Alter proc usp_AddNewCustomer
--parameters
@LastName nvarchar(255),
@FirstName nvarchar(255),
@LicenseNumber nvarchar(10),
@VehicleMake nvarchar(255),
@VehicleYear nchar(4),
@Email nvarchar(255),
@CustomerPassword nvarchar(20)
As
Begin Tran
Begin Try
Insert into Person(Lastname, FirstName)
Values(@lastName, @firstName)
Declare @Personkey int
set @PersonKey=ident_Current('Person')
Insert into Customer.vehicle
(LicenseNumber, VehicleMake, VehicleYear, personKey)
Values(@LicenseNumber, @VehicleMake, @VehicleYear, @PersonKey)
Insert into Customer.RegisteredCustomer
(Email, CustomerPassword, PersonKey)
Values(@Email, @CustomerPassword, @PersonKey)
Commit tran
End try
Begin Catch
Rollback tran
print 'The transaction failed'
print error_message()
end catch
Go
--version 3
--this version checks to see if the customer exists
--and then if the vehicle exists
--if the customer exists and the vehicle does not exist, insert it
--otherwise just end
--if the customer does not exist insert the person,
--vehicle and registered customer
Alter proc usp_AddNewCustomer
--parameters
@LastName nvarchar(255),
@FirstName nvarchar(255),
@LicenseNumber nvarchar(10),
@VehicleMake nvarchar(255),
@VehicleYear nchar(4),
@Email nvarchar(255),
@CustomerPassword nvarchar(20)
As
If exists
(Select p.PersonKey from Person p
inner Join Customer.Vehicle v
on p.personkey=v.personkey
inner join Customer.RegisteredCustomer r
on r.PersonKey=p.Personkey
Where lastname=@lastName
and firstname=@firstName
and Email = @Email)
Begin
Declare @pKey int
Select @pkey=p.PersonKey from Person p
inner Join Customer.Vehicle v
on p.personkey=v.personkey
inner join Customer.RegisteredCustomer r
on r.PersonKey=p.Personkey
Where lastname=@lastName
and firstname=@firstName
and Email = @Email
if not exists
(Select LicenseNumber, VehicleMake, VehicleYear
from Customer.Vehicle
Where personkey=@pKey
and LicenseNumber=@licenseNumber
and vehicleMake=@VehicleMake
and VehicleYear=@VehicleYear)
Begin
Begin try
Insert into Customer.vehicle(LicenseNumber,VehicleMake, VehicleYear, Personkey)
Values (@LicenseNumber, @VehicleMake, @VehicleYear, @pKey)
return
End Try
Begin Catch
print 'The license plate already exists'
return
End Catch
end
Else
Begin
print 'Already in the database'
return
end
End
Begin Tran
Begin Try
Insert into Person(Lastname, FirstName)
Values(@lastName, @firstName)
Declare @Personkey int
set @PersonKey=ident_Current('Person')
Insert into Customer.vehicle
(LicenseNumber, VehicleMake, VehicleYear, personKey)
Values(@LicenseNumber, @VehicleMake, @VehicleYear, @PersonKey)
Insert into Customer.RegisteredCustomer
(Email, CustomerPassword, PersonKey)
Values(@Email, @CustomerPassword, @PersonKey)
Commit tran
End try
Begin Catch
Rollback tran
print 'The transaction failed'
print error_message()
end catch
Go
exec usp_AddNewCustomer
@LastName ='Brown',
@FirstName ='Susan',
@LicenseNumber='WEB100' ,
@VehicleMake='Tesla',
@VehicleYear='2013',
@Email='sb@gmail.com',
@CustomerPassword = 'password'
Select * From Customer.Vehicle
--this is a stored procedure for updating customer
--information
--it has a problem if the customer has more than
--one vehicle. I will let you solve that
Go
Create proc usp_UpdateCustomer
@LastName nvarchar(255),
@FirstName nvarchar(255),
@LicenseNumber nvarchar(10),
@VehicleMake nvarchar(255),
@VehicleYear nchar(4),
@Email nvarchar(255),
@CustomerPassword nvarchar(20),
@Personkey int
As
Begin tran
Begin try
Update Person
set LastName=@LastName,
FirstName=@firstName
Where Personkey=@personkey
--count the vehicles see if you are
--updating an existing vehicle
--or adding something entirely new
Update Customer.Vehicle
Set LicenseNumber=@LicenseNumber,
VehicleMake=@VehicleMake,
VehicleYear=@vehicleYear
Where PersonKey = @Personkey
And @licenseNumber=@LicenseNumber
Update Customer.RegisteredCustomer
set Email=@Email,
CustomerPassword=@CustomerPassword
Where personKey=@PersonKey
Commit tran
End Try
Begin Catch
Rollback tran
print 'sorry'
end catch
go
exec usp_UpdateCustomer
@LastName ='Brown-Meyers',
@FirstName ='Susan',
@LicenseNumber='WEB100' ,
@VehicleMake='Tesla',
@VehicleYear='2013',
@Email='brown_meyers@gmail.com',
@CustomerPassword = 'password',
@personkey=74
Select * From Person
Select * From Customer.Vehicle
Select * from Customer.RegisteredCustomer where personkey=74
Wednesday, February 26, 2014
Stored Procedures Winter 2014
Monday, February 24, 2014
First Stored Procedure Example
Variable
Here is the work (mess) we made to show how to use variables
Use Automart --these are the functions and queries we ended with last week Select VehicleServiceID, ServiceName, ServicePrice, DiscountPercent, dbo.fx_Percentages(ServicePrice, DiscountPercent) as [Discount Price], dbo.fx_GetPercent(ServicePrice, TaxPercent) as Tax From Customer.AutoService a inner join Employee.VehicleServiceDetail vsd on a.AutoServiceID=vsd.AutoServiceID Where VehicleServiceID=3 Select VehicleServiceID, Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent)) as SubTotal, Sum(dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Tax, Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent) + dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Total From Customer.AutoService a inner join Employee.VehicleServiceDetail vsd on a.AutoServiceID=vsd.AutoServiceID Where VehicleServiceID=3 Group by VehicleServiceID --this breaks up the above and divides it into variables --it is a bit of a mess and much more work than the other way --but does show the use of variables --declare the variables Declare @Subtotal decimal(10,2) Declare @Tax decimal(10,2) Declare @Total decimal(10,2) --get the subtotal Select @Subtotal=Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent)) From Employee.VehicleServiceDetail sd Inner Join Customer.AutoService a on sd.AutoServiceID=a.AutoServiceID Where VehicleServiceID=3 group by VehicleServiceID --get the tax amount Select @Tax=Sum(dbo.fx_GetPercent(ServicePrice, TaxPercent)) From Employee.VehicleServiceDetail sd Inner Join Customer.AutoService a on sd.AutoServiceID=a.AutoServiceID Where VehicleServiceID=3 Group by vehicleServiceID --get total print 'subtotal ' + Cast(@Subtotal as nvarchar) print 'Tax ' + Cast(@Tax as nvarchar) Select @Total=@subtotal + @Tax Select VehicleServiceID, @Subtotal as SubTotal, @Tax as Tax, @total as Total From Employee.VehicleServiceDetail Where VehicleServiceID=3 Group by VehicleServiceID
Simple Stored Procedure
Here is our first, simple stored procedure
--here is a stored procedure that uses the functions --and queries above and creates a parameter for the --VehicleServiceID. This gives it the flexibility --so you can use it with any Vehicle's service Go Create proc usp_GetReceipt @VehicleServiceID int AS Select VehicleServiceID, ServiceName, ServicePrice, DiscountPercent, dbo.fx_Percentages(ServicePrice, DiscountPercent) as [Discount Price], dbo.fx_GetPercent(ServicePrice, TaxPercent) as Tax From Customer.AutoService a inner join Employee.VehicleServiceDetail vsd on a.AutoServiceID=vsd.AutoServiceID Where VehicleServiceID=@vehicleServiceID Select VehicleServiceID, Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent)) as SubTotal, Sum(dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Tax, Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent) + dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Total From Customer.AutoService a inner join Employee.VehicleServiceDetail vsd on a.AutoServiceID=vsd.AutoServiceID Where VehicleServiceID=@VehicleServiceID Group by VehicleServiceID Go --this is not part of the stored procedure. --these are using the stored procedure --two versions with the same result Execute usp_GetReceipt 4 Exec usp_GetReceipt @VehicleServiceID=7
Thursday, February 20, 2014
Wednesday, February 19, 2014
Home made Functions
--functions
--scalar functions operate on one row at time
--table valued function
--aggregate functions
use automart
go
--here is an a very simple function
Create function fx_Cube
(@number int ) --parameters, provided by the user
returns int --return type for the function note the s
As
Begin -- begin function
Declare @Cube int --declare a variable
Set @Cube = @number * @number * @number
return @cube --value to return
End
Go
--using the function
Select dbo.fx_Cube(37) as Cube
go
--altering the function to change the data type
alter function fx_Cube
(@number money )
returns money
As
Begin
Declare @Cube money
Set @Cube = @number * @number * @number
return @cube
End
Go
---use the changed function
Select ServicePrice, dbo.fx_cube(ServicePrice) as increase
From Customer.AutoService
Go
--this uses an if statement
Create function fx_GetPercent
(@number decimal(10,2), @percent decimal(3,2))
Returns decimal(10,2)
As
Begin
Declare @percentage decimal(10,2)
Set @Percentage = @number * @Percent
Return @Percentage
End
Go
Select ServicePrice, dbo.fx_GetPercent(ServicePrice, .05) Discount,
ServicePrice -dbo.fx_GetPercent(ServicePrice, .05) DiscountedPrice
From Customer.AutoService
Go
--added an if statement
Alter function fx_GetPercent
(@number decimal(10,2), @percent decimal(3,2))
Returns decimal(10,2)
As
Begin --begin function
Declare @percentage decimal(10,2)
if @Percent > 1
Begin --begin if
Set @Percent=@Percent /100
End --end if
Set @Percentage = @number * @Percent
Return @Percentage
End --end function
--- price is the autoservice table
-- in employee service detail discount percent and tax percent
--0's have
Go
Alter function fx_Percentages
(@amount decimal(10,2), @percent decimal(3,2))
returns decimal(10,2)
AS
Begin --begin function
Declare @result decimal(10,2)
if @amount != 0
Begin
Set @result =@Amount-(@amount * @Percent)
End --end if
Else
Begin --begin else
Set @result=@amount
End --end else
return @Result
End --end function
Go
Select * From Employee.VehicleServiceDetail
-- Here are a couple of fairly complex queries to figure out
--the totals for a service
Select VehicleServiceID, ServiceName, ServicePrice, DiscountPercent,
dbo.fx_Percentages(ServicePrice, DiscountPercent) as [Discount Price],
dbo.fx_GetPercent(ServicePrice, TaxPercent) as Tax
From Customer.AutoService a
inner join Employee.VehicleServiceDetail vsd
on a.AutoServiceID=vsd.AutoServiceID
Where VehicleServiceID=3
Select VehicleServiceID,
Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent)) as SubTotal,
Sum(dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Tax,
Sum(dbo.fx_Percentages(ServicePrice, DiscountPercent) +
dbo.fx_GetPercent(ServicePrice, TaxPercent)) as Total
From Customer.AutoService a
inner join Employee.VehicleServiceDetail vsd
on a.AutoServiceID=vsd.AutoServiceID
Where VehicleServiceID=3
Group by VehicleServiceID
Wednesday, February 12, 2014
Indexes and Views
Use MagazineSubscription
--adding a column
Alter table Customer
Add Email Nvarchar(255)
Select * from Customer
--dropping a column
Alter Table Customer
Drop column Email
--drop a foreign key constrain
Alter table MagazineDetail
Drop constraint FK1_MagazineDetails
--use a system table to see foreign keys in current database
Select * from sys.foreign_keys
--create a table to test default
Create table test
(
testID int identity(1,1) primary key,
testState nvarchar(10) default 'finished'
)
--add a column
Alter table test
add testDate date
--insert some records
Insert into test (TestDate) Values (GetDate())
Select * from Test
/**********************************
*Indexes and views
***********************************/
Use Automart
--noclustered is optional
Create nonclustered index ix_LastName on Person(LastName)
Drop index [UQ__Register__A9D105341CAB755D] on Customer.RegisteredCustomer
--uique index
Create unique index ix_Email on Customer.RegisteredCustomer(Email)
--filtered index
Create index ix_filtered on Employee.VehicleService(ServiceDate)
Where ServiceDate > '1/1/2012'
--composite index
Create index ix_service on Employee.vehicleService(ServiceDate, ServiceTime)
Create table testtable
(
testKey int identity,
TestName nvarchar(255) not null,
Constraint PK_TestTable primary key nonclustered(testKey)
)
--clustered index
Create clustered index ix_testname on TestTable(testName)
Insert into testTable(testName)
values('FirstTest'),
('a test'),
('third test')
Insert into testTable(testName)
values('alpha')
Select * from testTable
\--forcing an index
Select LastName, firstName, email, LicenseNumber, VehicleMake, VehicleYear
From Person p with (NoLock, Index(ix_lastName))
inner join customer.RegisteredCustomer rc
on p.Personkey=rc.PersonKey
inner join Customer.Vehicle v
on p.Personkey =v.PersonKey
Where LastName='Smith'
Go --go seperates batches
--views
Create view vw_Customer
As
Select LastName [Last Name]
, firstName [first Name]
, email Email
, LicenseNumber [License Number]
, VehicleMake Make
, VehicleYear [Year]
From Person p
inner join customer.RegisteredCustomer rc
on p.Personkey=rc.PersonKey
inner join Customer.Vehicle v
on p.Personkey =v.PersonKey
go
Select * from vw_customer
--using a view
Select [Last Name], Email from vw_Customer
Where [Last Name] ='Smith'
order by Email
go
Create view vw_simple
As
Select * from Person
Order by LastName
--can't order a view
Go
--altering a view
Alter view vw_customer
As
Select LastName [Last Name]
, firstName [first Name]
, email Email
, LicenseNumber [License Number]
, VehicleMake Make
, VehicleYear [Vehicle Year]
From Person p
inner join customer.RegisteredCustomer rc
on p.Personkey=rc.PersonKey
inner join Customer.Vehicle v
on p.Personkey =v.PersonKey
Monday, February 10, 2014
Creating and altering Tables
Create DataBase PetPals
Use PetPals
Create table Pet
(
PetKey int identity(1,1) primary key,
PetName nvarchar(255) not null,
PetSpecies nvarchar(255) not null,
PetSex nchar(1),
PetCondition nvarchar(255),
PetAge int,
PetDateAdded Date default GetDate()
)
alter table Pet
Add Constraint chk_Sex Check (PetSex in ('F', 'M'))
Insert into Pet(PetName, PetSpecies, PetSex, PetCondition, PetAge)
Values('Skittles','Cat','F', 'Good', 2)
Select * from Pet
Create Table CareTakers
(
CareTakerKey int identity(1,1),
CaretakerName nvarchar(255) not null,
CareTakerStreet nvarchar(255) not null,
CareTakerCity nvarchar(255) default 'Seattle',
careTakerState nchar(2) default 'WA',
CareTakerZip nchar(10) not null,
CareTakerPhone nchar(13),
Constraint PK_CareTakers primary key(CareTakerKey)
)
Create table Services
(
ServiceKey int identity(1,1),
ServiceName Nvarchar(255) not null,
ServicePrice Decimal(10,2) not null
)
Alter table Services
add Constraint PK_Service primary Key (ServiceKey)
Alter table Services
Add Constraint unique_name Unique(ServiceName)
Create Table CareTakerPet
(
CareTakerPetKey int identity(1,1),
PetKey int Foreign key references Pet(PetKey),
CareTakerKey int,
CareTakerPetDate Date not null,
Constraint FK_CareTaker Foreign Key (CareTakerKey)
references CareTakers(CareTakerKey),
Constraint PK_CareTakerPet Primary Key (CareTakerPetKey)
)
Create Table CareTakerPetDetail
(
CareTakerPetKey int,
ServiceKey int,
Constraint PK_CareTakerPetDetail Primary Key (CareTakerPetKey, ServiceKey),
Constraint FK_CareTakerPetKey Foreign Key (CareTakerPetKey)
References CaretakerPet(CareTakerPetKey),
Constraint FK_Service foreign key (ServiceKey)
references Services(ServiceKey)
)
Sunday, February 9, 2014
ADO Data Entities
For this example we will do much the same thing we did for the ADO example for assignment 4, only we will do it with ADO Entities. This will require less coding since the Entities wizards will create classes for all the Tables we add to the designer. We can use the same hash class as in the previous assignment.
First we create a new Empty web site. I will call it "Assignment5Example."
Next I am going to add an App_Code folder and add the existing class "PasswordHash."
To use the ADO Entities we will need to have a Data connection in the Server window. If it is is not open, open the Server window from View. Make a new DataConnection to Automart Database. Use the AutomarLogin we created for Assignment4
It will only show you the tables you have permissions for.
Now Let's add the ADO Data Entites. Right click on the project and select Add NewItem then ADO Data Entity Model. I am naming it "AutomartModel."
Click ADD, then YES when it tells you it needs to place these files in a special folder. Then Choose Generate from Database
Click NEXT, then make sure it has the correct connection. Click YES to include sensitive data and then NEXT
Next you need to select what you are going to add to the designer. Select all the tables under the customer and dbo schemas
Click Finish and it will set up the designer. You may get one or more security warnings. Just click OK.
Now we set up the Web forms. The login form, the registration form and the Welcome will have exactly the same structure as the assignment four example, so I will not go over them here.
I also added the PasscodeGenerator class from the previous assignment. I realized I would need it for the registration.
Let's do the registration code first. We will do this in the page, as there is little gained by separating it into a class. Double click the submit button in design view.
first we will initialize the data entities classes
//initialize the Data Entity Data context
AutomartEntities entites = new AutomartEntities();
Then we initialize the person class, set its properties and add it to the people collection. Next we do the same with Vehicles. The Person, property sets the relation to the person just created above and will insert that person's personkey as a foreign key.
//initialize the person class, set the values
//and add to People (a class that stores persons)
Person p = new Person();
p.FirstName = txtFirstName.Text;
p.LastName = txtLastName.Text;
entites.People.Add(p);
//same for vehicle
vehicle v = new vehicle();
v.LicenseNumber = txtLicense.Text;
v.Person = p;
v.VehicleMake = txtMake.Text;
v.VehicleYear = txtYear.Text;
entites.vehicles.Add(v);
The Registered customer class will take a little more work because we have to get the passcode and hash the password. Once done we save changes and the values are written to the database
PasscodeGenerator pg = new PasscodeGenerator();
int passcode = pg.GetPasscode();
PasswordHash ph = new PasswordHash();
RegisteredCustomer rc = new RegisteredCustomer();
rc.Person = p;
rc.Email = txtEmail.Text;
rc.CustomerPassCode = passcode;
rc.CustomerPassword = txtPassword.Text;
rc.CustomerHashedPassword = ph.HashIt(txtPassword.Text, passcode.ToString());
entites.RegisteredCustomers.Add(rc);
//write to database
entites.SaveChanges();
Now let's turn to the Login. We will create a new Login class. This one will use the entities syntax. So First add a class to the app_code called LoginClass. this class needs to take the user name and password, query the database to retrieve the passcode and then hash the password and code. If they match the existing hash then the user is authenticated. Here is the whole class with comments.
using System; using System.Collections.Generic; using System.Linq; using System.Web; ////// Summary description for LoginClass /// public class LoginClass { string user; string pass; int personkey=0; Byte[] hashed; AutomartEntities ent = new AutomartEntities(); public LoginClass(string userName, string pWord) { user = userName; pass = pWord; } //get the passcode from the database private int GetPassCode() { int passcode = 0; //this is linq syntax for a query var code = from c in ent.RegisteredCustomers where c.Email == user select new { c.PersonKey, c.CustomerPassCode, c.CustomerHashedPassword }; //we loop through the result and assign some values foreach (var v in code) { passcode = (int)v.CustomerPassCode; personkey = (int)v.PersonKey; hashed = (Byte[])v.CustomerHashedPassword; } return passcode; } // this method hashes the password and matches the database hash //to the new hash public int Authenticate() { int passcode = GetPassCode(); PasswordHash ph = new PasswordHash(); Byte[] newHash = ph.HashIt(pass, passcode.ToString()); int pk = 0; if (hashed == newHash) { pk = personkey; } return pk; } }
Finally we need to write some code for the Login button. It really doesn't need to change much from the code we wrote before.
LoginClass lc = new LoginClass(txtUser.Text, txtPassword.Text);
int personKey = lc.Authenticate();
if (personKey != 0)
{
Session["personkey"] = personKey;
Response.Redirect("Welcome.aspx");
}
else
{
lblError.Text = "Invalid login";
}
Now We will try a login
Monday, February 3, 2014
Ident_current function
When you insert into several tables, and when the primary key is an identity (auto number) the Ident_current function can be used to return the identity created by the insert above. In other words, if you insert a person, you will need the new personkey to insert as a foreign key in the vehicle table and the Registered customer table. Here is an example of an insert using the function.
Use Automart
Insert into Person(lastName, FirstName)
Values ('Oil', 'Caster')
Insert into Customer.vehicle (LicenseNumber, VehicleMake, VehicleYear, PersonKey)
values ('xyz123', 'Ford', '2012', ident_current('Person'))
Note that the argument for the Ident_Current function is the name of the table not the column name