Difference Between with Nested Query and Join with example.
A nested query (also called a subquery) in SQL is a query inside another query, often used to
filter data based on results from another table. The JOIN operation is used to combine rows
from two or more tables based on a related column between them.
Let’s explore both concepts with an example:
Example:
We have two tables: Employees and Departments.
Employees table:
EmployeeID EmployeeName DepartmentID
1 Alice 10
2 Bob 20
3 Carol 10
Departments table:
DepartmentID DepartmentName
10 HR
20 IT
Nested Query Example:
Let’s say we want to find all employees who work in the HR department. We first use a
subquery to find the DepartmentID of the HR department.
SELECT EmployeeName
FROM Employees
WHERE DepartmentID = (
SELECT DepartmentID
FROM Departments
WHERE DepartmentName = 'HR'
);
Here, the subquery finds the DepartmentID for the HR department, which is then used by the
outer query to get the names of the employees in that department.
JOIN Operation Example:
To achieve the same result using a JOIN, we can combine the Employees and Departments
tables based on the DepartmentID.
SELECT [Link]
FROM Employees
JOIN Departments ON [Link] = [Link]
WHERE [Link] = 'HR';
In this query, we use the JOIN operation to combine the rows from both tables where the
DepartmentID matches, and we filter for the department name 'HR'.
Nested Query with a JOIN:
We can also combine both techniques. For example, let’s say we want to find employees who
work in a department where at least one employee has an EmployeeID greater than 2:
SELECT EmployeeName
FROM Employees
WHERE DepartmentID IN (
SELECT DepartmentID
FROM Employees
WHERE EmployeeID > 2
);
Simple query optimization:
Simple query optimization focuses on improving query performance using basic techniques
that can significantly reduce the query's execution time and resource usage. Below are some
key techniques for simple query optimization:
1. Use Indexes
Indexes help the database find rows faster by creating a lookup table for specified columns.
They are particularly useful in WHERE clauses, joins, and sorting operations.
Example: Without an index, a query might require a full table scan, which can be slow. Adding
an index can make a huge difference.
Unoptimized query:
SELECT * FROM Customers WHERE City = 'New York';
Optimization: Create an index on the City column:
CREATE INDEX idx_city ON Customers(City);
This allows the query to quickly find the relevant rows based on the City value.
2. Avoid SELECT *
Fetching all columns from a table (SELECT *) is often inefficient because it retrieves
unnecessary data. Instead, select only the columns you need.
Unoptimized query:
SELECT * FROM Customers WHERE City = 'New York';
Optimization: Specify only the columns you need:
SELECT CustomerID, CustomerName FROM Customers WHERE City = 'New York';
This reduces the amount of data retrieved and processed, improving performance.
3. Limit the Number of Rows
If you're only interested in a subset of the results, use LIMIT to restrict the number of rows
returned. This is particularly useful when displaying results in a paginated fashion.
Unoptimized query:
SELECT CustomerID, CustomerName FROM Customers WHERE City = 'New York';
Optimization:
SELECT CustomerID, CustomerName FROM Customers WHERE City = 'New York' LIMIT
10;
This limits the result to 10 rows, reducing the amount of data retrieved and processed.
4. Use Efficient Filtering
Ensure that your WHERE clause is as specific as possible to reduce the number of rows the
database has to scan.
Unoptimized query:
SELECT CustomerID, CustomerName FROM Customers WHERE Age > 30;
Optimization: If you have another condition that narrows down the result set, include it:
SELECT CustomerID, CustomerName FROM Customers WHERE City = 'New York' AND
Age > 30;
Adding more specific filters helps the database limit the number of rows it processes.
5. Avoid Calculations in the WHERE Clause
Calculations or functions in the WHERE clause can slow down a query because they need to
be computed for every row.
Unoptimized query:
SELECT * FROM Orders WHERE YEAR(OrderDate) = 2023;
Optimization: Move the calculation outside the WHERE clause:
SELECT * FROM Orders WHERE OrderDate >= '2023-01-01' AND OrderDate < '2024-01-
01';
This allows the database to use an index on OrderDate if one exists.
6. Use Joins Efficiently
When joining tables, make sure to join on indexed columns and avoid unnecessary joins.
Unoptimized query:
SELECT [Link], [Link]
FROM Customers, Orders
WHERE [Link] = [Link];
Optimization: Use explicit JOIN syntax and ensure that CustomerID is indexed in both tables:
SELECT [Link], [Link]
FROM Customers
JOIN Orders ON [Link] = [Link];
PL/SQL:
PL/SQL (Procedural Language/Structured Query Language) is Oracle Corporation’s
procedural extension for SQL and the Oracle relational database. It is designed to integrate
seamlessly with SQL, allowing for more robust, flexible, and powerful database manipulation.
PL/SQL is used for writing complex queries, creating stored procedures, functions, packages,
and triggers, and adding control structures (such as loops, conditions, and exception handling)
to SQL.
1. Key Features of PL/SQL
PL/SQL extends SQL by adding programming features like:
• Procedural constructs: Loops, conditions (IF-THEN-ELSE), and variables allow for
procedural programming.
• Exception handling: Allows you to handle runtime errors effectively.
• Modularity: Code can be structured into procedures, functions, and packages for reuse
and maintainability.
• Tight integration with SQL: Direct SQL commands (DML, DDL) are supported
within PL/SQL blocks.
• High performance: Due to its tight integration with Oracle databases, PL/SQL often
performs better for complex operations than regular SQL statements.
2. PL/SQL Block Structure
PL/SQL programs are organized into blocks. Every block has the following sections:
• Declaration Section (Optional): Defines variables, constants, and cursors.
• Executable Section (Mandatory): Contains SQL queries and PL/SQL code that gets
executed.
• Exception Section (Optional): Handles errors and exceptions that may occur during
execution.
Syntax:
DECLARE
-- Declarations of variables, cursors, etc.
BEGIN
-- Executable statements (SQL, control structures, etc.)
EXCEPTION
-- Error handling code
END;
3. PL/SQL Variables and Data Types
In the DECLARE section, you can define variables to store data.
DECLARE
v_name VARCHAR2(50); -- Variable declaration
v_age NUMBER; -- Numeric variable declaration
BEGIN
v_name := 'John Doe'; -- Assigning value
v_age := 30;
END;
Common Data Types:
• VARCHAR2(size) – Variable-length string.
• NUMBER(precision, scale) – Numeric values.
• DATE – Date and time values.
• BOOLEAN – TRUE, FALSE, or NULL.
• %TYPE – Allows a variable to inherit the data type of a database column.
4. Control Structures
PL/SQL supports procedural programming constructs like loops and conditional logic.
IF-THEN-ELSE Statement:
IF v_age > 18 THEN
DBMS_OUTPUT.PUT_LINE('Adult');
ELSE
DBMS_OUTPUT.PUT_LINE('Minor');
END IF;
Loops:
1. Basic Loop:
LOOP
-- Code to execute
EXIT WHEN condition;
END LOOP;
2. FOR Loop:
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
3. WHILE Loop:
WHILE condition LOOP
-- Code to execute
END LOOP;
5. PL/SQL Cursors
Cursors are used to fetch and process rows returned by a query.
• Implicit Cursor: Automatically created for single SELECT statements.
Example: DECLARE
v_customer_name [Link]%TYPE;
BEGIN
-- This SELECT statement creates an implicit cursor
SELECT CustomerName INTO v_customer_name
FROM Customers
WHERE CustomerID = 101;
DBMS_OUTPUT.PUT_LINE('Customer Name: ' || v_customer_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No customer found with ID 101.');
END;
• Explicit Cursor: Defined explicitly by the programmer for more control.
Example: DECLARE
-- Declare the cursor
CURSOR cur_customers IS
SELECT CustomerID, CustomerName
FROM Customers
WHERE City = 'New York';
-- Variables to hold the fetched values
v_customer_id [Link]%TYPE;
v_customer_name [Link]%TYPE;
BEGIN
-- Open the cursor
OPEN cur_customers;
-- Loop through the cursor and fetch each row
LOOP
FETCH cur_customers INTO v_customer_id, v_customer_name;
EXIT WHEN cur_customers%NOTFOUND; -- Exit when no more rows to fetch
-- Output the fetched data
DBMS_OUTPUT.PUT_LINE('Customer ID: ' || v_customer_id || ', Name: ' ||
v_customer_name);
END LOOP;
-- Close the cursor
CLOSE cur_customers;
END;
6. Stored Procedures and Functions
Stored Procedures:
A stored procedure is a subprogram that performs a specific task and doesn’t return a value.
CREATE OR REPLACE PROCEDURE greet_user (p_name IN VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, ' || p_name);
END;
Stored Functions:
A stored function returns a single value.
CREATE OR REPLACE FUNCTION get_total_sales (p_customer_id IN NUMBER)
RETURN NUMBER IS
v_total_sales NUMBER;
BEGIN
SELECT SUM(OrderAmount) INTO v_total_sales
FROM Orders
WHERE CustomerID = p_customer_id;
RETURN v_total_sales;
END;
7. Packages
A package is a collection of related procedures, functions, variables, and cursors grouped
together.
Example:
CREATE OR REPLACE PACKAGE customer_pkg AS
PROCEDURE add_customer(p_name VARCHAR2, p_age NUMBER);
FUNCTION get_customer(p_customer_id NUMBER) RETURN VARCHAR2;
END customer_pkg;
8. Triggers
A trigger is a special kind of stored procedure that automatically runs when a certain event
occurs in the database, such as insert, update, or delete operations.
Example:
CREATE OR REPLACE TRIGGER trg_after_insert
AFTER INSERT ON Customers
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('New customer inserted: ' || :[Link]);
END;
• :NEW refers to the new row being inserted.
• :OLD refers to the existing row (in UPDATE or DELETE triggers).
9. Exception Handling
PL/SQL provides mechanisms to handle runtime errors using the EXCEPTION block.
Syntax:
BEGIN
-- Code that may cause an exception
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An unknown error occurred');
END;
10. Common Built-in Functions and Procedures
Oracle provides several built-in functions and procedures, such as:
• DBMS_OUTPUT.PUT_LINE: Outputs data to the console (for debugging purposes).
• SYSDATE: Returns the current date and time.
• TO_CHAR: Converts a date to a string.
• TO_DATE: Converts a string to a date.