SlideShare une entreprise Scribd logo
1  sur  12
Project 01: Transact SQL

Objective
Write several simple to complex data retrieval queries that involve self joins, correlated sub queries, and parameter insertions.

Sample Scenarios and Queries
Query #1

The Available Books page is a report listing the publishers and the books they offer. Output a list of publishers, the books they
publish and each book’s ISBN. Ensure the output lists the Publishers in alphabetical order and the titles in alphabetical order.

--Very basic query
USE junglebooks

SELECT publisher, title, isbn
FROM books
ORDER BY publisher, title
GO


Query # 2

The Range of Customers form allows the user to view orders placed within a given range of customer IDs. The user enters 6 in the
txtIDStart form field and 15 in txtIDEnd form field. Display all columns of data in order by Customer ID. Alias the columns in the
result set as: ‘Order #’, ‘Cust ID’, ‘Ordered’.

--Query with parameters
USE junglebooks

DECLARE @txtIDStart int, @txtIDEnd int
SET @txtIDStart = 6
SET @txtIDEnd = 15

SELECT orderID AS Order#, customerID AS [Cust ID], OrderDate AS Ordered
      FROM orders
      WHERE customerID BETWEEN @txtIDStart AND @txtIDEnd
ORDER BY customerID
GO


Query #3

The Large Orders page is a report displaying the largest number of items sold per order. Display the Order ID, Customer ID and
Name along with the total number of items they ordered. Display the record with the largest quantity first. Alias as: “Order ID’, ‘Cust
ID’, ‘Customer’ and ‘# of items’.

--Query with JOINS

USE junglebooks

