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

PL SQL Key Concepts Examples

jio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

PL SQL Key Concepts Examples

jio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

PL/SQL Key Concepts and Examples

Collections (Arrays)
PL/SQL provides associative arrays, nested tables, and VARRAYs for collection handling.

Example:
DECLARE
TYPE num_table IS TABLE OF NUMBER;
numbers num_table := num_table(1, 2, 3, 4, 5);
BEGIN
FOR i IN 1..numbers.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Number: ' || numbers(i));
END LOOP;
END;

Dynamic SQL
Dynamic SQL allows you to execute SQL statements that are constructed at runtime.

Example:
DECLARE
table_name VARCHAR2(30) := 'employees';
column_name VARCHAR2(30) := 'salary';
new_value NUMBER := 1000;
BEGIN
EXECUTE IMMEDIATE 'UPDATE ' || table_name || ' SET ' || column_name || ' = :1 WHERE
employee_id = 101'
USING new_value;
DBMS_OUTPUT.PUT_LINE('Salary updated successfully.');
END;

Bulk Collect and FORALL


BULK COLLECT allows you to retrieve multiple rows into a collection at once, making it
faster for handling large data.
FORALL is used for bulk processing of SQL statements, improving performance for multiple
DML operations.

Example: Bulk Collect


DECLARE
TYPE num_table IS TABLE OF NUMBER;
salaries num_table;
BEGIN
SELECT salary BULK COLLECT INTO salaries FROM employees WHERE department_id =
10;
FOR i IN 1..salaries.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Salary: ' || salaries(i));
END LOOP;
END;

Example: FORALL
DECLARE
TYPE num_table IS TABLE OF NUMBER;
emp_ids num_table := num_table(101, 102, 103);
BEGIN
FORALL i IN emp_ids.FIRST..emp_ids.LAST
UPDATE employees SET salary = salary + 500 WHERE employee_id = emp_ids(i);
DBMS_OUTPUT.PUT_LINE('Salaries updated.');
END;

Types of PL/SQL Collections


Associative Arrays: Indexed by strings or integers.

Example:
DECLARE
TYPE emp_name_type IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;
emp_names emp_name_type;
BEGIN
emp_names(1) := 'Habib';
emp_names(2) := 'Himel';
FOR i IN 1..emp_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Employee ' || i || ': ' || emp_names(i));
END LOOP;
END;

Advanced Triggers
INSTEAD OF Trigger: Used on views to handle DML operations that aren't possible directly
on views.

Example:
CREATE OR REPLACE VIEW emp_view AS
SELECT employee_id, first_name, last_name FROM employees WHERE department_id =
10;

CREATE OR REPLACE TRIGGER trg_emp_view_insert


INSTEAD OF INSERT ON emp_view
FOR EACH ROW
BEGIN
INSERT INTO employees (employee_id, first_name, last_name, department_id)
VALUES (:NEW.employee_id, :NEW.first_name, :NEW.last_name, 10);
END;

Records and PL/SQL Tables


A record is a composite data structure that groups related data.
PL/SQL Tables (nested tables and associative arrays) can store records, providing a way to
handle complex data structures.

Example:
DECLARE
TYPE emp_record_type IS RECORD (
employee_id employees.employee_id%TYPE,
first_name employees.first_name%TYPE,
salary employees.salary%TYPE
);
emp_record emp_record_type;
BEGIN
SELECT employee_id, first_name, salary INTO emp_record
FROM employees WHERE employee_id = 101;
DBMS_OUTPUT.PUT_LINE('Employee ID: ' || emp_record.employee_id || ', Name: ' ||
emp_record.first_name || ', Salary: ' || emp_record.salary);
END;

Error Logging and Custom Error Messages


Use RAISE_APPLICATION_ERROR to throw custom error messages and SQLCODE and
SQLERRM to capture error information.

Example:
DECLARE
invalid_salary EXCEPTION;
salary NUMBER := -100;
BEGIN
IF salary < 0 THEN
RAISE invalid_salary;
END IF;
EXCEPTION
WHEN invalid_salary THEN
DBMS_OUTPUT.PUT_LINE('Error: Salary cannot be negative');
RAISE_APPLICATION_ERROR(-20001, 'Invalid salary detected: ' || salary);
END;
Pipelined Table Functions
Pipelined table functions return a set of rows as a table that can be queried directly using
SQL.

Example:
CREATE OR REPLACE TYPE number_list AS TABLE OF NUMBER;
CREATE OR REPLACE FUNCTION get_numbers (n IN NUMBER)
RETURN number_list PIPELINED IS
BEGIN
FOR i IN 1..n LOOP
PIPE ROW(i);
END LOOP;
RETURN;
END;

-- Using the pipelined function


SELECT * FROM TABLE(get_numbers(5));

PL/SQL Table Functions and Parallel Processing


It allows to use table functions in parallel to handle large datasets efficiently. By setting the
table function as parallel-enabled, it can process data in parallel threads.

Example:
CREATE OR REPLACE FUNCTION parallel_table_function(p_max NUMBER)
RETURN NUMBER_TABLE PIPELINED PARALLEL_ENABLE IS
BEGIN
FOR i IN 1..p_max LOOP
PIPE ROW(i);
END LOOP;
END;

