SQL - Trigger for auto-incrementing number of signed in people - sql-server

I am having a little bit of trouble with making a trigger in my SQL. I have two tables:
This one
Create table [user]
(
[id_user] Integer Identity(1,1) NOT NULL,
[id_event] Integer NULL,
[name] Nvarchar(15) NOT NULL,
[lastname] Nvarchar(25) NOT NULL,
[email] Nvarchar(50) NOT NULL, UNIQUE ([email]),
[phone] Integer NULL, UNIQUE ([phone]),
[pass] Nvarchar(50) NOT NULL,
[nick] Nvarchar(20) NOT NULL, UNIQUE ([nick]),
Primary Key ([id_user])
)
go
and this one
Create table [event]
(
[id_event] Integer Identity(1,1) NOT NULL,
[id_creator] Integer NOT NULL,
[name] Nvarchar(50) NOT NULL,
[date] Datetime NOT NULL, UNIQUE ([date]),
[city] Nvarchar(50) NOT NULL,
[street] Nvarchar(50) NOT NULL,
[zip] Integer NOT NULL,
[building_number] Integer NOT NULL,
[n_signed_people] Integer Default 0 NOT NULL Constraint [n_signed_people] Check (n_signed_people <= 20),
Primary Key ([id_akce])
)
Now I need a trigger for when I insert a new user with and id_event, or update existing one with one, to take the id_event I inserted, look in the table of events and increment the n_signed_people in a line with a coresponding id_event, until it is 20. When it is 20, it should say that the event is full. I made something like this, it is working when I add a new user with id, but now I need it to stop at 20 and say its full and also I am not sure if it will work, when I'll try to update existing user, by adding an id_event (I assume it was NULL before update).
CREATE TRIGGER TR_userSigning
ON user
AFTER INSERT
AS
BEGIN
DECLARE #idevent int;
IF (SELECT id_event FROM Inserted) IS NOT NULL --if the id_event is not empty
BEGIN
SELECT #idevent=id_event FROM Inserted; --the inserted id_event will be save in a local variable
UPDATE event SET n_signed_people = n_signed_people+1 WHERE #idevent = id_event;
END
END
go

