0% found this document useful (0 votes)
1 views

Database Management Systems Using PL-SQL

This document provides an overview of various SQL concepts, including creating and using sequences, implementing conditional logic with IF...ELSE, utilizing loops, creating stored procedures, defining functions, simulating associative arrays, and handling errors with TRY...CATCH. Each section includes scripts and explanations to demonstrate how to automate tasks, manage data, and ensure program stability in SQL Server. The document aims to enhance learners' understanding of SQL programming and improve their ability to write efficient and reusable code.

Uploaded by

Soham Ghadge
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Database Management Systems Using PL-SQL

This document provides an overview of various SQL concepts, including creating and using sequences, implementing conditional logic with IF...ELSE, utilizing loops, creating stored procedures, defining functions, simulating associative arrays, and handling errors with TRY...CATCH. Each section includes scripts and explanations to demonstrate how to automate tasks, manage data, and ensure program stability in SQL Server. The document aims to enhance learners' understanding of SQL programming and improve their ability to write efficient and reusable code.

Uploaded by

Soham Ghadge
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

UNIT 1

1. Creating and Using Sequences

Question: How can you create, reference, alter, and drop a sequence in SQL Server?
Use and Meaning:

Sequences are used to generate unique numeric values automatically, typically for primary
keys or IDs.

Script:

-- Step 1: Create a sequence


CREATE SEQUENCE TestSeq
START WITH 1 -- Starting value of the sequence
INCREMENT BY 1; -- Step to increment the sequence value

-- Step 2: Create a table to use the sequence


CREATE TABLE SequenceDemo (
ID INT PRIMARY KEY,
Name NVARCHAR(50)
);

-- Step 3: Insert data using the sequence


INSERT INTO SequenceDemo (ID, Name)
VALUES (NEXT VALUE FOR TestSeq, 'Alice'),
(NEXT VALUE FOR TestSeq, 'Bob');

-- Step 4: Alter the sequence to restart at a specific value


ALTER SEQUENCE TestSeq RESTART WITH 100;

-- Step 5: Insert more data using the altered sequence


INSERT INTO SequenceDemo (ID, Name)
VALUES (NEXT VALUE FOR TestSeq, 'Charlie');

-- Step 6: Drop the sequence


DROP SEQUENCE TestSeq;

-- Step 7: View data in the table


SELECT * FROM SequenceDemo;

Explanation:

● Creating the Sequence:


○ The CREATE SEQUENCE statement initializes the sequence with a starting value
and increment step.
○ Example: Starts at 1 and increments by 1 for each call.
● Using the Sequence:
○ The NEXT VALUE FOR clause retrieves the next value of the sequence.
○ This value can be used in INSERT statements to auto-generate IDs.
● Altering the Sequence:
○ The ALTER SEQUENCE statement changes the sequence's behavior (e.g.,
restarting at a specific value).
● Dropping the Sequence:
○ The DROP SEQUENCE statement deletes the sequence from the database.

Outcome:

1. Learn to automate ID generation and modify sequences effectively.


2. Creates a sequence for generating unique IDs automatically.
3. Demonstrates how to use the sequence in a table and alter its behavior.
4. Learners can efficiently automate unique identifier creation for tables.

2. Conditional Selection Using IF...ELSE

Question: How do you implement conditional logic in a stored procedure?


Use and Meaning:

Conditional logic allows dynamic execution based on input parameters or conditions, enabling
decision-making in queries or stored procedures.

The IF...ELSE statement in SQL allows conditional execution of different sets of SQL
statements based on whether a specified condition evaluates to TRUE or FALSE. It is
commonly used to implement decision-making logic in stored procedures or scripts.

Script:

-- Step 1: Declare a variable to store input

DECLARE @Age INT = 20;


-- Step 2: Use IF...ELSE to check the condition

IF @Age >= 18

PRINT 'Eligible to Vote'; -- Execute if the condition is TRUE

ELSE

PRINT 'Not Eligible to Vote'; -- Execute if the condition is FALSE

-- Step 3: Example with multiple conditions using ELSE IF

DECLARE @Marks INT = 85;

IF @Marks >= 90

PRINT 'Grade: A+';

ELSE IF @Marks >= 75

PRINT 'Grade: A';

ELSE IF @Marks >= 50

PRINT 'Grade: B';

ELSE

PRINT 'Grade: Fail';

Explanation:

1. Basic IF...ELSE Logic:


○ The IF block executes a SQL statement if the condition evaluates to TRUE.
○ The ELSE block executes if the IF condition evaluates to FALSE.
2. Nested Conditions (ELSE IF):
○ Allows for multiple conditions to be checked in sequence.
○ Useful for scenarios requiring a graded or tiered response.
3. Variables in Conditions:
○ SQL variables (e.g., @Age, @Marks) allow dynamic evaluation of conditions
based on input.
Outcome:

1. Learners can use IF...ELSE for decision-making in SQL scripts or stored


procedures.
2. Gain insights into executing different SQL statements based on conditions.
3. Understand the flexibility of nested conditions for complex decision-making.
4. Understand conditional statements and execute actions based on input.