SELECT * FROM TABLE(parallel_table_function(1000));

User-Defined Object Types


Object types allow defining complex data structures that can be stored as a single column in
a table or passed to PL/SQL procedures.

Example:
CREATE OR REPLACE TYPE person_type AS OBJECT (
first_name VARCHAR2(50),
last_name VARCHAR2(50),
birthdate DATE
);
DECLARE
person person_type := person_type('Habib', 'Himel', TO_DATE('1997-02-28', 'YYYY-MM-
DD'));
BEGIN
DBMS_OUTPUT.PUT_LINE('Name: ' || person.first_name || ' ' || person.last_name);
END;

PL/SQL Performance Optimization


NOCOPY Hint: Allows PL/SQL to pass large objects (like collections) by reference instead of
by value, saving memory and improving performance.

Example:
CREATE OR REPLACE PROCEDURE update_employee_salary (
emp_id IN NUMBER,
new_salary IN OUT NOCOPY NUMBER
) IS
BEGIN
UPDATE employees SET salary = new_salary WHERE employee_id = emp_id;
DBMS_OUTPUT.PUT_LINE('Salary updated for employee ' || emp_id);
END;

Using PRAGMA DIRECTIVES


Pragmas are compiler directives that optimize specific aspects of PL/SQL code.
PRAGMA EXCEPTION_INIT: Associates an exception with an Oracle error number.

Example:
DECLARE
insufficient_balance EXCEPTION;
PRAGMA EXCEPTION_INIT(insufficient_balance, -20000);
BEGIN
-- Attempt some operation that could trigger error -20000
EXCEPTION
WHEN insufficient_balance THEN
DBMS_OUTPUT.PUT_LINE('Error: Insufficient balance');
END;

Ref Cursors
Ref cursors (or cursor variables) define a cursor whose query is determined at runtime.

Example:
DECLARE
TYPE ref_cursor_type IS REF CURSOR;
emp_cursor ref_cursor_type;
emp_record employees%ROWTYPE;
BEGIN
OPEN emp_cursor FOR SELECT * FROM employees WHERE department_id = 10;
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Employee: ' || emp_record.first_name || ' ' ||
emp_record.last_name);
END LOOP;
CLOSE emp_cursor;
END;

Using SYS_REFCURSOR for Dynamic Queries


SYS_REFCURSOR is a predefined ref cursor type in PL/SQL, simplifying the code by not
requiring explicit type declarations.

Example:
DECLARE
cur SYS_REFCURSOR;
emp_name VARCHAR2(50);
BEGIN
OPEN cur FOR 'SELECT first_name FROM employees WHERE employee_id = :id' USING
101;
FETCH cur INTO emp_name;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_name);
CLOSE cur;
END;

Fine-Grained Auditing (FGA)


Fine-grained auditing enables capturing specific query information based on a particular
condition, such as capturing sensitive data access.

Example:
BEGIN
DBMS_FGA.ADD_POLICY(
object_schema => 'CBS',
object_name => 'employees',
policy_name => 'sensitive_data_access',
audit_condition => 'salary > 50000',
audit_column => 'salary'
);
END;
More Example:
1.

create or replace FUNCTION VC2CLOB_FROM_BLOB(B BLOB)

RETURN CLOB

IS

c CLOB;

chunk_size CONSTANT NUMBER := 32767; -- chunk size for reading

start_pos NUMBER := 1;

bytes_read NUMBER;

buffer VARCHAR2(32767);

BEGIN

IF (B IS NULL) THEN

RETURN NULL;

END IF;

IF (DBMS_LOB.GETLENGTH(B) = 0) THEN

RETURN EMPTY_CLOB();

END IF;

DBMS_LOB.CREATETEMPORARY(c, TRUE);

DBMS_LOB.OPEN(c, DBMS_LOB.LOB_READWRITE);

WHILE start_pos <= DBMS_LOB.GETLENGTH(B) LOOP

bytes_read := LEAST(chunk_size, DBMS_LOB.GETLENGTH(B) - start_pos + 1);

buffer := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(B, bytes_read,


start_pos));
DBMS_LOB.WRITEAPPEND(c, LENGTH(buffer), buffer);

start_pos := start_pos + bytes_read;

END LOOP;

DBMS_LOB.CLOSE(c);

RETURN c;

END;

2.

create or replace FUNCTION SPLIT_CLOB_TO_ROWS(clob_data CLOB, delimiter VARCHAR2)


RETURN SYS.ODCIVARCHAR2LIST PIPELINED IS

pos PLS_INTEGER := 1;

next_pos PLS_INTEGER;

BEGIN

LOOP

next_pos := INSTR(clob_data, delimiter, pos);

IF next_pos = 0 THEN

PIPE ROW (TRIM(SUBSTR(clob_data,pos)));

EXIT;

END IF;

PIPE ROW (TRIM(SUBSTR(clob_data, pos,next_pos - pos)));

pos := next_pos + LENGTH(delimiter);

END LOOP;

RETURN;

END SPLIT_CLOB_TO_ROWS;

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy