445 Consulting Database

Fully functional relational database design for a fictional consulting company. Includes multiple stored procedures, business rules, views, and calculated columns. Built using SQL Server.


database ERD

Who it was built for

As a final project for INFO 445, Advanced Database Design, I was tasked with building a fully functional and complex database. This database was built to fulfill the needs of a fictional consulting company (445 Consulting).

The database tracks projects (including tasks, skills, and assigned employees), as well as client companies, and employees (with their positions, wages, and skills). This allows the consulting company to easily track its projects, employees, and clients, making the most of their resources.

This database is fully normalized, with no data redundancy or possibility for ‘infinite loops’. The final submission included several Stored Procedures for insertion of complex data (such as assigning an employee to a project with specific tasks). The DB also includes several business rules that automatically send out alerts after certain actions are flagged, such as redundant skills being added for an employee, or an employee being assigned to too many active projects

Example Code Snippets:

Stored Procedure

Add a salary history (a salary the employee was paid at one point)

CREATE PROC uspAddSalaryHistory
@Fname varchar(100),
@Lname varchar(100),
@DOB DATE,
@Position varchar(100),
@Company varchar(100),
@Amount MONEY,
@BeginDate DATE,
@EndDate DATE
AS
DECLARE @PositionID INT
DECLARE @CompanyID INT
DECLARE @EmpID INT
DECLARE @EmpHistoryID INT

BEGIN
SET @PositionID = (
	SELECT PositionID FROM [POSITION]
	WHERE PositionName = @Position
)
IF @PositionID IS NULL
	RAISERROR('Position name not valid', 12, 1)
SET @CompanyID = (
	SELECT CompanyID FROM [COMPANY]
	WHERE CompanyName = @Company
)
IF @CompanyID IS NULL
	RAISERROR('Company name not valid', 12, 1)
SET @EmpID = (
	SELECT EmployeeID FROM [EMPLOYEE]
	WHERE FName = @Fname
	AND LName = @Lname
	AND DOB = @DOB
)
IF @CompanyID IS NULL
	RAISERROR('Personal info not valid', 12, 1)
SET @EmpHistoryID = (
	SELECT EmploymentHistoryID FROM [EMPLOYMENT_HISTORY]
	WHERE EmployeeID = @EmpID
	AND PositionID = @PositionID
	AND CompanyID = @CompanyID
)
IF @EmpHistoryID IS NULL
	RAISERROR('Data mismatch (person not found to have that job at that company)', 12, 1)

BEGIN TRAN TranNewSalaryHistory
	INSERT INTO [SALARY_HISTORY]([EmploymentHistoryID], BeginDate, EndDate, Amount)
	VALUES (@EmpHistoryID, @BeginDate, @EndDate, @Amount)
	IF @@Error <> 0
		ROLLBACK TRAN TranNewSalaryHistory
	ELSE
		COMMIT TRAN TranNewSalaryHistory
END

Check Constraint

Employees can’t have two instances of the same skill

CREATE FUNCTION fn_LimitEmployeeSkillDuplicates()
RETURNS INT
AS
BEGIN
DECLARE @RET INT = 0
IF EXISTS (SELECT COUNT(*), SE.EmployeeID, SE.SkillID FROM SKILL_EMPLOYEE SE
	GROUP BY SE.SkillID, SE.EmployeeID
	HAVING COUNT(*) > 1)
		SET @RET = 1
RETURN @RET
END
GO

ALTER TABLE SKILL_EMPLOYEE WITH NOCHECK
ADD CONSTRAINT ck_LimitEmployeeSkillDuplicates
CHECK (dbo.fn_LimitEmployeeSkillDuplicates() = 0)

Computed Column

Number of employees assigned to a project

CREATE FUNCTION dbo.getNumProjectEmployees(@ProjectID int)
RETURNS int
AS
BEGIN
    DECLARE @RET int
    SELECT @RET = COUNT(*) FROM PROJECT_EMPLOYEE PE WHERE PE.ProjectID = @ProjectID
    RETURN @RET
END

ALTER TABLE PROJECT ADD NumEmployeesAssigned AS (dbo.getNumProjectEmployees(ProjectID))

View: Project tasks

Artificial table with description of task & assigned employee

CREATE VIEW taskView
AS
SELECT p.ProjectName AS 'Project Name', p.ProjectDescription AS 'Project Description', e.FullName AS 'Employee Name', t.TaskName AS 'Task Name', t.TaskDesc AS 'Task Description'
FROM TASK t
JOIN PROJECT_EMPLOYEE pe ON t.ProjectEmployeeID = pe.ProjectEmployeeID
JOIN EMPLOYEE e ON pe.EmployeeID = e.EmployeeID
JOIN PROJECT p ON pe.ProjectID = p.ProjectID
GO