Good evening,
I did notice some issues with your schema. I want to list the fixes I made in order.
1 - Do not use reserved words. Both user and event are reserved.
2 - Name your constraints. You will be glad they are not some random word when you want to drop one.
3 - I added a foreign key to make sure there is integrity in the relationship.
All this work was done in tempdb. Now, lets get to the fun stuff, the trigger.
-- Just playing around
use tempdb;
go
-- attendee table
if object_id('attendees') > 0
drop table attendees
go
create table attendees
(
id int identity (1,1) NOT NULL constraint pk_attendees primary key,
firstname nvarchar(15) NOT NULL,
lastname nvarchar(25) NOT NULL,
email nvarchar(50) NOT NULL constraint uc_email unique,
phone int NULL constraint uc_phone unique,
pass nvarchar(50) NOT NULL,
nick nvarchar(20) NOT NULL constraint uc_nick unique,
event_id int NOT NULL
)
go
-- events table
if object_id('events') > 0
drop table events
go
create table events
(
id int identity (1,1) NOT NULL constraint pk_events primary key,
creator int NOT NULL,
name nvarchar(50) NOT NULL,
planed_date datetime NOT NULL constraint uc_planed_date unique,
street nvarchar(50) NOT NULL,
city nvarchar(50) NOT NULL,
zip nvarchar(9) NOT NULL,
building_num int NOT NULL,
registered int
constraint df_registered default (0) NOT NULL
constraint chk_registered check (registered <= 20),
);
go
-- add some data
insert into events (creator, name, planed_date, street, city, zip, building_num)
values (1, 'new years eve', '20131231 20:00:00', 'Promenade Street', 'Providence', '02908', 99);
-- make sure their is integrity
alter table attendees add constraint [fk_event_id]
foreign key (event_id) references events (id);
I usually add all three options (insert, update, & delete). You coded for insert in the example above. But you did not code for delete.
Also, both the inserted and deleted tables can contain multiple rows. For instance, if two attendees decide to drop out, you want to minus 2 from the table.
-- create the new trigger.
CREATE TRIGGER [dbo].[trg_attendees_cnt] on [dbo].[attendees]
FOR INSERT, UPDATE, DELETE
AS
BEGIN
-- declare local variable
DECLARE #MYMSG VARCHAR(250);
-- nothing to do?
IF (##rowcount = 0) RETURN;
-- do not count rows
SET NOCOUNT ON;
-- deleted data
IF NOT EXISTS (SELECT * FROM inserted)
BEGIN
UPDATE e
SET e.registered = e.registered - c.total
FROM
[dbo].[events] e
INNER JOIN
(SELECT [event_id], count(*) as total
FROM deleted group by [event_id]) c
ON e.id = c.event_id;
RETURN;
END
-- inserted data
ELSE IF NOT EXISTS (SELECT * FROM deleted)
BEGIN
UPDATE e
SET e.registered = e.registered + c.total
FROM
[dbo].[events] e
INNER JOIN
(SELECT [event_id], count(*) as total
FROM inserted group by [event_id]) c
ON e.id = c.event_id;
RETURN;
END;
-- updated data (no counting involved)
END
GO
Like any good programmer, I need to test my work to make sure it is sound.
Lets add 21 new attendees. The check constraint should fire. This only works since the error generated by the UPDATE rollback the insert.
-- Add 21 attendees
declare #var_cnt int = 0;
declare #var_num char(2);
while (#var_cnt < 22)
begin
set #var_num = str(#var_cnt, 2, 0);
insert into attendees (firstname, lastname, email, phone, pass, nick, event_id)
values ('first-' + #var_num,
'last-' + #var_num,
'email-'+ #var_num,
5554400 + (#var_cnt),
'pass-' + #var_num,
'nick-' + #var_num, 1);
set #var_cnt = #var_cnt + 1
end
go
Last but not least, we need to test a DELETE action.
-- Delete the last row
delete from [dbo].[attendees] where id = 20;
go

Related

MS SQL Constraint on a column

I have a table called Products this is how it looks like and I am trying to create a constraint on [IsDefaultProductKey] column, that any time a value is added to it, it needs be an active product key.
CREATE TABLE [dbo].[Products](
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](64) NOT NULL,
[IsActive] [bit] NOT NULL,
[IsDefaultProductKey] [int] NULL,
CONSTRAINT [PK_dbo.Products] PRIMARY KEY CLUSTERED
(
[ProductId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Products] ADD CONSTRAINT [DF_products_IsActive] DEFAULT ((1)) FOR [IsActive]
GO
ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_Products_Product_IsDefaultProductKey] FOREIGN KEY([IsDefaultProductKey])
REFERENCES [dbo].[Products] ([ProductId])
GO
ALTER TABLE [dbo].[Products] CHECK CONSTRAINT [FK_Products_Product_IsDefaultProductKey]
GO
If these are the entries in the table, row 4 should not be allowed to have a value of 1, since 1 is inactive. How can I go about adding a constraint on the table for that
ProductId Name IsActive IsDefaultProductKey
1 Test1 0 NULL
2 Test2 1 NULL
3 Test3 0 2
4 Test4 0 1 (Should not let me do this)
Based on suggestion, I created this UDF. But still not acting 100% the way I want it.. Please suggest.
CREATE TABLE [dbo].[Products]( [ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](64) NOT NULL,
[IsActive] [bit] NOT NULL,
[IsDefaultProductKey] [int] NULL,
)
go
Create FUNCTION dbo.CheckProduct (#IsDefaultProductKey int)
RETURNS int
AS
BEGIN
DECLARE #retval int
SELECT #retval = 0
Select #retval = 1
FROM [Products]
WHERE ProductId = #IsDefaultProductKey and IsActive = 1
RETURN #retval
END;
GO
--Select CheckProduct(1)
ALTER TABLE [Products]
ADD CONSTRAINT chkActiveProduct
CHECK (IsDefaultProductKey = null or dbo.CheckProduct(IsDefaultProductKey) = 1);
go
You can use a CHECK CONSTRAINT that calls a UDF that queries the table to see if the ProductId referenced by IsDefaultProductKey is Active or not.
EDIT:
Since you need the constraint to check both ways, you would create a UDF that has parameters for ProductId, IsActive and IsDefaultProductKey.
Inside the function, if there is a non-NULL value for IsDefaultProductKey, then you need to query the table to see if the row with that ProductId is Active. If not, then the function needs to return false.
ALSO, if the IsActive parameter is passed a value of 0, then you need to check the table to make sure that no row has a IsDefaultProductKey equal to the value of the ProductId parameter. If there is such a row, then the function needs to return false.
But if neither of those cases occur, the function returns true, and in the CHECK CONSTRAINT, you then just test to see if the function returns true.
I did not understand your questions completely. However looks like you want to apply a check constraint based on the value of other column. The issue which I see in your SQL is you are applying a column level constraint, while I think you need to apply a table level constraint. Please see below sample based on my understanding of your question.
CREATE TABLE [dbo].[Products](
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](64) NOT NULL,
[IsActive] [bit] NOT NULL,
[IsDefaultProductKey] [int] NULL,
CONSTRAINT ck_contraint CHECK
(
(IsActive = 1 AND (IsDefaultProductKey>0) )
)
)
I think you need a trigger not a constraint to do this. Something like:
CREATE OR ALTER TRIGGER DefaultNotActive ON [dbo].[Products]
AFTER INSERT, UPDATE
AS
IF EXISTS (SELECT *
FROM [dbo].[Products] p
JOIN inserted AS i
ON p.[ProductId] = i.[IsDefaultProductKey]
WHERE p.[IsActive] = 0
)
BEGIN
RAISERROR ('Default Product is inactive.', 16, 1);
ROLLBACK TRANSACTION;
RETURN
END;
It might need to be more complex if you also need the default product key to exist. Currently this will allow inserts\updates where the default product key is an id that does not have an existing row in the table
Thanks to Tab Allemnan, Here is the solution I found. Works both ways.
Create FUNCTION CheckProduct (#IsDefaultProductKey int, #ProductId int, #IsActive bit)
RETURNS bit
AS
BEGIN
BEGIN
DECLARE #ret bit;
if (#IsDefaultProductKey is not NULL)
begin
SELECT #ret = 1
FROM [Products] p
WHERE p.ProductID = #IsDefaultProductKey
AND p.IsActive = 1;
end
else -- If #IsDefaultProductKey is null
Select #ret = 1
If (#IsActive = 0) -- If Product is made inactive, make sure that its not a defaultkey for any product.
Begin
SELECT #ret = 0
FROM [Products] p
WHERE p.IsDefaultProductKey = #ProductId
End
IF (#ret IS NULL)
SET #ret = 0;
RETURN #ret;
END;
END;
--Select dbo.CheckProduct (2,1,0)
GO
ALTER TABLE [Products]
ADD CONSTRAINT chkActiveProduct
CHECK (dbo.CheckProduct(IsDefaultProductKey,ProductId, IsActive)=1);
go

How can I insert a newly generated IDENTITY value into a related table with other fields?

I have a data table that contains a name and a social security number. I want to insert the name into a table with an identity field, then insert the ssn with that new identity field value into another table.
Below are the tables:
CREATE TABLE [data_table]
(
[name] [varchar](50) NOT NULL,
[ssn] [varchar](9) NOT NULL,
)
CREATE TABLE [entity_key_table]
(
[entity_key] [int] IDENTITY(1000000,1) NOT NULL,
[name] [varchar](50) NOT NULL,
)
CREATE TABLE [entity_identifier_table]
(
[entity_identifier_key] [int] IDENTITY(1000000,1) NOT NULL,
[entity_key] [int] NOT NULL,
[ssn] [int] NOT NULL,
)
This query works but doesn't link entity_key in [entity_key_table] TO ssn in [entity_identifier_table]:
INSERT INTO entity_key_table (name)
OUTPUT [INSERTED].[entity_key]
INTO [entity_identifier_table] (entity_key)
SELECT [name]
FROM [data_table]
This is what I want to do, but it doesn't work.
INSERT INTO entity (name)
OUTPUT [INSERTED].[entity_key], [data_table].[ssn]
INTO [entity_identifier] (entity_key,ssn)
SELECT [name]
FROM [data_table]
Rewriting my answer based on your requirements and the articles you linked. I think you can get that behavior doing something like this. I admit, I have never seen a merge on something like 1 != 1 like the article suggests, so I would be very cautious with this and test the bajeezes out out of it.
FWIW, it looks like during an INSERT, you can't access data that's not in the inserted virtual table, but updates (and apparently MERGE statements) can.
if object_id('tempdb.dbo.#data_table') is not null drop table #data_table
create table #data_table
(
[name] [varchar](50) NOT NULL,
[ssn] [varchar](9) NOT NULL,
)
if object_id('tempdb.dbo.#entity_key_table') is not null drop table #entity_key_table
create table #entity_key_table
(
[entity_key] [int] IDENTITY(1000000,1) NOT NULL,
name varchar(50)
)
if object_id('tempdb.dbo.#entity_identifier_table') is not null drop table #entity_identifier_table
create table #entity_identifier_table
(
[entity_identifier_key] [int] IDENTITY(2000000,1) NOT NULL,
[entity_key] [int] NOT NULL,
[ssn] varchar(9) NOT NULL,
)
insert into #Data_table (Name, SSN)
select 'John', '123456789' union all
select 'John', '001100110' union all
select 'Jill', '987654321'
merge into #entity_key_table t
using #data_table s
on 1 != 1
when not matched then insert
(
name
)
values
(
s.name
)
output inserted.entity_key, s.ssn
into #entity_identifier_table
(
entity_key,
ssn
);
select top 1000 *
from #data_table
select top 1000 *
from #entity_key_table
select top 1000 *
from #entity_identifier_table
The problem with your code is that you output data only from inserted or deleted.
Assuming your name column only relates to one SSN, the following would work:
DECLARE #output TABLE (entity_key INT,ssn VARCHAR (11))
INSERT INTO entity (entity_key, name)
OUTPUT [INSERTED].[entity_key], [inserted].[name]
INTO #output
SELECT D.Entity_key, d.name
FROM datatable
INSERT INTO entity_identifier (entity_key, ssn)
Select o.entity_key, d.snn
from #output o
join datatable d on o.name = d.name
However, the problem of multiple duplicated names having different Social Security Numbers is extremely high. In this case, your current structure simply does not work because there is no way to know which identity belongs to which name record. (The Merge solution in another post may also have this problem, before you put that to production be sure to test the scenario of duplicated names. The chances of duplicated names in a set of records is extremely high in any reasonable large data set of names and this should be one of your unit test for any potential solution.)
Here is a potential workaround. First, insert the SSN as the name in the first insert, then return output as shown but join on the #output Name column to the SSN column. After doing the other insert, then update the name in the orginal table to the correct name again joining on the SSN data.
DECLARE #output TABLE (entity_key INT,ssn VARCHAR (11))
INSERT INTO entity (entity_key, name)
OUTPUT [INSERTED].[entity_key], [inserted].[ssn]
INTO #output
SELECT D.Entity_key, d.name
FROM datatable
INSERT INTO entity_identifier (entity_key, ssn)
Select o.entity_key, d.output
from #output o
update e
set name = d.name
FROM entity e
join #output o on e.entity_key = o.entity_key
join datatable d on o.name = d.ssn

creating before INSERT TRIGGER comparing values between two tables

I need help creating a before insert trigger, as i am new to TSQL. below are the two tables.
SALARY table:
CREATE TABLE SALARY
(
StarName varchar(30) NOT NULL,
MovieTitle varchar(30)NOT NULL,
MovieYearMade numeric(4, 0) NOT NULL,
Amount numeric(8, 0) NULL,
PRIMARY KEY (MovieTitle,StarName,MovieYearMade),
)
MOVIESTAR table
CREATE TABLE MOVIESTAR
(
Name varchar(30) NOT NULL,
Address varchar(20),
City varchar(15) DEFAULT ('Palm Springs'),
Gender char(1) NULL CHECK (Gender ='M' OR GENDER ='F'),
BirthYear Numeric(4),
PRIMARY KEY CLUSTERED (Name)
)
I want to create a trigger so when a new movie is added. It prevents adding SALARY.Amount if SALARY.MovieYearMade is before MOVIESTAR.BirthYear.
I am confused as how to define trigger, when I am comparing values in two tables i.e. SALARY and MOVIESTAR.
thanks,
Are you looking for something like this?
CREATE TRIGGER tg_salary ON salary
INSTEAD OF INSERT AS
BEGIN
INSERT INTO salary (StarName, MovieTitle, MovieYearMade, Amount)
SELECT i.StarName, i.MovieTitle, i.MovieYearMade,
CASE WHEN i.MovieYearMade < s.BirthYear THEN NULL ELSE i.Amount END
FROM INSERTED i JOIN moviestar s
ON i.StarName = s.Name
END
Here is SQLFiddle demo

Update timestamp column when Foreign table updates without Trigger

I'm trying to setup a Timestamp/Rowversion on a Parent table so that when the Child table updates, the Timestamp on the Parent table row changes.
I don't need to know about the row in the Child table, just that according to the parent this particular row has changed.
USE [Test]
GO
CREATE TABLE [dbo].[Clerk](
[ID] [int] NOT NULL,
[Name] [varchar](20) NOT NULL,
[lastUpdate] [timestamp] NOT NULL,
CONSTRAINT [PK_Clerk] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
CREATE TABLE [dbo].[ClerkAddress](
[ClerkID] [int] NOT NULL,
[Address] [varchar](40) NOT NULL,
CONSTRAINT [PK_ClerkAddress] PRIMARY KEY CLUSTERED
(
[ClerkID] ASC
)
ALTER TABLE [dbo].[ClerkAddress] WITH CHECK ADD CONSTRAINT [FK_ClerkAddress_Clerk] FOREIGN KEY([ClerkID])
REFERENCES [dbo].[Clerk] ([ID])
ON UPDATE CASCADE
insert into Clerk (ID, Name) values (1, 'Test1')
insert into Clerk (id, Name) values (2, 'Test2')
insert into ClerkAddress (ClerkID, Address) values (1, 'address1')
insert into ClerkAddress (ClerkID, Address) values (2, 'address2')
using the following code examples.
update ClerkAddress set Address = NEWID() where ClerkID = 2
--no change to Clerk when address changes
select * from Clerk
select * from ClerkAddress
--Of course these update the lastUpdate in clerk
update Clerk set Name = 'test2' where ID = 2
update Clerk set Name = name
Is this even possible or do I need to make triggers for the updates? (update clerk set name = name where id = ClerkID)
You can make it appear as though the parent row is updated with a view.
You need to add a rowversion column to ClerkAddress, then
CREATE VIEW dbo.Clerk2
WITH SCHEMABINDING -- works for me on SQL Server 2012
AS
SELECT
C.ID, C.Name, ISNULL(MAX(CA.lastUpdate), C.lastUpdate) AS lastupdate
FROM
[dbo].[Clerk] C
LEFT JOIN
[dbo].[ClerkAddress] CA ON C.ID = CA.ClerkID
GROUP BY
C.ID, C.Name, C.lastUpdate
GO
SELECT * FROM dbo.Clerk2;
GO
update ClerkAddress set Address = NEWID() where ClerkID = 2;
GO
SELECT * FROM dbo.Clerk2;
GO
update ClerkAddress set Address = NEWID() where ClerkID = 2;
GO
SELECT * FROM dbo.Clerk2;
GO
This uses the highest value from rowversion yet preserves the actual rowversion on Clerk (which can still be used for optimistic concurrency by the client)
This works because rowversion is database unique

What is the proper procedure when trying to test your database in SQL?

I'm pretty new to databases and I have this assignment that I've completed where I had to look at a merged Entity Relationship Diagram and then create Drop Tables, Tables (with constraints and identity's), Alterations and Indexes. I'm pretty sure I've coded everything correctly but the only area I'm a little unsure about, it's how to test that the database will actually function when executing it. My instructor gave me a TestData.sql file that I just have to refer to the database and then execute and it should insert all the data into the tables and drop everything correctly. I have it all hooked up properly on SQL Server Management Studio but I forget what steps I should be taking in order to test the proper execution of the tables. I'll post some of my code so you guys can take a look. Any information regarding this issue would be greatly appreciated!
Also, when it says in the Test Data SQL code "IMPORTANT! If you need to run this script more than once you must drop and recreate your tables first to reset the identity properties." --Does this mean that if I run into any errors while trying to execute the test data, I will have to execute the DROP TABLES first and then maybe copy and paste all the TABLES back into the Database file? I don't actually have to manually type all the TABLES again, just need to re-enter them as "new" so the system will kind of reset it's identity properties?
If you guys need me to post more of the code for clarification, just let me know. Thanks for taking the time to read this :)
Update: I'm getting 2 error messages when trying to execute the TestData script: "Invalid object name 'SaleDetail'." and "Invalid object name 'Author'." I've also provided the rest of the code from my Database script file for you to take a look at. I'm almost certain everything is correct.
Database Tables Code (this is the complete code script)
USE Lab2A_BooksGalore
GO
/*------ Drop Table Statements ------*/
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'SaleDetail')
DROP TABLE SaleDetail
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'AuthorTitle')
DROP TABLE AuthorTitle
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Title')
DROP TABLE Title
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Publisher')
DROP TABLE Publisher
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Category')
DROP TABLE Category
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Author')
DROP TABLE Author
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Sale')
DROP TABLE Sale
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Employee')
DROP TABLE Employee
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Customer')
DROP TABLE Customer
/*------- Create Table Statements -------*/
CREATE TABLE Customer
(
CustomerNumber int
CONSTRAINT PK_Customer_CustomerNumber
PRIMARY KEY
IDENTITY (1, 1) NOT NULL,
LastName varchar(30) NOT NULL,
FirstName varchar(30) NOT NULL,
[Address] varchar(40) NULL,
City varchar(30) NULL,
Province char(2)
CONSTRAINT DF_Customer_Province
DEFAULT ('AB') NULL,
PostalCode char(6)
CONSTRAINT CK_Customer_PostalCode
CHECK (PostalCode LIKE '[A-Z][0-9][A-Z][0-9][A-Z][0-9]')
NULL,
HomePhone char(10)
)
CREATE TABLE Employee
(
EmployeeNumber int
CONSTRAINT PK_Employee_EmployeeNumber
PRIMARY KEY
IDENTITY (300, 1) NOT NULL,
[SIN] char(9) NOT NULL,
LastName varchar(30) NOT NULL,
FirstName varchar(30) NOT NULL,
[Address] varchar(40) NULL,
City varchar(20) NULL,
Province char(2)
CONSTRAINT DF_Employee_Province
DEFAULT ('AB') NULL,
PostalCode char(6)
CONSTRAINT CK_Employee_PostalCode
CHECK (PostalCode LIKE '[A-Z][0-9][A-Z][0-9][A-Z][0-9]')
NULL,
HomePhone char(10) NULL,
WorkPhone char(10) NULL,
Email varchar(40) NULL,
)
CREATE TABLE Sale
(
SaleNumber int
CONSTRAINT PK_Sale_SaleNumber
PRIMARY KEY
IDENTITY (3000, 1) NOT NULL,
SaleDate datetime NOT NULL,
CustomerNumber int
CONSTRAINT FK_Sale_CustomerNumber_Customer_CustomerNumber
FOREIGN KEY REFERENCES Customer(CustomerNumber)
NOT NULL,
EmployeeNumber int
CONSTRAINT FK_Sale_EmployeeNumber_Employee_EmployeeNumber
FOREIGN KEY REFERENCES Employee(EmployeeNumber)
NOT NULL,
Subtotal money
CONSTRAINT CK_Sale_Subtotal
CHECK (Subtotal <= Total) NOT NULL,
GST money NOT NULL,
Total money
CONSTRAINT CK_Sale_Total
CHECK (Total >= Subtotal) NOT NULL,
)
CREATE TABLE Author
(
AuthorCode int
CONSTRAINT PK_Author_AuthorCode
PRIMARY KEY
IDENTITY (100, 1) NOT NULL,
LastName varchar(30) NOT NULL,
FirstName varchar(30) NOT NULL,
)
CREATE TABLE Category
(
CategoryCode int
CONSTRAINT PK_Category_CategoryCode
PRIMARY KEY
IDENTITY (1, 1) NOT NULL,
[Description] varchar(40) NOT NULL,
)
CREATE TABLE Publisher
(
PublisherCode int
CONSTRAINT PK_Publisher_PublisherCode
PRIMARY KEY
IDENTITY (200, 1) NOT NULL,
[Name] varchar(40) NOT NULL,
)
CREATE TABLE Title
(
ISBN char(10)
CONSTRAINT PK_Title_ISBN
PRIMARY KEY NOT NULL,
Title varchar(40) NOT NULL,
SuggestedPrice smallmoney
CONSTRAINT DF_Title_SuggestedPrice
DEFAULT (0) NOT NULL,
NumberInStock smallint
CONSTRAINT CK_Title_NumberInStock
CHECK (NumberInStock >= 0)
CONSTRAINT DF_Title_NumberInStock
DEFAULT (0) NOT NULL,
PublisherCode int
CONSTRAINT FK_Title_PublisherCode_Publisher_PublisherCode
FOREIGN KEY REFERENCES Publisher(PublisherCode)
NOT NULL,
CategoryCode int
CONSTRAINT FK_Title_CategoryCode_Category_CategoryCode
FOREIGN KEY REFERENCES Category(CategoryCode)
NOT NULL,
)
CREATE TABLE AuthorTitle
(
ISBN char(10)
CONSTRAINT FK_AuthorTitle_ISBN_Title_ISBN
FOREIGN KEY REFERENCES Title(ISBN)
NOT NULL,
AuthorCode int
CONSTRAINT FK_AuthorTitle_AuthorCode_Author_AuthorCode
FOREIGN KEY REFERENCES Author(AuthorCode)
NOT NULL,
)
CREATE TABLE SaleDetail
(
SaleNumber int
CONSTRAINT FK_SaleDetail_SaleNumber_Sale_SaleNumber
FOREIGN KEY REFERENCES Sale(SaleNumber)
NOT NULL,
ISBN char(10)
CONSTRAINT FK_SaleDetail_ISBN_Title_ISBN
FOREIGN KEY REFERENCES Title(ISBN)
NOT NULL,
SellingPrice money NOT NULL,
Quantity int NOT NULL,
Amount money NOT NULL,
)
/*----------------- Alter Table Statements --------------------*/
---1) Add a char(10) attribute named WorkPhone to the Customer Table
ALTER TABLE Customer
ADD WorkPhone char(10) NULL
GO
---2) Add a varchar(30) attribute named Email to the Customer Table
ALTER TABLE Customer
ADD Email varchar(30) NULL
GO
---3) Add a constraint to make sure the correct format is followed for the Email attribute
ALTER TABLE Customer
ADD CONSTRAINT CK_Customer_Email
CHECK (Email LIKE '[a-z, 0-9][a-z, 0-9][a-z, 0-9]%#[a-z, 0-9][a-z, 0-9][a-z, 0-9]%.[a-z, 0-9][a-z, 0-9]%')
--- Match For: b 8 l # g v t . c a
GO
---4) Add a char(1) attribute named Active that's required for the Employee Table
ALTER TABLE Employee
ADD Active char(1) NOT NULL
GO
---5) Add a constraint to make sure the default character is used for the Active attribute
ALTER TABLE Employee
ADD CONSTRAINT DF_Employee_Active
DEFAULT ('y')
GO
/*------------------ Foreign Key Index Statements -----------------*/
CREATE NONCLUSTERED INDEX IX_Sale_CustomerNumber
ON Sale (CustomerNumber)
CREATE NONCLUSTERED INDEX IX_Sale_EmployeeNumber
ON Sale (EmployeeNumber)
CREATE NONCLUSTERED INDEX IX_Title_PublisherCode
ON Title (PublisherCode)
CREATE NONCLUSTERED INDEX IX_Title_CategoryCody
ON Title (CategoryCode)
CREATE NONCLUSTERED INDEX IX_AuthorTitle_ISBN
ON AuthorTitle (ISBN)
CREATE NONCLUSTERED INDEX IX_AuthorTitle_AuthorCode
ON AuthorTitle (AuthorCode)
CREATE NONCLUSTERED INDEX IX_SaleDetail_SaleNumber
ON SaleDetail (SaleNumber)
CREATE NONCLUSTERED INDEX IX_SaleDetail_ISBN
ON SaleDetail (ISBN)
GO
Test Data Code(this is only a snippet being this script is 100% accurate - provided by instructor)
USE Lab2A_BooksGalore
GO
--Lab 2 insert script
--IMPORTANT! If you need to run this script more than once you must drop and recreate your tables first to reset the identity properties.
--Delete existing data in the tables, if there is any
Delete From SaleDetail
Delete From Sale
Delete From AuthorTitle
Delete From Title
Delete From Employee
Delete From Customer
Delete From Category
Delete From Publisher
Delete From Author
Go
Insert into Author
(LastName, FirstName)
Values
('Smith', 'Sammy'),
('Greens', 'George'),
('Jones', 'Johnny'),
('Davidson', 'David'),
('Robertson', 'Rob'),
('Abbots', 'Abe'),
('Bakers', 'Bob'),
('Caters', 'Clem'),
('Semenko', 'Dave'),
('Franky', 'Fran'),
('Horton', 'Harry'),
('Kelly', 'Kevin'),
('Lambert', 'Larry'),
('Johnson', 'Jon'),
('Anderson', 'Ander'),
('Peterson', 'Peter'),
('Jensen', 'Jens'),
('Issacsen', 'Issac')
Insert into Publisher
(Name)
Values
('Addison Westley'),
('SAMS'),
('Harlequin'),
('Self Publish Inc'),
('Microsoft Press'),
('Jones and Bartlett'),
('WROX'),
('West'),
('Premier')
Insert into Category
(Description)
Values
('Computers'),
('Business'),
('Human Relation'),
('Electronics'),
('Designs'),
('Miscellaneous'),
('Media Design'),
('Information Technologies')

Resources