3. LOOP Statements

Question: How can loops be used to repeatedly execute a set of statements in SQL?
Use and Meaning:

Loops automate repetitive tasks, such as processing or calculating values over multiple
iterations.

Loops in SQL are used to perform repetitive tasks, such as updating records, calculating
values, or processing rows in a dataset. They provide automation, reducing the need for
manual execution of repetitive operations.

Script:

-- Step 1: Declare a variable for the loop


DECLARE @Counter INT = 1;

-- Step 2: Use a WHILE loop to iterate


WHILE @Counter <= 5
BEGIN
-- Print the current counter value
PRINT 'Counter Value: ' + CAST(@Counter AS NVARCHAR);

-- Increment the counter


SET @Counter = @Counter + 1;
END;

-- Step 3: Example of using a loop for table updates


CREATE TABLE LoopDemo (ID INT, Value NVARCHAR(50));
INSERT INTO LoopDemo (ID, Value)
VALUES (1, 'Initial'), (2, 'Initial'), (3, 'Initial');

DECLARE @ID INT = 1;

-- Update table rows in a loop


WHILE @ID <= 3
BEGIN
UPDATE LoopDemo
SET Value = 'Updated Value ' + CAST(@ID AS NVARCHAR)
WHERE ID = @ID;

-- Increment the ID
SET @ID = @ID + 1;
END;

-- Step 4: View updated table


SELECT * FROM LoopDemo;

Explanation:

1. Basic Looping with WHILE:


○ The WHILE loop executes the block of statements as long as the condition
evaluates to TRUE.
○ Example: Iterating through values from 1 to 5.
2. Incrementing Variables:
○ Variables (e.g., @Counter, @ID) are incremented or modified in each iteration to
avoid infinite loops.
3. Practical Use Case – Updating Rows:
○ Loops can iterate over rows in a table to apply updates dynamically, as
demonstrated in the second example.
4. Ending the Loop:
○ The loop ends when the condition evaluates to FALSE. For instance, @Counter
<= 5 becomes FALSE when @Counter is 6.

Outcome:

1. Efficiently execute repetitive processes using loops.


2. Understand the syntax and implementation of WHILE loops in SQL.
3. Learn to perform repetitive operations like updating or processing rows
dynamically.
4. Efficiently automate tasks, reducing manual workload and errors.

4. Creating and Using Stored Procedures

Question: What are stored procedures, and how can you create and execute them in SQL?
Use and Meaning:

Stored procedures encapsulate reusable SQL code for modularity, efficiency, and reduced
redundancy.

A stored procedure is a precompiled collection of SQL statements and logic, stored in the
database. It can be reused, parameterized, and optimized for efficiency. Stored procedures
improve performance, enforce business logic, and simplify complex operations.

Script:

-- Step 1: Create a stored procedure


CREATE PROCEDURE GetEmployeeDetails
@EmployeeID INT
AS
BEGIN
-- Fetch details of the employee with the given ID
SELECT EmployeeID, FirstName, LastName, Department, Salary
FROM Employees
WHERE EmployeeID = @EmployeeID;
END;

-- Step 2: Execute the stored procedure


EXEC GetEmployeeDetails @EmployeeID = 101;

-- Step 3: Create a stored procedure with an INSERT operation


CREATE PROCEDURE AddNewEmployee
@FirstName NVARCHAR(50),
@LastName NVARCHAR(50),
@Department NVARCHAR(50),
@Salary DECIMAL(10, 2)
AS
BEGIN
-- Insert a new employee record
INSERT INTO Employees (FirstName, LastName, Department, Salary)
VALUES (@FirstName, @LastName, @Department, @Salary);
END;

-- Step 4: Execute the INSERT stored procedure


EXEC AddNewEmployee @FirstName = 'John', @LastName = 'Doe', @Department = 'IT',
@Salary = 75000.00;

-- Step 5: View updated table data


SELECT * FROM Employees;

-- Step 6: Alter a stored procedure


ALTER PROCEDURE GetEmployeeDetails
@EmployeeID INT
AS
BEGIN
-- Fetch details with additional columns
SELECT EmployeeID, FirstName, LastName, Department, Salary, HireDate
FROM Employees
WHERE EmployeeID = @EmployeeID;
END;

-- Step 7: Drop the stored procedure


DROP PROCEDURE GetEmployeeDetails;

Explanation:

1. Creating a Stored Procedure:


○ CREATE PROCEDURE defines a procedure with optional parameters.
○ Example: Fetch employee details based on @EmployeeID.
2. Executing a Stored Procedure:
○ EXEC or EXECUTE runs the procedure with required parameters.
○ Example: Fetching data or inserting records.
3. Parameterized Procedures:
○ Allow dynamic input for flexibility, such as inserting or retrieving specific data.
4. Altering a Stored Procedure:
○ ALTER PROCEDURE modifies the definition of an existing procedure.
5. Dropping a Stored Procedure:
○ DROP PROCEDURE removes the procedure from the database.

Outcome:

1. Enhance modular programming and code reuse in SQL.


2. Learners can create and manage reusable SQL scripts with stored procedures.
3. Understand how stored procedures simplify tasks like querying, inserting, and
updating data.
4. Gain insights into dynamic operations through parameterization.

5. Using Functions and Recursion

Question: How do you create a user-defined function and use it for calculations?
Use and Meaning:

Functions simplify repetitive calculations and encapsulate logic for reuse.

Functions in SQL are used to encapsulate reusable logic and computations.

Recursive functions are a special type of function that calls itself to solve problems that can
be broken down into simpler sub-problems, such as calculating factorials, Fibonacci
sequences, or hierarchical data traversal.

Script:

-- Step 1: Create a scalar function to calculate factorial using recursion


CREATE FUNCTION CalculateFactorial (@Number INT)
RETURNS INT
AS
BEGIN
-- Base case: if the number is 0 or 1, return 1
IF @Number = 0 OR @Number = 1
RETURN 1;

-- Recursive case: multiply the number by the factorial of (number - 1)


RETURN @Number * dbo.CalculateFactorial(@Number - 1);
END;
-- Step 2: Use the function to calculate factorial
SELECT dbo.CalculateFactorial(5) AS FactorialValue; -- Output: 120

-- Step 3: Create a table-valued function for Fibonacci series


CREATE FUNCTION GenerateFibonacci (@Count INT)
RETURNS @FibonacciTable TABLE (SequenceNumber INT, FibonacciValue INT)
AS
BEGIN
DECLARE @First INT = 0, @Second INT = 1, @Next INT, @Index INT = 1;

WHILE @Index <= @Count


BEGIN
INSERT INTO @FibonacciTable (SequenceNumber, FibonacciValue)
VALUES (@Index, @First);

-- Calculate the next Fibonacci value


SET @Next = @First + @Second;
SET @First = @Second;
SET @Second = @Next;

SET @Index = @Index + 1;


END;

RETURN;
END;

-- Step 4: Use the table-valued function to get the Fibonacci series


SELECT * FROM dbo.GenerateFibonacci(10);

-- Step 5: Drop the functions when no longer needed


DROP FUNCTION CalculateFactorial;
DROP FUNCTION GenerateFibonacci;

Explanation:

1. Scalar Function for Factorial Calculation:


○ The CalculateFactorial function recursively calculates the factorial of a number.
○ Base case ensures the recursion terminates, and the recursive case reduces the
problem size.
2. Table-Valued Function for Fibonacci Series:
○ Generates a sequence of Fibonacci numbers and returns a table of results.
○ Uses a WHILE loop to iterate until the desired count is reached.
3. Using Functions:
○ Functions are called within SELECT statements for scalar results or as table
sources for tabular results.
4. Dropping Functions:
○ Use DROP FUNCTION to remove user-defined functions when they are no longer
required.

Outcome:

● Learners understand how to create scalar and table-valued functions for computations
and series generation.
● Gain insights into using recursion for solving mathematical and hierarchical problems.
● Learn how functions simplify complex logic and enhance code reusability.

6. Working with Associative Arrays

Question: How can you simulate an associative array using tables in SQL?
Use and Meaning:

Associative arrays provide key-value pair mappings for quick lookups.

Associative arrays, also known as key-value pairs or hash maps, store data as a collection of
unique keys and associated values. In SQL, associative arrays are typically implemented using
collections such as TABLE or ASSOCIATIVE ARRAY types in PL/SQL (Oracle) or SQL Server's
XML and JSON data types. They allow for quick lookups and efficient data storage when
key-value relationships are needed.

Script:

-- Step 1: Declare an XML variable to represent the associative array


DECLARE @AssociativeArray XML;

-- Step 2: Initialize the XML variable with key-value pairs (representing the associative array)
SET @AssociativeArray =
'<Items>
<Item>
<Key>1</Key>
<Value>Apple</Value>
</Item>
<Item>
<Key>2</Key>
<Value>Banana</Value>
</Item>
<Item>
<Key>3</Key>
<Value>Orange</Value>
</Item>
</Items>';

-- Step 3: Query the associative array using XML methods to extract data
SELECT
Item.value('(Key)[1]', 'INT') AS Key,
Item.value('(Value)[1]', 'NVARCHAR(50)') AS Value
FROM @AssociativeArray.nodes('/Items/Item') AS X(Item);

-- Step 4: Retrieve a specific key-value pair


SELECT
Item.value('(Key)[1]', 'INT') AS Key,
Item.value('(Value)[1]', 'NVARCHAR(50)') AS Value
FROM @AssociativeArray.nodes('/Items/Item') AS X(Item)
WHERE Item.value('(Key)[1]', 'INT') = 2;

-- Step 5: Update a value in the associative array