SELECT o.OrderID AS [Order ID], c.CustomerID AS [Cust ID], c.Name AS [Name},
SUM(quantityordered) AS [# of items]
   FROM orders AS o JOIN customers AS c
       ON o.customerID = c.customerID
       JOIN orderitems AS oi
       ON o.orderID = oi.orderID
GROUP BY o.orderID, c.customerID, c.Name
ORDER BY SUM(quantityordered) DESC
GO


Query #4

The Search For Authors page also allows the user to search for Authors with a last name starting with a particular letter. The user
inputs ‘B’ in the txtLastName form field. Display AuthorID and Name in order by name. Make the assumption that any compound
names are hyphenated (i.e.: Billy-Bob Hicks or Susan Smith-Anderson). Alias as: ‘ID’, ‘Name’.

--Query with parameters and wild card

USE junglebooks

DECLARE @txtLastName varchar(80)
SET @txtLastName = '% B%'
SELECT AuthorID AS ID, Name
   FROM Authors
WHERE Name LIKE @txtLastName
ORDER BY Name
GO
Query #5

Write and execute a query that returns the member_no, full name, out_date, due_date, and title columns from the Loan, Member,
and Title tables. Convert the datetime values from the out_date and due_date columns to char(12), format 101. Restrict the results
to books which were due prior to the current date. Load the records into a temporary table called #overdue. Leave the query
window open after you create the temporary table.


--Query data to temporary table

USE library
SELECT m.member_no, (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name,
CONVERT (char(12), l.out_date, 101) AS out_date,
CONVERT (char(12), l.due_date, 101) AS due_date , t.title
INTO #overdue
FROM member AS m JOIN loan AS l
 ON m.member_no = l.member_no
 JOIN title AS t
 ON t.title_no = l.title_no
WHERE due_date < CURRENT_TIMESTAMP
GO

Query #6

Using joins and a UNION clause, write a query to retrieve a single list of members both adult and juvenile, who have reserved ISBN
number 288. The list must include the ISBN, title, member_no and name (i.e.: Smith, John) of each member who has the
reservation. Additionally, the list should indicate whether the member is an adult or a juvenile. Output the records by name.

--Query with UNION clause

USE library
SELECT (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name , m.member_no, r.isbn, title,
'adult' AS [adult or juvenile]
FROM member AS m JOIN adult AS a
 ON m.member_no = a.member_no
 JOIN reservation AS r
 ON a.member_no = r.member_no
 JOIN item AS it
 ON r.isbn = it.isbn
 JOIN title AS t
 ON t.title_no = it.title_no
WHERE r.isbn = 288
UNION
SELECT (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name, m.member_no, r.isbn, title,
'juvenile' AS [adult or juvenile]
FROM member AS m JOIN juvenile AS j
 ON m.member_no = j.member_no
 JOIN reservation AS r
 ON r.member_no = j.member_no
 JOIN item AS it
 ON r.isbn = it.isbn
 JOIN title AS t
 ON t.title_no = it.title_no
WHERE r.isbn = 288
ORDER BY name
GO

Query #7

Using CASE statement, write a query to retrieve a single list of members both adult and juvenile, who have reserved ISBN number
288. You cannot JOIN to the Adult or Juvenile tables. The list must include the ISBN, title, member_no and name (i.e.: Smith, John)
of each member who has the reservation. Additionally, the list should indicate whether the member is an adult or a juvenile. Output
the records by name.

--Query invloving a subquery

SELECT r.isbn AS Isbn, t.title AS Title
, m.member_no AS Member_no
, m.lastname + ', ' + m.firstname AS name
, Category = (CASE WHEN (SELECT a.member_no FROM dbo.adult AS a
                   WHERE a.member_no = m.member_no) = m.member_no
                   THEN 'adult'
                     ELSE
                   WHEN (SELECT j.member_no FROM dbo.juvenile AS j
                   WHERE j.member_no = m.member_no) = m.member_no
                   THEN 'juvenile' END)

FROM dbo.reservation AS r JOIN dbo.member AS m
 ON r.member_no = m.member_no
 JOIN dbo.item AS i
 ON i.isbn = r.isbn
 JOIN dbo.title AS t
 ON t.title_no = i.title_no
WHERE r.isbn = 288
ORDER BY name
GO
Project 02: XML

Objective
Create XML queries involving FOR XML, and XQuery to retrieve order delivery details.


XML Query Samples
Sample 1:

Create two FOR XML queries to return the order manifest documents.

--Attribute-centric XML
USE Northwind
SELECT OrderID, OrderDate, CustomerID,
      (SELECT ProductID, Quantity AS OrderQty
      FROM [Order Details]
      WHERE orders.orderID = [Order Details].orderID
      FOR XML RAW ('Details'),TYPE)

FROM Orders
FOR XML RAW ('Order'), ROOT ('Orders')

--Mixture of element-centric and attribute-centric XML
USE Northwind
SELECT OrderID, OrderDate, CustomerID,
      (SELECT ProductID, Quantity AS OrderQty
      FROM [Order Details]
      WHERE orders.orderID = [Order Details].orderID
      FOR XML RAW ('Item'), ELEMENTS, TYPE)
FROM Orders
FOR XML RAW ('SalesOrder')

Sample 2:

We have a reporting application that the marketing analysts use to analyze product sales. This Application needs data in XML
Format where the parent node is the city and its children are the list of products with Product ID, UnitPrice sold, Discount provided,
and Quantity Sold. Create a FORXML Query to return this document. Include all product sales data available.

USE Northwind
SELECT ShipCity,
      (SELECT ProductID, UnitPrice, Discount, Quantity
      FROM [Order Details]
      WHERE orders.orderID = [Order Details].orderID
      FOR XML RAW ('Details'), TYPE)
FROM Orders
FOR XML RAW ('Sale')

Sample 3:

For each order that Northwind Traders receives, the goods are delivered by a delivery driver. These drivers are going to utilize
delivery lists that you are going to implement now. Using SSMS, create a dbo.DeliverySchedule table containing a Delivery ID,
Schedule date, Delivery Route, Delivery Driver, and Delivery List column.

Populate (“insert” via the starter script provided) the dbo.DeliverySchedule table with test data as follows:

   •   ScheduleDate is GetDate()
   •   DeliveryRoute is 3
   •   DeliveryDriver is James
   •   DeliveryList is the delivery list XML document (copy and paste from deliverylist.xml)
   •   DeliveryID can auto-increment via an identity property and does not need to be inserted.

Verify that this data has been stored in the dbo.DeliverySchedule table.

USE Northwind
GO


-- Drop Statement for when the table is already in the database
IF EXISTS(SELECT * FROM sys.tables
              WHERE name='DeliverySchedule'
            AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name = 'dbo'))
BEGIN
  DROP TABLE dbo.DeliverySchedule
END

--Create a table for delivery schedule
CREATE TABLE dbo.DeliverySchedule
(ScheduleID int IDENTITY PRIMARY KEY,
 ScheduleDate Datetime,
 DeliveryRoute int,
 DeliveryDriver nvarchar(20),
 DeliveryList xml)

--Insert XML
INSERT INTO DeliverySchedule
VALUES
(GetDate(), 3, 'James', '<?xml version="1.0" ?>
<DeliveryList>
                                                <Delivery OrderID="10296">
                                                    <CustomerName>Carlos González</CustomerName>
                                                    <Address>Carrera 52 con Ave. Bolívar #65-98 Llano Largo
         Barquisimeto          Lara    3508   Venezuela</Address>
                                                </Delivery>
                                                <Delivery OrderID="10310">
                                                    <CustomerName>Liz Nixon</CustomerName>
                                                    <Address>89 Jefferson Way Suite 2 Portland </Address>
                                                </Delivery>
                                              </DeliveryList>')

--Insert Completed
SELECT * FROM dbo.DeliverySchedule


Sample 4:
Use XQuery expressions to retrieve and modify delivery schedule data

Tasks:

Retrieve the delivery elements
Retrieve the address for the first delivery
Find the driver for an order
Update a delivery address
Verify new delivery address

--Retrieve the delivery elements
USE Northwind
SELECT ScheduleID, ScheduleDate, DeliveryRoute, DeliveryDriver,
DeliveryList.query('/DeliveryList/Delivery')DeliveryList
FROM DeliverySchedule


--Retrieve the address for the first delivery
USE Northwind
SELECT DeliveryList.value('(/DeliveryList/Delivery/@Address)[1]', 'nvarchar(100)') [Delivery Address]
FROM DeliverySchedule
WHERE ScheduleID = 1

--Find the driver for an order
SELECT DeliveryDriver
FROM DeliverySchedule
WHERE DeliveryList.exist
      ('/DeliveryList/Delivery[@OrderID=10296]') = 1

--Find the driver for an order
UPDATE DeliverySchedule
SET DeliveryList.modify
  ('replace value of (/DeliveryList/Delivery/@Address)[1]
  with "2000 Park Place, Portland"')
WHERE ScheduleID = 1

--Verify change delivery address
SELECT DeliveryList.value
      ('(/DeliveryList/Delivery/Address)[1]', 'nvarchar(100)')[Delivery Address]
FROM DeliverySchedule
WHERE ScheduleID = 1
Project 03: Stored Procedures

Objective
Create stored procedures to the support the following principal functions of a library’s day-to-day operations: adding new members
(adult and juvenile) and checking books in and out, adding new books, renewing memberships, changing a juvenile record into an
adult record after a customer has reached 18.

Requirements
   •     Design and develop back end stored procedures that satisfy these functionalities: Add Adult, Add Juvenile, Check In a book,
         Check Out a book, Add Book, Renew Membership, Change Juvenile to Adult, Update Adult.
   •     Provide input validations (against null and whitespace values as outlined).
   •     Provide adequate error handling.
   •     Produce a build script and two test scripts that are intuitively designed to indicate to the grader that the intended functionality
         works. These should require a minimum of effort to execute. The test scripts must test all required functionality: one should
         hold all test cases intended to succeed and the second script should hold all the failures-> i.e.

Sample Stored Procedures

Add Adult Member
--Default values are set to NULL to allow execution despite missing inputs.

ALTER PROCEDURE [dbo].[sp_AddAdultMember]
       @street varchar(15) = NULL
      ,@city varchar(15) = NULL
      ,@state char(2) = NULL
      ,@zip char(10) = NULL
      ,@phone_no char(13) = NULL
      ,@lastname varchar(15) = NULL
      ,@firstname varchar(15) = NULL
      ,@MemberID int = NULL OUTPUT
AS
BEGIN
    SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements.


--Verify that required params being passed are not NULL and do not contain spaces.

       IF ((@firstname IS NULL OR @firstname = '')
       OR (@lastname IS NULL OR @lastname = '')
       OR (@street IS NULL OR @street = '')
       OR (@city IS NULL OR @city = '')
       OR (@state IS NULL OR @state = '')
       OR (@zip IS NULL OR @zip = ''))
       BEGIN
         RAISERROR('Null values and whitespaces are prohibited. Please enter a valid integer.',16,1)
       RETURN
       END

--If validations met, insert values into member and adult table.
      BEGIN TRY
                BEGIN TRAN --Allows for execute all or rollback
                INSERT   [dbo].[member] ([lastname],[firstname])
                VALUES   (@lastname, @firstname)

                    Set @MemberID = SCOPE_IDENTITY()

                    INSERT      [dbo].[adult]
                                      ([member_no],[street],[city],[state],[zip],[phone_no],[expr_date])
                    VALUES      (@MemberID,@street,@city,@state,@zip,@phone_no,dateadd(year,1,getdate()))

                    COMMIT TRAN
         END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:

         BEGIN CATCH
               ROLLBACK TRAN
               SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
         END CATCH
END
GO
Add Book

--Default values are set to NULL to allow execution despite missing inputs.
ALTER PROCEDURE [dbo].[sp_AddBook]
       @title varchar(63) = NULL,
       @author varchar(31) = NULL,
       @synopsis text = NULL,
       @isbn int = NULL,
       @translation char(8) = NULL,
       @cover char(8) = NULL,
       @copy_no smallint = 1,
       @title_no int = NULL OUTPUT

AS
BEGIN
        SET NOCOUNT ON; --Prevents extra result sets from interfering with SELECT statements.

--Verify that required params being passed are not NULL and do not contain spaces.

        IF ((@title IS NULL OR @title = '')
        OR (@author IS NULL OR @author = '')
        OR (@isbn IS NULL OR @isbn = '')
        OR (@copy_no IS NULL OR @copy_no = ''))
      BEGIN
        RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1)
        RETURN
        END

 ELSE

--If no NULL or blank spaces, check if @isbn book already exists and create new copy record.

                    IF EXISTS (SELECT isbn, title_no FROM item WHERE isbn = @isbn)
                  BEGIN TRY
                    BEGIN TRAN --Allows for execute all or rollback

--Declare @copyno so that the proc adds one to the highest existing copy number.
--Set @title_no to insert existing title_no into record.

                            DECLARE @copyno int
                            SET @copyno = (SELECT max(copy_no) FROM dbo.copy WHERE isbn = @isbn)
                            SET @title_no = (SELECT title_no FROM item WHERE isbn = @isbn)
                            INSERT INTO [library].[dbo].[copy] ([isbn], [copy_no], [title_no], [on_loan])
                            VALUES (@isbn, @copyno + 1, @title_no, 'N')
                            COMMIT TRAN
              END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:

        BEGIN CATCH
              ROLLBACK TRAN
              SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
        END CATCH
ELSE

--If @isbn does not exist, create new a title record
                        BEGIN TRY
                        BEGIN TRAN
                        INSERT INTO [library].[dbo].[title] ([title],[author],[synopsis])
                        VALUES (@title, @author, @synopsis)

                            Set @title_no = SCOPE_IDENTITY()

--then a new item record

                        INSERT INTO [library].[dbo].[item] ([isbn], [title_no],[translation],
                                                                                  [cover],[loanable])
                        VALUES (@isbn, @title_no, @translation, @cover, 'Y')

--and lastly a new copy record

                        INSERT INTO [library].[dbo].[copy] ([isbn], [copy_no], [title_no], [on_loan])
                        VALUES (@isbn, @copy_no, @title_no, 'N')
                        COMMIT TRAN
        END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:

        BEGIN CATCH
              ROLLBACK TRAN
              SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
        END CATCH
END
GO
Check Book Out

--Default values are set to NULL to allow execution despite missing inputs.
ALTER PROCEDURE [dbo].[sp_CheckOutBook]
            @isbn int = NULL
           ,@copy_no smallint = NULL
           ,@member_no smallint = NULL

AS
BEGIN
        SET NOCOUNT ON; --Prevents extra result sets from interfering with SELECT statements.

--Verify that required params being passed are not NULL and do not contain spaces.

IF ((@isbn IS NULL OR @isbn = '')
    OR (@copy_no IS NULL OR @copy_no = '')
    OR (@member_no IS NULL OR @member_no = ''))
    BEGIN
             RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1)
      RETURN
      END

--Verify that book exists.

IF NOT EXISTS (SELECT isbn, copy_no FROM copy where isbn = @isbn AND copy_no = @copy_no)
      BEGIN
      RAISERROR('Book does not exist. Please enter a valid isbn and copy_no.',16,1)
      RETURN
      END

--Verify that card is not expired.

IF (SELECT expr_date FROM adult WHERE member_no = @member_no) <= getdate()
      BEGIN
             RAISERROR('Member card expired or does not exist. Please renew.' ,16,1)
      RETURN
      END

--Verify that member has not reached their book limit.

IF (SELECT COUNT(member_no) FROM loan WHERE member_no = @member_no) > 4
      BEGIN
             RAISERROR('Cannot process request. Book check out limit met.',16,1)
      RETURN
      END

--Verify that book is loanable

IF (SELECT loanable FROM item WHERE isbn = @isbn) = 'N'
      BEGIN
             RAISERROR('Item is not loanable. Please make another selection',16,1)
      RETURN
      END

--Verify that book is not on loan

IF (SELECT on_loan FROM copy WHERE isbn = @isbn AND copy_no = @copy_no) = 'Y'
      BEGIN
             RAISERROR('Item is on loan. Please make another selection',16,1)
      RETURN
      END

--If validations met, insert param values into the loan table
      BEGIN TRY
              BEGIN TRAN --Allows for rollback in case of error
                    DECLARE @title_no int
                    SET @title_no = (SELECT title_no FROM item WHERE isbn = @isbn)
              INSERT INTO [library].[dbo].[loan] ([isbn],[copy_no],[title_no],[member_no]
                                                 ,[out_date],[due_date])
              VALUES (@isbn, @copy_no, @title_no, @member_no, getdate(), dateadd(day,14,getdate()))

--then update the on_loan column in the copy table.

                      UPDATE [library].[dbo].[copy]
                      SET [on_loan] = 'Y'
                      WHERE isbn = @isbn AND copy_no = @copy_no
                      COMMIT TRAN
      END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:

        BEGIN CATCH
              SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
              ROLLBACK TRAN
        END CATCH
END
GO
Project 04: Building Bank database

Objective
Create stored procedures, views and triggers to support the day-to-day duties of Bank tellers. The tellers will need to search for
customers by phone, name, or account number. They will need to search for accounts by customer and account number. The
application should also be able to list all Checking accounts for a customer and list all Savings accounts for a customer. The
application should support all the actions like Deposit, Withdraw, Transfer funds, obtaining account history (of current month),
account history (of any month), etc.

Requirements

   •   Design and build a banking database based on given specifications
   •   Design and develop back end stored procedures that satisfy these functionalities: create account, deposit, withdraw, transfer
       funds, close account, update account, and obtain account history.
   •   Provide input validations (against null and whitespace values as outlined).
   •   Provide adequate error handling.
   •   Prevent Drop and Alter to Schema (DDL Triggers) and prevent delete of Account and delete/updates of Transactions (DML
       triggers)
   •   Produce a build script and two test scripts that are intuitively designed to indicate to the grader that the intended functionality
       works. These should require a minimum of effort to execute. The test scripts must test all required functionality: one should
       hold all test cases intended to succeed and the second script should hold all the failures.

Bank ERD diagram
Sample Stored Procedures

Create Account

CREATE PROCEDURE [dbo].[sp_CreateAccount]
                @CustomerID int = NULL
               ,@AccountTypeID int = NULL
               ,@AccountStatusID int = NULL
               ,@OpeningBalance money = NULL
               ,@SavingsInterestRate decimal (18,2) = NULL
               ,@GeneralOverDraft bit = 0
               ,@GeneralOverDraftBalance money = NULL
               ,@OverDraftAccountID int = NULL
               ,@AccountID int = NULL OUTPUT
AS
BEGIN
      SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements.

--Verify that required params being passed are not NULL and do not contain spaces.

       IF ((@CustomerID IS NULL OR @CustomerID = '')
       OR (@AccountTypeID IS NULL OR @AccountTypeID = '')
       OR (@OpeningBalance IS NULL OR @OpeningBalance = '')
       OR (@AccountStatusID IS NULL OR @AccountStatusID = ''))
     BEGIN
              RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1)
       RETURN
       END


--Verify that the Customer exists.

     IF NOT EXISTS (SELECT CustomerID FROM Customer where @CustomerID = CustomerID)
       BEGIN
       RAISERROR('CustomerID is invalid. Please enter a valid CustomerID.',16,1)
       RETURN
       END

--If validations met, insert values into table Account and CustomerAccount tables to create account.

       BEGIN TRY
                 BEGIN TRAN --Allows for execute all or rollback

                    DECLARE @CurrentBalance money
                    SET @CurrentBalance = @OpeningBalance
                    INSERT INTO [PiggBank].[dbo].[Account] ([AccountTypeID],[AccountStatusID],
                   [DateOpened],[OpeningBalance], [CurrentBalance], [SavingsInterestRate],[GeneralOverDraft],
                   [GeneralOverDraftBalance],[OverDraftAccountID]
                                                                                  ,[OverDraftDate])
                         VALUES (@AccountTypeID, @AccountStatusID, GETDATE(), @OpeningBalance,
                         @CurrentBalance,@SavingsInterestRate, @GeneralOverDraft,
                                  @GeneralOverDraftBalance, @OverDraftAccountID, GETDATE())

                                      Set @AccountID = SCOPE_IDENTITY()

                      INSERT INTO [PiggBank].[dbo].[CustomerAccount] ([AccountID], [CustomerID])
                      VALUES (@AccountID, @CustomerID)
                      COMMIT TRAN
       END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:
      BEGIN CATCH
            ROLLBACK TRAN
            SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
      END CATCH
END

GO
Transfer funds
--Default values are set to NULL to allow execution despite missing inputs.
CREATE PROCEDURE [dbo].[sp_Transfer]
                @CustomerID int = NULL
               ,@wAccountID int = NULL
               ,@dAccountID int = NULL
               ,@wTransactionTypeID int = NULL
               ,@dTransactionTypeID int = NULL
               ,@TransactionAmount money = NULL
               ,@Description ntext = NULL
               ,@TransactionID int = NULL OUTPUT
AS
BEGIN
      SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements.

--Verify that required params being passed are not NULL and do not contain spaces.

      IF   ((@CustomerID IS NULL OR @CustomerID = '')
      OR   (@wAccountID IS NULL OR @wAccountID = '')
      OR   (@dAccountID IS NULL OR @dAccountID = '')
      OR   (@wTransactionTypeID IS NULL OR @wTransactionTypeID = '')
      OR   (@dTransactionTypeID IS NULL OR @dTransactionTypeID = '')
      OR   (@TransactionAmount IS NULL OR @TransactionAmount = ''))

    BEGIN
              RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1)
      RETURN
      END

--Verify that the Customer is linked to the Account specified.

    IF NOT EXISTS (SELECT CustomerID, AccountID FROM CustomerAccount WHERE @CustomerID = CustomerID AND
@wAccountID = AccountID OR @dAccountID = AccountID )
      BEGIN
      RAISERROR('CustomerID is not linked to the account. Please enter a valid AccountID.',16,1)
      RETURN
      END

--Verify that the Account is active.

    IF (SELECT AccountStatusID FROM Account WHERE @wAccountID = AccountID OR @dAccountID = AccountID) = '2'
      BEGIN
      RAISERROR('AccountID is inactive. Please enter a valid AccountID or reactivate account.',16,1)
      RETURN
      END

--Verfiy that there is enough funding in overdraft account as well as the general overdraft account to
commit transaction.
IF @OverDraftAccount IS NOT NULL
      AND @OverDraftBalance - @TransactionAmount < 0
      AND @GeneralOverDraft = '1'
      AND @GeneralOverDraftBalance - @TransactionAmount < -400
BEGIN
      RAISERROR('Not enough funding in acccount to commit transaction.',16,1)
      RETURN
      END


--If validations met, insert values into table.

      BEGIN TRY
                 BEGIN TRAN --Allows for execute all or rollback
                          DECLARE @wNewBalance money, @wOldBalance money
                          SET @wOldBalance = (SELECT CurrentBalance FROM Account WHERE   @wAccountID =
                                              AccountID)
                          SET @wNewBalance = (@wOldBalance - @TransactionAmount)

--First insert the withdraw/deposit into the Transaction table.
                        INSERT INTO [PiggBank].[dbo].[Transaction] ([AccountID],[TransactionTypeID],
                        [TransactionDate],[TransactionAmount],[OldBalance],[NewBalance],[Description])
                        VALUES (@wAccountID, @wTransactionTypeID, GETDATE(), @TransactionAmount,
                        @wOldBalance, @wNewBalance, @Description)

                                      Set @TransactionID = SCOPE_IDENTITY()

--Then update the Account table with the new current balance.
                        UPDATE [PiggBank].[dbo].[Account]
                        SET [CurrentBalance] = @wNewBalance
                        WHERE @wAccountID = AccountID


--Now record the desposit into the transferring account.
                        DECLARE @dNewBalance money, @dOldBalance money
                        SET @dOldBalance = (SELECT CurrentBalance FROM Account WHERE     @dAccountID =
                        AccountID)
                        SET @dNewBalance = (@dOldBalance + @TransactionAmount)

                          INSERT INTO [PiggBank].[dbo].[Transaction] ([AccountID],[TransactionTypeID],
                    [TransactionDate]
                    ,[TransactionAmount],[OldBalance],[NewBalance],[Description])
                          VALUES (@dAccountID, @dTransactionTypeID, GETDATE(), @TransactionAmount,
                                @dOldBalance, @dNewBalance, @Description)
Set @TransactionID = SCOPE_IDENTITY()

--Finally, update the transferring account’s current balance with the set @dNewBalance value.

                        UPDATE [PiggBank].[dbo].[Account]
                        SET [CurrentBalance] = @dNewBalance
                        WHERE @dAccountID = AccountID

                    COMMIT TRAN
      END TRY

--If any error(s) take place during the transaction, errors will be raised and displayed like so:
      BEGIN CATCH
            ROLLBACK TRAN
            SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message
      END CATCH
END
GO


DML Trigger

CREATE TRIGGER [dbo].[PreventAccountDelete]
ON [dbo].[Account]
AFTER DELETE AS

--If the total rowcount of the item just deleted is = to zeroreturn to the transaction.

DECLARE @rowcount int
SET @rowcount = @@rowcount
IF @rowcount = 0
      RETURN

--If the total rowcount of the item just deleted and the rows deleted from the transaction table is
--is not equal to the rowcount of the deleted account, prevent the delete then raise error.

IF (SELECT COUNT(*)
      FROM [dbo].[Transaction] t, deleted d
      WHERE t.AccountID = d.AccountID) <> @rowcount
      BEGIN
            RAISERROR 50001
            'User cannot delete records from Account table'
            ROLLBACK TRAN
            RETURN
      END


DDL Trigger
--DDL trigger safety will fire whenever a DROP TABLE or ALTER TABLE event occurs in the database, raising
an error and preventing altering/deletion of tables.

CREATE TRIGGER [Safety]
ON DATABASE
AFTER DROP_TABLE, ALTER_TABLE
AS
   PRINT 'You must disable Trigger "safety" to drop or alter tables!'
   ROLLBACK;

GO




.

Contenu connexe

Similaire à SQL Portfolio

May Woo Bi Portfolio
May Woo Bi PortfolioMay Woo Bi Portfolio
May Woo Bi Portfolio
maywoo
 

Similaire à SQL Portfolio (20)

SQL Server 2008 Portfolio
SQL Server 2008 PortfolioSQL Server 2008 Portfolio
SQL Server 2008 Portfolio
 
James Colby Maddox Business Intellignece and Computer Science Portfolio
James Colby Maddox Business Intellignece and Computer Science PortfolioJames Colby Maddox Business Intellignece and Computer Science Portfolio
James Colby Maddox Business Intellignece and Computer Science Portfolio
 
supporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered tablesupporting t-sql scripts for Heap vs clustered table
supporting t-sql scripts for Heap vs clustered table
 
Introduction to SQL
Introduction to SQLIntroduction to SQL
Introduction to SQL
 
Introduction to database
Introduction to databaseIntroduction to database
Introduction to database
 
May Woo Bi Portfolio
May Woo Bi PortfolioMay Woo Bi Portfolio
May Woo Bi Portfolio
 
Marcus Matthews
Marcus MatthewsMarcus Matthews
Marcus Matthews
 
My Portfolio
My PortfolioMy Portfolio
My Portfolio
 
My Portfolio
My PortfolioMy Portfolio
My Portfolio
 
Data Exploration with Apache Drill: Day 2
Data Exploration with Apache Drill: Day 2Data Exploration with Apache Drill: Day 2
Data Exploration with Apache Drill: Day 2
 
Practical guide to SQL basics
Practical guide to SQL basicsPractical guide to SQL basics
Practical guide to SQL basics
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
Introducing N1QL: New SQL Based Query Language for JSON
Introducing N1QL: New SQL Based Query Language for JSONIntroducing N1QL: New SQL Based Query Language for JSON
Introducing N1QL: New SQL Based Query Language for JSON
 
SQL Queries Information
SQL Queries InformationSQL Queries Information
SQL Queries Information
 
Customer Clustering for Retailer Marketing
Customer Clustering for Retailer MarketingCustomer Clustering for Retailer Marketing
Customer Clustering for Retailer Marketing
 
Oracle basic queries
Oracle basic queriesOracle basic queries
Oracle basic queries
 
Databricks Sql cheatseet for professional exam
Databricks Sql cheatseet for professional examDatabricks Sql cheatseet for professional exam
Databricks Sql cheatseet for professional exam
 
JKJ_T SQL project code samples
JKJ_T SQL project code samplesJKJ_T SQL project code samples
JKJ_T SQL project code samples
 
Python Programming.pptx
Python Programming.pptxPython Programming.pptx
Python Programming.pptx
 
Tutorial - Learn SQL with Live Online Database
Tutorial - Learn SQL with Live Online DatabaseTutorial - Learn SQL with Live Online Database
Tutorial - Learn SQL with Live Online Database
 

SQL Portfolio

  • 1.
  • 2. Project 01: Transact SQL Objective Write several simple to complex data retrieval queries that involve self joins, correlated sub queries, and parameter insertions. Sample Scenarios and Queries Query #1 The Available Books page is a report listing the publishers and the books they offer. Output a list of publishers, the books they publish and each book’s ISBN. Ensure the output lists the Publishers in alphabetical order and the titles in alphabetical order. --Very basic query USE junglebooks SELECT publisher, title, isbn FROM books ORDER BY publisher, title GO Query # 2 The Range of Customers form allows the user to view orders placed within a given range of customer IDs. The user enters 6 in the txtIDStart form field and 15 in txtIDEnd form field. Display all columns of data in order by Customer ID. Alias the columns in the result set as: ‘Order #’, ‘Cust ID’, ‘Ordered’. --Query with parameters USE junglebooks DECLARE @txtIDStart int, @txtIDEnd int SET @txtIDStart = 6 SET @txtIDEnd = 15 SELECT orderID AS Order#, customerID AS [Cust ID], OrderDate AS Ordered FROM orders WHERE customerID BETWEEN @txtIDStart AND @txtIDEnd ORDER BY customerID GO Query #3 The Large Orders page is a report displaying the largest number of items sold per order. Display the Order ID, Customer ID and Name along with the total number of items they ordered. Display the record with the largest quantity first. Alias as: “Order ID’, ‘Cust ID’, ‘Customer’ and ‘# of items’. --Query with JOINS USE junglebooks SELECT o.OrderID AS [Order ID], c.CustomerID AS [Cust ID], c.Name AS [Name}, SUM(quantityordered) AS [# of items] FROM orders AS o JOIN customers AS c ON o.customerID = c.customerID JOIN orderitems AS oi ON o.orderID = oi.orderID GROUP BY o.orderID, c.customerID, c.Name ORDER BY SUM(quantityordered) DESC GO Query #4 The Search For Authors page also allows the user to search for Authors with a last name starting with a particular letter. The user inputs ‘B’ in the txtLastName form field. Display AuthorID and Name in order by name. Make the assumption that any compound names are hyphenated (i.e.: Billy-Bob Hicks or Susan Smith-Anderson). Alias as: ‘ID’, ‘Name’. --Query with parameters and wild card USE junglebooks DECLARE @txtLastName varchar(80) SET @txtLastName = '% B%' SELECT AuthorID AS ID, Name FROM Authors WHERE Name LIKE @txtLastName ORDER BY Name GO
  • 3. Query #5 Write and execute a query that returns the member_no, full name, out_date, due_date, and title columns from the Loan, Member, and Title tables. Convert the datetime values from the out_date and due_date columns to char(12), format 101. Restrict the results to books which were due prior to the current date. Load the records into a temporary table called #overdue. Leave the query window open after you create the temporary table. --Query data to temporary table USE library SELECT m.member_no, (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name, CONVERT (char(12), l.out_date, 101) AS out_date, CONVERT (char(12), l.due_date, 101) AS due_date , t.title INTO #overdue FROM member AS m JOIN loan AS l ON m.member_no = l.member_no JOIN title AS t ON t.title_no = l.title_no WHERE due_date < CURRENT_TIMESTAMP GO Query #6 Using joins and a UNION clause, write a query to retrieve a single list of members both adult and juvenile, who have reserved ISBN number 288. The list must include the ISBN, title, member_no and name (i.e.: Smith, John) of each member who has the reservation. Additionally, the list should indicate whether the member is an adult or a juvenile. Output the records by name. --Query with UNION clause USE library SELECT (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name , m.member_no, r.isbn, title, 'adult' AS [adult or juvenile] FROM member AS m JOIN adult AS a ON m.member_no = a.member_no JOIN reservation AS r ON a.member_no = r.member_no JOIN item AS it ON r.isbn = it.isbn JOIN title AS t ON t.title_no = it.title_no WHERE r.isbn = 288 UNION SELECT (firstname + ' ' + middleinitial + '.' + ' ' + lastname) AS name, m.member_no, r.isbn, title, 'juvenile' AS [adult or juvenile] FROM member AS m JOIN juvenile AS j ON m.member_no = j.member_no JOIN reservation AS r ON r.member_no = j.member_no JOIN item AS it ON r.isbn = it.isbn JOIN title AS t ON t.title_no = it.title_no WHERE r.isbn = 288 ORDER BY name GO Query #7 Using CASE statement, write a query to retrieve a single list of members both adult and juvenile, who have reserved ISBN number 288. You cannot JOIN to the Adult or Juvenile tables. The list must include the ISBN, title, member_no and name (i.e.: Smith, John) of each member who has the reservation. Additionally, the list should indicate whether the member is an adult or a juvenile. Output the records by name. --Query invloving a subquery SELECT r.isbn AS Isbn, t.title AS Title , m.member_no AS Member_no , m.lastname + ', ' + m.firstname AS name , Category = (CASE WHEN (SELECT a.member_no FROM dbo.adult AS a WHERE a.member_no = m.member_no) = m.member_no THEN 'adult' ELSE WHEN (SELECT j.member_no FROM dbo.juvenile AS j WHERE j.member_no = m.member_no) = m.member_no THEN 'juvenile' END) FROM dbo.reservation AS r JOIN dbo.member AS m ON r.member_no = m.member_no JOIN dbo.item AS i ON i.isbn = r.isbn JOIN dbo.title AS t ON t.title_no = i.title_no WHERE r.isbn = 288 ORDER BY name GO
  • 4. Project 02: XML Objective Create XML queries involving FOR XML, and XQuery to retrieve order delivery details. XML Query Samples Sample 1: Create two FOR XML queries to return the order manifest documents. --Attribute-centric XML USE Northwind SELECT OrderID, OrderDate, CustomerID, (SELECT ProductID, Quantity AS OrderQty FROM [Order Details] WHERE orders.orderID = [Order Details].orderID FOR XML RAW ('Details'),TYPE) FROM Orders FOR XML RAW ('Order'), ROOT ('Orders') --Mixture of element-centric and attribute-centric XML USE Northwind SELECT OrderID, OrderDate, CustomerID, (SELECT ProductID, Quantity AS OrderQty FROM [Order Details] WHERE orders.orderID = [Order Details].orderID FOR XML RAW ('Item'), ELEMENTS, TYPE) FROM Orders FOR XML RAW ('SalesOrder') Sample 2: We have a reporting application that the marketing analysts use to analyze product sales. This Application needs data in XML Format where the parent node is the city and its children are the list of products with Product ID, UnitPrice sold, Discount provided, and Quantity Sold. Create a FORXML Query to return this document. Include all product sales data available. USE Northwind SELECT ShipCity, (SELECT ProductID, UnitPrice, Discount, Quantity FROM [Order Details] WHERE orders.orderID = [Order Details].orderID FOR XML RAW ('Details'), TYPE) FROM Orders FOR XML RAW ('Sale') Sample 3: For each order that Northwind Traders receives, the goods are delivered by a delivery driver. These drivers are going to utilize delivery lists that you are going to implement now. Using SSMS, create a dbo.DeliverySchedule table containing a Delivery ID, Schedule date, Delivery Route, Delivery Driver, and Delivery List column. Populate (“insert” via the starter script provided) the dbo.DeliverySchedule table with test data as follows: • ScheduleDate is GetDate() • DeliveryRoute is 3 • DeliveryDriver is James • DeliveryList is the delivery list XML document (copy and paste from deliverylist.xml) • DeliveryID can auto-increment via an identity property and does not need to be inserted. Verify that this data has been stored in the dbo.DeliverySchedule table. USE Northwind GO -- Drop Statement for when the table is already in the database IF EXISTS(SELECT * FROM sys.tables WHERE name='DeliverySchedule' AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name = 'dbo')) BEGIN DROP TABLE dbo.DeliverySchedule END --Create a table for delivery schedule CREATE TABLE dbo.DeliverySchedule (ScheduleID int IDENTITY PRIMARY KEY, ScheduleDate Datetime, DeliveryRoute int, DeliveryDriver nvarchar(20), DeliveryList xml) --Insert XML INSERT INTO DeliverySchedule VALUES (GetDate(), 3, 'James', '<?xml version="1.0" ?>
  • 5. <DeliveryList> <Delivery OrderID="10296"> <CustomerName>Carlos González</CustomerName> <Address>Carrera 52 con Ave. Bolívar #65-98 Llano Largo Barquisimeto Lara 3508 Venezuela</Address> </Delivery> <Delivery OrderID="10310"> <CustomerName>Liz Nixon</CustomerName> <Address>89 Jefferson Way Suite 2 Portland </Address> </Delivery> </DeliveryList>') --Insert Completed SELECT * FROM dbo.DeliverySchedule Sample 4: Use XQuery expressions to retrieve and modify delivery schedule data Tasks: Retrieve the delivery elements Retrieve the address for the first delivery Find the driver for an order Update a delivery address Verify new delivery address --Retrieve the delivery elements USE Northwind SELECT ScheduleID, ScheduleDate, DeliveryRoute, DeliveryDriver, DeliveryList.query('/DeliveryList/Delivery')DeliveryList FROM DeliverySchedule --Retrieve the address for the first delivery USE Northwind SELECT DeliveryList.value('(/DeliveryList/Delivery/@Address)[1]', 'nvarchar(100)') [Delivery Address] FROM DeliverySchedule WHERE ScheduleID = 1 --Find the driver for an order SELECT DeliveryDriver FROM DeliverySchedule WHERE DeliveryList.exist ('/DeliveryList/Delivery[@OrderID=10296]') = 1 --Find the driver for an order UPDATE DeliverySchedule SET DeliveryList.modify ('replace value of (/DeliveryList/Delivery/@Address)[1] with "2000 Park Place, Portland"') WHERE ScheduleID = 1 --Verify change delivery address SELECT DeliveryList.value ('(/DeliveryList/Delivery/Address)[1]', 'nvarchar(100)')[Delivery Address] FROM DeliverySchedule WHERE ScheduleID = 1
  • 6. Project 03: Stored Procedures Objective Create stored procedures to the support the following principal functions of a library’s day-to-day operations: adding new members (adult and juvenile) and checking books in and out, adding new books, renewing memberships, changing a juvenile record into an adult record after a customer has reached 18. Requirements • Design and develop back end stored procedures that satisfy these functionalities: Add Adult, Add Juvenile, Check In a book, Check Out a book, Add Book, Renew Membership, Change Juvenile to Adult, Update Adult. • Provide input validations (against null and whitespace values as outlined). • Provide adequate error handling. • Produce a build script and two test scripts that are intuitively designed to indicate to the grader that the intended functionality works. These should require a minimum of effort to execute. The test scripts must test all required functionality: one should hold all test cases intended to succeed and the second script should hold all the failures-> i.e. Sample Stored Procedures Add Adult Member --Default values are set to NULL to allow execution despite missing inputs. ALTER PROCEDURE [dbo].[sp_AddAdultMember] @street varchar(15) = NULL ,@city varchar(15) = NULL ,@state char(2) = NULL ,@zip char(10) = NULL ,@phone_no char(13) = NULL ,@lastname varchar(15) = NULL ,@firstname varchar(15) = NULL ,@MemberID int = NULL OUTPUT AS BEGIN SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements. --Verify that required params being passed are not NULL and do not contain spaces. IF ((@firstname IS NULL OR @firstname = '') OR (@lastname IS NULL OR @lastname = '') OR (@street IS NULL OR @street = '') OR (@city IS NULL OR @city = '') OR (@state IS NULL OR @state = '') OR (@zip IS NULL OR @zip = '')) BEGIN RAISERROR('Null values and whitespaces are prohibited. Please enter a valid integer.',16,1) RETURN END --If validations met, insert values into member and adult table. BEGIN TRY BEGIN TRAN --Allows for execute all or rollback INSERT [dbo].[member] ([lastname],[firstname]) VALUES (@lastname, @firstname) Set @MemberID = SCOPE_IDENTITY() INSERT [dbo].[adult] ([member_no],[street],[city],[state],[zip],[phone_no],[expr_date]) VALUES (@MemberID,@street,@city,@state,@zip,@phone_no,dateadd(year,1,getdate())) COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH ROLLBACK TRAN SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message END CATCH END GO
  • 7. Add Book --Default values are set to NULL to allow execution despite missing inputs. ALTER PROCEDURE [dbo].[sp_AddBook] @title varchar(63) = NULL, @author varchar(31) = NULL, @synopsis text = NULL, @isbn int = NULL, @translation char(8) = NULL, @cover char(8) = NULL, @copy_no smallint = 1, @title_no int = NULL OUTPUT AS BEGIN SET NOCOUNT ON; --Prevents extra result sets from interfering with SELECT statements. --Verify that required params being passed are not NULL and do not contain spaces. IF ((@title IS NULL OR @title = '') OR (@author IS NULL OR @author = '') OR (@isbn IS NULL OR @isbn = '') OR (@copy_no IS NULL OR @copy_no = '')) BEGIN RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1) RETURN END ELSE --If no NULL or blank spaces, check if @isbn book already exists and create new copy record. IF EXISTS (SELECT isbn, title_no FROM item WHERE isbn = @isbn) BEGIN TRY BEGIN TRAN --Allows for execute all or rollback --Declare @copyno so that the proc adds one to the highest existing copy number. --Set @title_no to insert existing title_no into record. DECLARE @copyno int SET @copyno = (SELECT max(copy_no) FROM dbo.copy WHERE isbn = @isbn) SET @title_no = (SELECT title_no FROM item WHERE isbn = @isbn) INSERT INTO [library].[dbo].[copy] ([isbn], [copy_no], [title_no], [on_loan]) VALUES (@isbn, @copyno + 1, @title_no, 'N') COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH ROLLBACK TRAN SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message END CATCH ELSE --If @isbn does not exist, create new a title record BEGIN TRY BEGIN TRAN INSERT INTO [library].[dbo].[title] ([title],[author],[synopsis]) VALUES (@title, @author, @synopsis) Set @title_no = SCOPE_IDENTITY() --then a new item record INSERT INTO [library].[dbo].[item] ([isbn], [title_no],[translation], [cover],[loanable]) VALUES (@isbn, @title_no, @translation, @cover, 'Y') --and lastly a new copy record INSERT INTO [library].[dbo].[copy] ([isbn], [copy_no], [title_no], [on_loan]) VALUES (@isbn, @copy_no, @title_no, 'N') COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH ROLLBACK TRAN SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message END CATCH END GO
  • 8. Check Book Out --Default values are set to NULL to allow execution despite missing inputs. ALTER PROCEDURE [dbo].[sp_CheckOutBook] @isbn int = NULL ,@copy_no smallint = NULL ,@member_no smallint = NULL AS BEGIN SET NOCOUNT ON; --Prevents extra result sets from interfering with SELECT statements. --Verify that required params being passed are not NULL and do not contain spaces. IF ((@isbn IS NULL OR @isbn = '') OR (@copy_no IS NULL OR @copy_no = '') OR (@member_no IS NULL OR @member_no = '')) BEGIN RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1) RETURN END --Verify that book exists. IF NOT EXISTS (SELECT isbn, copy_no FROM copy where isbn = @isbn AND copy_no = @copy_no) BEGIN RAISERROR('Book does not exist. Please enter a valid isbn and copy_no.',16,1) RETURN END --Verify that card is not expired. IF (SELECT expr_date FROM adult WHERE member_no = @member_no) <= getdate() BEGIN RAISERROR('Member card expired or does not exist. Please renew.' ,16,1) RETURN END --Verify that member has not reached their book limit. IF (SELECT COUNT(member_no) FROM loan WHERE member_no = @member_no) > 4 BEGIN RAISERROR('Cannot process request. Book check out limit met.',16,1) RETURN END --Verify that book is loanable IF (SELECT loanable FROM item WHERE isbn = @isbn) = 'N' BEGIN RAISERROR('Item is not loanable. Please make another selection',16,1) RETURN END --Verify that book is not on loan IF (SELECT on_loan FROM copy WHERE isbn = @isbn AND copy_no = @copy_no) = 'Y' BEGIN RAISERROR('Item is on loan. Please make another selection',16,1) RETURN END --If validations met, insert param values into the loan table BEGIN TRY BEGIN TRAN --Allows for rollback in case of error DECLARE @title_no int SET @title_no = (SELECT title_no FROM item WHERE isbn = @isbn) INSERT INTO [library].[dbo].[loan] ([isbn],[copy_no],[title_no],[member_no] ,[out_date],[due_date]) VALUES (@isbn, @copy_no, @title_no, @member_no, getdate(), dateadd(day,14,getdate())) --then update the on_loan column in the copy table. UPDATE [library].[dbo].[copy] SET [on_loan] = 'Y' WHERE isbn = @isbn AND copy_no = @copy_no COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message ROLLBACK TRAN END CATCH END GO
  • 9. Project 04: Building Bank database Objective Create stored procedures, views and triggers to support the day-to-day duties of Bank tellers. The tellers will need to search for customers by phone, name, or account number. They will need to search for accounts by customer and account number. The application should also be able to list all Checking accounts for a customer and list all Savings accounts for a customer. The application should support all the actions like Deposit, Withdraw, Transfer funds, obtaining account history (of current month), account history (of any month), etc. Requirements • Design and build a banking database based on given specifications • Design and develop back end stored procedures that satisfy these functionalities: create account, deposit, withdraw, transfer funds, close account, update account, and obtain account history. • Provide input validations (against null and whitespace values as outlined). • Provide adequate error handling. • Prevent Drop and Alter to Schema (DDL Triggers) and prevent delete of Account and delete/updates of Transactions (DML triggers) • Produce a build script and two test scripts that are intuitively designed to indicate to the grader that the intended functionality works. These should require a minimum of effort to execute. The test scripts must test all required functionality: one should hold all test cases intended to succeed and the second script should hold all the failures. Bank ERD diagram
  • 10. Sample Stored Procedures Create Account CREATE PROCEDURE [dbo].[sp_CreateAccount] @CustomerID int = NULL ,@AccountTypeID int = NULL ,@AccountStatusID int = NULL ,@OpeningBalance money = NULL ,@SavingsInterestRate decimal (18,2) = NULL ,@GeneralOverDraft bit = 0 ,@GeneralOverDraftBalance money = NULL ,@OverDraftAccountID int = NULL ,@AccountID int = NULL OUTPUT AS BEGIN SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements. --Verify that required params being passed are not NULL and do not contain spaces. IF ((@CustomerID IS NULL OR @CustomerID = '') OR (@AccountTypeID IS NULL OR @AccountTypeID = '') OR (@OpeningBalance IS NULL OR @OpeningBalance = '') OR (@AccountStatusID IS NULL OR @AccountStatusID = '')) BEGIN RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1) RETURN END --Verify that the Customer exists. IF NOT EXISTS (SELECT CustomerID FROM Customer where @CustomerID = CustomerID) BEGIN RAISERROR('CustomerID is invalid. Please enter a valid CustomerID.',16,1) RETURN END --If validations met, insert values into table Account and CustomerAccount tables to create account. BEGIN TRY BEGIN TRAN --Allows for execute all or rollback DECLARE @CurrentBalance money SET @CurrentBalance = @OpeningBalance INSERT INTO [PiggBank].[dbo].[Account] ([AccountTypeID],[AccountStatusID], [DateOpened],[OpeningBalance], [CurrentBalance], [SavingsInterestRate],[GeneralOverDraft], [GeneralOverDraftBalance],[OverDraftAccountID] ,[OverDraftDate]) VALUES (@AccountTypeID, @AccountStatusID, GETDATE(), @OpeningBalance, @CurrentBalance,@SavingsInterestRate, @GeneralOverDraft, @GeneralOverDraftBalance, @OverDraftAccountID, GETDATE()) Set @AccountID = SCOPE_IDENTITY() INSERT INTO [PiggBank].[dbo].[CustomerAccount] ([AccountID], [CustomerID]) VALUES (@AccountID, @CustomerID) COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH ROLLBACK TRAN SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message END CATCH END GO
  • 11. Transfer funds --Default values are set to NULL to allow execution despite missing inputs. CREATE PROCEDURE [dbo].[sp_Transfer] @CustomerID int = NULL ,@wAccountID int = NULL ,@dAccountID int = NULL ,@wTransactionTypeID int = NULL ,@dTransactionTypeID int = NULL ,@TransactionAmount money = NULL ,@Description ntext = NULL ,@TransactionID int = NULL OUTPUT AS BEGIN SET NOCOUNT ON;--Prevents extra result sets from interfering with SELECT statements. --Verify that required params being passed are not NULL and do not contain spaces. IF ((@CustomerID IS NULL OR @CustomerID = '') OR (@wAccountID IS NULL OR @wAccountID = '') OR (@dAccountID IS NULL OR @dAccountID = '') OR (@wTransactionTypeID IS NULL OR @wTransactionTypeID = '') OR (@dTransactionTypeID IS NULL OR @dTransactionTypeID = '') OR (@TransactionAmount IS NULL OR @TransactionAmount = '')) BEGIN RAISERROR('Null values and whitespaces prohibited. Please enter a valid integer.',16,1) RETURN END --Verify that the Customer is linked to the Account specified. IF NOT EXISTS (SELECT CustomerID, AccountID FROM CustomerAccount WHERE @CustomerID = CustomerID AND @wAccountID = AccountID OR @dAccountID = AccountID ) BEGIN RAISERROR('CustomerID is not linked to the account. Please enter a valid AccountID.',16,1) RETURN END --Verify that the Account is active. IF (SELECT AccountStatusID FROM Account WHERE @wAccountID = AccountID OR @dAccountID = AccountID) = '2' BEGIN RAISERROR('AccountID is inactive. Please enter a valid AccountID or reactivate account.',16,1) RETURN END --Verfiy that there is enough funding in overdraft account as well as the general overdraft account to commit transaction. IF @OverDraftAccount IS NOT NULL AND @OverDraftBalance - @TransactionAmount < 0 AND @GeneralOverDraft = '1' AND @GeneralOverDraftBalance - @TransactionAmount < -400 BEGIN RAISERROR('Not enough funding in acccount to commit transaction.',16,1) RETURN END --If validations met, insert values into table. BEGIN TRY BEGIN TRAN --Allows for execute all or rollback DECLARE @wNewBalance money, @wOldBalance money SET @wOldBalance = (SELECT CurrentBalance FROM Account WHERE @wAccountID = AccountID) SET @wNewBalance = (@wOldBalance - @TransactionAmount) --First insert the withdraw/deposit into the Transaction table. INSERT INTO [PiggBank].[dbo].[Transaction] ([AccountID],[TransactionTypeID], [TransactionDate],[TransactionAmount],[OldBalance],[NewBalance],[Description]) VALUES (@wAccountID, @wTransactionTypeID, GETDATE(), @TransactionAmount, @wOldBalance, @wNewBalance, @Description) Set @TransactionID = SCOPE_IDENTITY() --Then update the Account table with the new current balance. UPDATE [PiggBank].[dbo].[Account] SET [CurrentBalance] = @wNewBalance WHERE @wAccountID = AccountID --Now record the desposit into the transferring account. DECLARE @dNewBalance money, @dOldBalance money SET @dOldBalance = (SELECT CurrentBalance FROM Account WHERE @dAccountID = AccountID) SET @dNewBalance = (@dOldBalance + @TransactionAmount) INSERT INTO [PiggBank].[dbo].[Transaction] ([AccountID],[TransactionTypeID], [TransactionDate] ,[TransactionAmount],[OldBalance],[NewBalance],[Description]) VALUES (@dAccountID, @dTransactionTypeID, GETDATE(), @TransactionAmount, @dOldBalance, @dNewBalance, @Description)
  • 12. Set @TransactionID = SCOPE_IDENTITY() --Finally, update the transferring account’s current balance with the set @dNewBalance value. UPDATE [PiggBank].[dbo].[Account] SET [CurrentBalance] = @dNewBalance WHERE @dAccountID = AccountID COMMIT TRAN END TRY --If any error(s) take place during the transaction, errors will be raised and displayed like so: BEGIN CATCH ROLLBACK TRAN SELECT ERROR_NUMBER() ErrorNumber, ERROR_MESSAGE() Message END CATCH END GO DML Trigger CREATE TRIGGER [dbo].[PreventAccountDelete] ON [dbo].[Account] AFTER DELETE AS --If the total rowcount of the item just deleted is = to zeroreturn to the transaction. DECLARE @rowcount int SET @rowcount = @@rowcount IF @rowcount = 0 RETURN --If the total rowcount of the item just deleted and the rows deleted from the transaction table is --is not equal to the rowcount of the deleted account, prevent the delete then raise error. IF (SELECT COUNT(*) FROM [dbo].[Transaction] t, deleted d WHERE t.AccountID = d.AccountID) <> @rowcount BEGIN RAISERROR 50001 'User cannot delete records from Account table' ROLLBACK TRAN RETURN END DDL Trigger --DDL trigger safety will fire whenever a DROP TABLE or ALTER TABLE event occurs in the database, raising an error and preventing altering/deletion of tables. CREATE TRIGGER [Safety] ON DATABASE AFTER DROP_TABLE, ALTER_TABLE AS PRINT 'You must disable Trigger "safety" to drop or alter tables!' ROLLBACK; GO .