SET @AssociativeArray.modify('
replace value of (/Items/Item[Key="2"]/Value)[1] with "Grapes"');

-- Step 6: View the updated associative array


SELECT @AssociativeArray AS UpdatedAssociativeArray;

Explanation:

1. Using XML for Associative Arrays:


○ XML can be used to create key-value pairs in SQL Server, where the <Key>
element stores the key and the <Value> element stores the corresponding value.
This allows SQL to mimic the behavior of associative arrays.
2. Querying the XML Data:
○ The nodes() method is used to extract each <Item> element.
○ The value() method retrieves the values for the <Key> and <Value>.
3. Filtering Data:
○ You can filter based on the key by specifying the key in the WHERE clause, which
is useful for retrieving a specific key-value pair.
4. Modifying the Array:
○ The modify() method allows you to update a value for a given key in the XML
structure. This simulates the process of updating a value in an associative array.
5. XML Representation:
○ XML is particularly useful for managing hierarchical or nested data and can be a
good fit for situations where associative arrays or key-value stores are required.

Outcome:

● Learners understand how to create and work with associative arrays using SQL Server’s
XML data type.
● Gain knowledge on querying, updating, and managing key-value pairs in SQL.
● Learn to use XML-based associative arrays to handle and store data in a flexible and
efficient way.

7. Error Handling and Exception Propagation

Question: How can you handle errors using TRY...CATCH in SQL Server?
Use and Meaning:

1. Error handling ensures program stability by catching and responding to runtime errors.
2. Error handling in SQL allows you to manage runtime errors gracefully without
terminating the execution of your SQL statements.
3. Exception propagation ensures that errors are passed up the call stack, enabling proper
error management in stored procedures, functions, and triggers.
4. This is especially useful in complex systems where multiple layers of logic are involved,
and errors need to be caught and handled at different levels.
Script:

-- Step 1: Create a stored procedure with error handling

CREATE PROCEDURE HandleErrorExample

AS

BEGIN

BEGIN TRY

-- Simulating an error (dividing by zero)

DECLARE @Result INT;

SET @Result = 10 / 0; -- This will cause a divide-by-zero error

PRINT 'This will not be printed if an error occurs.';

END TRY

BEGIN CATCH

-- Catch the error and handle it

PRINT 'An error occurred: ' + ERROR_MESSAGE(); -- Print the error message

-- Optionally, you can re-throw the error to propagate it

THROW; -- This rethrows the error, propagating it to the caller

END CATCH;

END;

-- Step 2: Execute the stored procedure

EXEC HandleErrorExample;
-- Step 3: Handling errors in a transaction

BEGIN TRY

BEGIN TRANSACTION;

-- Insert a record into a table (Assume a table named Employees)

INSERT INTO Employees (EmployeeID, FirstName, LastName)

VALUES (NULL, 'John', 'Doe'); -- This might cause an error due to NULL EmployeeID

-- Commit the transaction if no errors occur

COMMIT;

END TRY

BEGIN CATCH

-- Rollback the transaction if an error occurs

ROLLBACK;

PRINT 'Error in transaction: ' + ERROR_MESSAGE();

END CATCH;

Explanation:

1. Error Handling with TRY...CATCH:


○ The TRY...CATCH block is used to catch exceptions that occur in the TRY
section and handle them in the CATCH section.
○ If an error occurs, control is passed to the CATCH block, where you can log the
error, print a message, or even propagate the error further.
2. Re-throwing Errors with THROW:
○ The THROW statement is used to propagate the caught exception back to the
calling environment. This is useful when you want to catch an error but still want
it to be handled further up the stack, such as in a calling application or another
procedure.
3. Transaction Management with Error Handling:
○ In the case of a transaction, if an error occurs during any operation (e.g.,
INSERT), the entire transaction can be rolled back using ROLLBACK to maintain
data consistency.
○ The COMMIT statement is only executed if all operations in the TRY block
succeed without errors.
4. Error Functions:
○ ERROR_MESSAGE(): Returns the error message that occurred.
○ ERROR_NUMBER(): Returns the error number.
○ ERROR_SEVERITY(): Returns the severity of the error.
○ ERROR_STATE(): Returns the state number associated with the error.

Outcome:

● Learners can use TRY...CATCH for robust error handling in SQL, ensuring errors are
caught and managed properly.
● Gain knowledge about propagating errors back to the calling environment with THROW.
● Understand how to manage transactions in SQL, ensuring data integrity and
consistency even in case of errors.

8. Using NULL Statements

Question: How do you handle NULL values in SQL queries?


Use and Meaning: NULL handling ensures robust logic when dealing with undefined or
missing data.

Script:

Explanation and Outcome:


● Explanation: Demonstrates handling NULL scenarios in conditional logic.
● Outcome: Prevent errors caused by undefined or missing data.

9. Creating Multidimensional Collections

Question: How can you create and manipulate multidimensional collections in SQL?
Use and Meaning:

Multidimensional collections store complex datasets requiring a row-column structure.

Multidimensional collections allow you to store data in a format where multiple levels of
information are maintained within a single collection. These are commonly used to represent
tabular data, grids, or matrices. In SQL, multidimensional collections can be implemented
using arrays, tables, or nested collections within PL/SQL (Oracle) or SQL Server's XML/JSON
structures. These collections are useful when you need to model data with more than one
dimension, such as a list of lists (2D array) or more complex structures.

-- Step 1: Create a table to simulate a 2D matrix structure using XML

DECLARE @MultiDimensionalCollection XML;

-- Step 2: Initialize the XML variable with multidimensional data (simulating a 2D array)

SET @MultiDimensionalCollection =

'<Matrix>

<Row>

<Column>1</Column>

<Column>2</Column>

<Column>3</Column>

</Row>

<Row>

<Column>4</Column>

<Column>5</Column>
<Column>6</Column>

</Row>

<Row>

<Column>7</Column>

<Column>8</Column>

<Column>9</Column>

</Row>

</Matrix>';

-- Step 3: Query the multidimensional collection to extract data

SELECT

Row.value('(Column)[1]', 'INT') AS Column1,

Row.value('(Column)[2]', 'INT') AS Column2,

Row.value('(Column)[3]', 'INT') AS Column3

FROM @MultiDimensionalCollection.nodes('/Matrix/Row') AS X(Row);

-- Step 4: Access specific row or column data

SELECT

Row.value('(Column)[2]', 'INT') AS Column2

FROM @MultiDimensionalCollection.nodes('/Matrix/Row') AS X(Row)

WHERE Row.exist('(Column[2] = "5")') = 1; -- Find the row where Column2 is 5

-- Step 5: Update an element in the multidimensional collection (modifying the XML)


SET @MultiDimensionalCollection.modify('

replace value of (/Matrix/Row[2]/Column[2])[1] with "10"'); -- Change value from 5 to 10

-- Step 6: View the updated multidimensional collection

SELECT @MultiDimensionalCollection AS UpdatedMatrix;

Explanation:

1. Using XML to Simulate Multidimensional Arrays:


○ In this example, we use XML to represent a 2D array (matrix) with rows and
columns. Each <Row> element contains multiple <Column> elements,
simulating the structure of a 2D array.
2. Accessing Data in the Matrix:
○ The nodes() method is used to iterate over each <Row> in the matrix.
○ The value() method retrieves the value from each column within the row.
Here, we extract all columns for each row.
3. Filtering Data in the Matrix:
○ We use the exist() method to filter rows based on a condition (e.g., looking
for a column value of 5 in the second column).
4. Updating Values in the Matrix:
○ The modify() method is used to change an element's value within the XML
structure, simulating an update to a specific cell in the matrix.
5. Multidimensional Data Representation:
○ Using XML for multidimensional collections allows you to store, query, and
manipulate data in multiple dimensions (like rows and columns) effectively.

Outcome:

● Learners will understand how to use XML to create multidimensional collections in SQL
Server, simulating 2D arrays or matrices.
● Gain knowledge on how to query, filter, and update data in a structured,
multidimensional format.
● Learn how to leverage XML’s powerful querying and modification features for complex
data structures within SQL.

10. Exception Handling for User-Defined Errors


Question: How can you create and handle user-defined exceptions in SQL Server?
Use and Meaning:

User-defined exceptions allow tailored error management for specific scenarios.

User-defined errors allow you to create specific exceptions for custom scenarios in SQL,
which may not be captured by predefined errors. This is useful when you need to handle
specific business logic violations, constraints, or conditions that are unique to your
application or database schema.

Using RAISEERROR in SQL Server (or RAISE in PL/SQL), you can raise custom errors with
detailed messages, error numbers, and state values, and then handle these errors within
TRY...CATCH blocks or exception handling routines.

Script :(Using RAISEERROR)

-- Step 1: Create a stored procedure that checks for a specific condition and raises a
user-defined error

CREATE PROCEDURE CheckSalary

@EmployeeID INT,

@Salary DECIMAL(10, 2)

AS

BEGIN

-- Step 2: Check if the salary provided is negative

IF @Salary < 0

BEGIN

-- Raise a custom error with a message, error number, and state

RAISERROR('Salary cannot be negative.', 16, 1); -- Error severity 16: General errors

RETURN; -- Exit the procedure

END
-- Step 3: Perform a task if the salary is valid (e.g., updating employee salary)

UPDATE Employees

SET Salary = @Salary

WHERE EmployeeID = @EmployeeID;

PRINT 'Salary updated successfully.';

END;

-- Step 4: Execute the stored procedure with valid and invalid input

EXEC CheckSalary @EmployeeID = 1, @Salary = -5000.00; -- This will raise an error

-- Step 5: Handle the error using TRY...CATCH

BEGIN TRY

-- Call the stored procedure with invalid salary

EXEC CheckSalary @EmployeeID = 2, @Salary = -1000.00;

END TRY

BEGIN CATCH

-- Step 6: Catch the error and handle it (e.g., print the error message)

PRINT 'An error occurred: ' + ERROR_MESSAGE();

END CATCH;

-- Step 7: Call with a valid salary to see success


EXEC CheckSalary @EmployeeID = 2, @Salary = 4000.00; -- This will succeed

Explanation:

1. Creating the Procedure:


○ The CheckSalary stored procedure accepts EmployeeID and Salary as
parameters.
○ It checks if the salary is valid (non-negative). If the salary is negative, it raises a
custom error using RAISEERROR.
2. Raising a Custom Error with RAISEERROR:
○ RAISEERROR('message', error_number, state) is used to raise a
user-defined error with a specific message, error number, and state.
■ Example: RAISEERROR('Salary cannot be negative.', 16, 1)
raises an error if the salary is negative.
○ The error severity (16) indicates a general error, and the state (1) can be used to
represent the instance of the error.
3. Handling Errors with TRY...CATCH:
○ The TRY...CATCH block is used to catch and handle errors raised in the
procedure.
○ In the CATCH block, you can retrieve the error message using
ERROR_MESSAGE() and handle the error accordingly.
4. Executing the Procedure:
○ When the procedure is called with a negative salary (-5000 or -1000), the
custom error is raised, and the control jumps to the CATCH block where the error
message is printed.
○ If the salary is valid, the procedure updates the salary and prints a success
message.

Outcome:

● Learners will understand how to create and handle user-defined errors in SQL.
● Gain hands-on experience with using RAISEERROR in SQL Server to raise custom
exceptions for specific business logic errors.
● Learn how to handle these errors using TRY...CATCH and capture detailed
information about the errors that occur during execution.

UNIT 2
1. Cursors: Overview of Cursor, Types of Cursors, Invalid Cursor Exception

Question:

How can you create and use explicit cursors to fetch data, handle cursor exceptions, and
demonstrate invalid cursor handling?

Meaning:

A cursor is a pointer to a context area in SQL that allows you to process query result sets
row by row.

Uses:

Cursors are used when you need to fetch and process rows one at a time, often for complex
logic or row-specific processing.

Script:

-- Step 1: Declare an explicit cursor to fetch employee data

DECLARE @EmployeeID INT, @FirstName NVARCHAR(50), @LastName NVARCHAR(50);

DECLARE employee_cursor CURSOR FOR

SELECT EmployeeID, FirstName, LastName

FROM Employees;

-- Step 2: Open the cursor and fetch data

OPEN employee_cursor;

FETCH NEXT FROM employee_cursor INTO @EmployeeID, @FirstName, @LastName;

-- Step 3: Loop through the cursor and display results

WHILE @@FETCH_STATUS = 0

BEGIN
PRINT 'EmployeeID: ' + CAST(@EmployeeID AS NVARCHAR) + ', Name: ' + @FirstName + ' ' +
@LastName;

FETCH NEXT FROM employee_cursor INTO @EmployeeID, @FirstName, @LastName;

END;

-- Step 4: Close and deallocate the cursor

CLOSE employee_cursor;

DEALLOCATE employee_cursor;

-- Step 5: Example of an invalid cursor exception (trying to fetch after deallocation)

BEGIN TRY

FETCH NEXT FROM employee_cursor INTO @EmployeeID, @FirstName, @LastName; --


This will raise an error

END TRY

BEGIN CATCH

PRINT 'Error: Invalid cursor operation.';

END CATCH;

Explanation:

● An explicit cursor is declared to fetch employee data from the Employees table.
● The cursor processes rows and prints the employee details.
● An error is generated by trying to fetch data after the cursor is deallocated,
demonstrating the invalid cursor exception.

Outcome:

The cursor fetches data correctly until deallocated. When an invalid cursor operation occurs,
the error handling catches and prints the exception message.
2. Static SQL: Description of Static SQL, Cursors Overview

Question:

How can you process query result sets using static SQL with cursors?

Meaning:

Static SQL refers to SQL queries that are predefined and executed without change each time
they run, as opposed to dynamic SQL which can change at runtime.

Uses:

Used when SQL queries are known in advance and do not need to be altered dynamically
during execution.

Script:

-- Step 1: Declare a cursor to fetch all employee data

DECLARE @EmployeeID INT, @FirstName NVARCHAR(50), @Salary DECIMAL(10, 2);

DECLARE employee_cursor CURSOR STATIC FOR

SELECT EmployeeID, FirstName, Salary

FROM Employees;

-- Step 2: Open and fetch data from the cursor

OPEN employee_cursor;

FETCH NEXT FROM employee_cursor INTO @EmployeeID, @FirstName, @Salary;

-- Step 3: Display results

WHILE @@FETCH_STATUS = 0

BEGIN
PRINT 'EmployeeID: ' + CAST(@EmployeeID AS NVARCHAR) + ', FirstName: ' + @FirstName
+ ', Salary: ' + CAST(@Salary AS NVARCHAR);

FETCH NEXT FROM employee_cursor INTO @EmployeeID, @FirstName, @Salary;

END;

-- Step 4: Close and deallocate the cursor

CLOSE employee_cursor;

DEALLOCATE employee_cursor;

Explanation:

● This script demonstrates the use of a STATIC cursor that fetches all employee
records.
● A WHILE loop is used to process and display each row retrieved by the cursor.

Outcome:

It prints each employee’s details. The cursor is static, which means the query doesn’t change
during execution, making the execution efficient.

3. Transaction Processing and Control: Autonomous Transactions, Commit Protocol

Question:

How can you implement autonomous transactions and control commits in SQL?

Meaning:

Autonomous transactions are independent transactions within a main transaction, allowing


operations like commit or rollback without affecting the parent transaction.

Uses:

Used when a transaction must execute independently, for example, logging data while
performing a primary task.

Script:
-- Step 1: Create a stored procedure for autonomous transaction

CREATE PROCEDURE UpdateEmployeeSalary

@EmployeeID INT, @NewSalary DECIMAL(10, 2)

AS

BEGIN

-- Start an autonomous transaction

SAVE TRANSACTION SavePoint;

-- Update the employee salary

UPDATE Employees

SET Salary = @NewSalary

WHERE EmployeeID = @EmployeeID;

-- Commit the autonomous transaction

COMMIT TRANSACTION SavePoint;

END;

-- Step 2: Call the procedure to update salary

EXEC UpdateEmployeeSalary @EmployeeID = 1, @NewSalary = 70000.00;

Explanation:

● A stored procedure is created to update an employee's salary with an autonomous


transaction, ensuring the salary update is committed independently.
● A SAVE TRANSACTION is used to set a point for commit.

Outcome:
The salary update occurs without being affected by the surrounding transaction,
demonstrating the autonomous transaction.

4. Deadlocks Handling

Question:

How can you handle deadlocks in SQL Server?

Meaning:

A deadlock occurs when two transactions are waiting for each other to release resources,
causing the transactions to be stuck indefinitely.

Uses:

Handling deadlocks ensures that a system can recover gracefully from situations where
transactions are stuck.

Script:

-- Step 1: Simulate two transactions causing a deadlock

BEGIN TRANSACTION;

UPDATE Employees SET Salary = 50000 WHERE EmployeeID = 1;

WAITFOR DELAY '00:00:05'; -- Simulate delay

UPDATE Employees SET Salary = 60000 WHERE EmployeeID = 2;

BEGIN TRANSACTION;

UPDATE Employees SET Salary = 60000 WHERE EmployeeID = 2;

WAITFOR DELAY '00:00:05'; -- Simulate delay

UPDATE Employees SET Salary = 50000 WHERE EmployeeID = 1;

-- Step 2: Deadlock will occur, SQL Server will automatically handle and resolve it by
terminating one of the transactions.

Explanation:
● The script simulates a deadlock scenario by having two transactions simultaneously
trying to update different rows that each other hold.
● SQL Server automatically resolves deadlocks by terminating one of the transactions.

Outcome:

A deadlock error is raised, and SQL Server resolves the conflict by terminating one of the
transactions.

5. Dynamic SQL: Native Dynamic SQL, SQL Injection

Question:

How can you prevent SQL injection and implement native dynamic SQL?

Meaning:

Dynamic SQL refers to SQL code that is constructed at runtime, allowing flexibility in query
execution.

Uses:

Used to execute SQL commands that are determined dynamically, such as queries where
table names or column names are provided by the user.

Script:

-- Step 1: Using sp_executesql for dynamic SQL to avoid SQL injection

DECLARE @TableName NVARCHAR(50), @SQL NVARCHAR(1000);

SET @TableName = 'Employees';

SET @SQL = 'SELECT * FROM ' + QUOTENAME(@TableName);

-- Step 2: Execute the dynamic SQL

EXEC sp_executesql @SQL;

Explanation:

● sp_executesql is used to execute dynamic SQL safely, avoiding SQL injection.


● The query is built dynamically to select from a table name defined at runtime.

Outcome:

The dynamic SQL executes successfully without causing SQL injection, as input is properly
sanitized.

6. Triggers: Creating Insert Trigger

Question:

How can you create an insert trigger to enforce data integrity?

Meaning:

A trigger is a database object that automatically executes or fires when certain events occur
in the database, like INSERT, UPDATE, or DELETE.

Uses:

Triggers are useful for enforcing data integrity, logging changes, or auditing database
modifications.

Script:

-- Step 1: Create a trigger to enforce a rule when a new employee is inserted

CREATE TRIGGER trg_insert_employee

ON Employees

AFTER INSERT

AS

BEGIN

DECLARE @Salary DECIMAL(10, 2);

SELECT @Salary = Salary FROM inserted;

-- Step 2: Enforce rule: salary must be greater than 0


IF @Salary <= 0

BEGIN

RAISERROR('Salary must be greater than 0.', 16, 1);

ROLLBACK TRANSACTION;

END;

END;

-- Step 3: Insert a record to test the trigger

INSERT INTO Employees (EmployeeID, FirstName, LastName, Salary)

VALUES (6, 'Tom', 'Hanks', -500); -- This will cause an error due to the trigger

Explanation:

● This trigger ensures that any inserted employee record has a salary greater than 0,
enforcing business rules.
● If the condition fails, the transaction is rolled back with an error message.

Outcome:

If an invalid salary (<= 0) is inserted, the trigger raises an error and prevents the insertion,
maintaining data integrity

7. Triggers: Delete Trigger

Question:

How can you create a delete trigger to enforce data integrity?

Meaning:

A delete trigger fires after a delete operation is executed on a table, often used for auditing or
maintaining integrity.

Uses:
Triggers are used to track deleted data or prevent data from being deleted improperly.

Script:

-- Step 1: Create a delete trigger to log deleted employees

CREATE TRIGGER trg_delete_employee

ON Employees

AFTER DELETE

AS

BEGIN

DECLARE @EmployeeID INT, @FirstName NVARCHAR(50), @LastName NVARCHAR(50);

SELECT @EmployeeID = EmployeeID, @FirstName = FirstName, @LastName = LastName


FROM deleted;

-- Step 2: Log the deleted employee to a separate table

INSERT INTO DeletedEmployeesLog (EmployeeID, FirstName, LastName, DeletedDate)

VALUES (@EmployeeID, @FirstName, @LastName, GETDATE());

END;

-- Step 3: Delete a record to test the trigger

DELETE FROM Employees WHERE EmployeeID = 5;

Explanation:

● The trigger logs deleted employee records into a DeletedEmployeesLog table.


● The delete operation on the Employees table triggers this event.

Outcome:
The employee data is logged into the DeletedEmployeesLog table, providing an audit trail
for deleted records.

8. Packages: Overview of Packages

Question:

How can you create and use a package in PL/SQL?

Meaning:

A package in PL/SQL is a collection of related procedures, functions, variables, and types that
are stored together in the database.

Uses:

Packages provide modularization and easier management of related procedures and


functions, improving performance and reusability.

Script:

-- Step 1: Create a package specification

CREATE OR REPLACE PACKAGE EmployeePackage AS

PROCEDURE UpdateSalary(EmployeeID IN INT, NewSalary IN DECIMAL);

FUNCTION GetEmployeeName(EmployeeID IN INT) RETURN VARCHAR2;

END EmployeePackage;

-- Step 2: Create the package body

CREATE OR REPLACE PACKAGE BODY EmployeePackage AS

PROCEDURE UpdateSalary(EmployeeID IN INT, NewSalary IN DECIMAL) IS

BEGIN

UPDATE Employees

SET Salary = NewSalary


WHERE EmployeeID = EmployeeID;

END UpdateSalary;

FUNCTION GetEmployeeName(EmployeeID IN INT) RETURN VARCHAR2 IS

EmployeeName VARCHAR2(100);

BEGIN

SELECT FirstName || ' ' || LastName INTO EmployeeName

FROM Employees

WHERE EmployeeID = EmployeeID;

RETURN EmployeeName;

END GetEmployeeName;

END EmployeePackage;

-- Step 3: Execute the package procedure

EXEC EmployeePackage.UpdateSalary(1, 80000);

SELECT EmployeePackage.GetEmployeeName(1) FROM dual;

Explanation:

● This script defines a Package with a procedure to update salary and a function to
retrieve employee names.
● The package body implements the logic for these operations.

Outcome:

The procedure updates the salary of an employee, and the function retrieves the full name.
The package encapsulates related functionality.

9. Nested Tables: Creating and Using Nested Tables


Question:

How can you create and work with nested tables in PL/SQL?

Meaning:

A nested table is a table data type that allows you to store multiple values in a single column.

Uses:

Nested tables are used when you need to store collections of items (e.g., a list of employees
within a department) within a row.

Script:
-- Step 1: Create a nested table type
CREATE OR REPLACE TYPE EmployeeTable AS TABLE OF VARCHAR2(50);

-- Step 2: Create a table that uses the nested table type


CREATE TABLE DepartmentEmployees (
DepartmentID INT,
Employees EmployeeTable
) NESTED TABLE Employees STORE AS EmployeesTable;

-- Step 3: Insert data into the nested table


INSERT INTO DepartmentEmployees (DepartmentID, Employees)
VALUES (1, EmployeeTable('John', 'Alice', 'Bob'));

-- Step 4: Query the nested table


SELECT * FROM TABLE((SELECT Employees FROM DepartmentEmployees WHERE DepartmentID
= 1));

Explanation:

● A Nested Table type is created for employee names.


● The DepartmentEmployees table stores a nested table of employees for each department.

Outcome:

The nested table stores employee names and allows querying of the employee list for each
department.

10. Triggers: Update Trigger

Question:
How can you create an update trigger to prevent salary modifications to a specific value?

Meaning:

An update trigger is executed automatically when a record is updated in a table. It can be used to
enforce business rules.

Uses:

Used to prevent certain updates or enforce additional logic during record modification.

Script:
-- Step 1: Create an update trigger
CREATE TRIGGER trg_update_employee_salary
ON Employees
AFTER UPDATE
AS
BEGIN
IF UPDATE(Salary)
BEGIN
DECLARE @OldSalary DECIMAL(10, 2), @NewSalary DECIMAL(10, 2);
SELECT @OldSalary = Salary FROM deleted;
SELECT @NewSalary = Salary FROM inserted;

-- Step 2: Prevent salary modification to a specific value


IF @NewSalary = 100000
BEGIN
RAISERROR('Salary cannot be set to 100000.', 16, 1);
ROLLBACK TRANSACTION;
END;
END;
END;

-- Step 3: Update the salary to test the trigger


UPDATE Employees SET Salary =

Explanation:

● This trigger prevents updates to the salary field if the new salary value is 100000.
● It raises an error and rolls back the transaction if the condition is met.

Outcome:

The update is blocked if the salary is set to 100000, ensuring that the business rule is maintained.

You might also like