এখানে কয়েকটি বাস্তব উদাহরণ এবং ডেমো দেওয়া হলো, যেগুলি PL/SQL এর বিভিন্ন বৈশিষ্ট্য এবং ফিচার ব্যবহার করে তৈরি করা হয়েছে। এই উদাহরণগুলির মাধ্যমে PL/SQL কোডিং এবং এর ব্যবহার বুঝতে সহায়তা পাওয়া যাবে।
1. PL/SQL ব্লক উদাহরণ
এই উদাহরণটি একটি সাধারণ PL/SQL ব্লক যা একটি ভেরিয়েবল ডিক্লেয়ার করে, মান প্রদান করে এবং সেটি প্রদর্শন করে।
DECLARE
v_emp_name VARCHAR2(50); -- ভেরিয়েবল ডিক্লেয়ার করা হচ্ছে
BEGIN
v_emp_name := 'John Doe'; -- ভেরিয়েবলে মান অ্যাসাইন করা হচ্ছে
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_emp_name); -- ভেরিয়েবলের মান প্রিন্ট করা হচ্ছে
END;
ব্যাখ্যা:
- DECLARE: ভেরিয়েবল ডিক্লেয়ার করা হয়।
- BEGIN: কোড ব্লক শুরু হয়।
- DBMS_OUTPUT.PUT_LINE: ভেরিয়েবলের মান আউটপুট হিসেবে প্রদর্শন করা হয়।
আউটপুট:
Employee Name: John Doe
2. PL/SQL ফাংশন উদাহরণ
এই উদাহরণে একটি ফাংশন তৈরি করা হচ্ছে যা দুটি ইনপুট নেওয়ার পর তাদের যোগফল প্রদান করবে।
CREATE OR REPLACE FUNCTION add_numbers(p_num1 IN NUMBER, p_num2 IN NUMBER)
RETURN NUMBER
IS
v_result NUMBER; -- ফাংশনের রিটার্ন ভ্যালু
BEGIN
v_result := p_num1 + p_num2; -- ইনপুট সংখ্যা যোগফল বের করা হচ্ছে
RETURN v_result; -- ফলাফল ফেরত দেওয়া হচ্ছে
END;
/
-- ফাংশন কল করা
DECLARE
v_sum NUMBER;
BEGIN
v_sum := add_numbers(10, 20); -- ফাংশন কল করা হচ্ছে
DBMS_OUTPUT.PUT_LINE('Sum: ' || v_sum); -- আউটপুট প্রিন্ট করা হচ্ছে
END;
ব্যাখ্যা:
- CREATE FUNCTION: ফাংশন তৈরি করা হচ্ছে যা দুটি ইনপুট নেয় এবং তাদের যোগফল ফেরত দেয়।
- DBMS_OUTPUT.PUT_LINE: ফাংশন থেকে প্রাপ্ত মান আউটপুট হিসেবে প্রদর্শন করা হচ্ছে।
আউটপুট:
Sum: 30
3. PL/SQL প্রোসিডিউর উদাহরণ
এখানে একটি প্রোসিডিউর তৈরি করা হচ্ছে যা নির্দিষ্ট টেবিল থেকে তথ্য নিয়ে প্রদর্শন করবে।
CREATE OR REPLACE PROCEDURE get_employee_details (p_emp_id IN NUMBER)
IS
v_emp_name VARCHAR2(50); -- ভেরিয়েবল ডিক্লেয়ার করা হচ্ছে
v_emp_salary NUMBER;
BEGIN
SELECT employee_name, salary
INTO v_emp_name, v_emp_salary
FROM employees
WHERE employee_id = p_emp_id; -- নির্দিষ্ট employee_id এর জন্য তথ্য নেয়া হচ্ছে
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_emp_name);
DBMS_OUTPUT.PUT_LINE('Salary: ' || v_emp_salary);
END;
/
-- প্রোসিডিউর কল করা
BEGIN
get_employee_details(101); -- employee_id 101 এর জন্য প্রোসিডিউর কল করা হচ্ছে
END;
ব্যাখ্যা:
- CREATE PROCEDURE: একটি প্রোসিডিউর তৈরি করা হচ্ছে যা একটি employee_id ইনপুট হিসেবে নেয় এবং সেই নির্দিষ্ট employee এর নাম এবং বেতন প্রদর্শন করে।
- DBMS_OUTPUT.PUT_LINE: প্রোসিডিউরের আউটপুট প্রদর্শন করা হচ্ছে।
আউটপুট:
Employee Name: Alice
Salary: 5000
4. PL/SQL Cursor উদাহরণ
এখানে একটি Cursor ব্যবহার করা হচ্ছে যার মাধ্যমে একাধিক রেকর্ড নিয়ে কাজ করা হচ্ছে।
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, employee_name FROM employees WHERE department_id = 10;
v_emp_id employees.employee_id%TYPE;
v_emp_name employees.employee_name%TYPE;
BEGIN
OPEN emp_cursor; -- Cursor খুলে দেওয়া হচ্ছে
LOOP
FETCH emp_cursor INTO v_emp_id, v_emp_name; -- রেকর্ড গুলি ফেচ করা হচ্ছে
EXIT WHEN emp_cursor%NOTFOUND; -- যদি কোনো রেকর্ড না থাকে তবে লুপ বের হয়ে যাবে
DBMS_OUTPUT.PUT_LINE('Employee ID: ' || v_emp_id || ' Name: ' || v_emp_name);
END LOOP;
CLOSE emp_cursor; -- Cursor বন্ধ করা হচ্ছে
END;
ব্যাখ্যা:
- CURSOR: একটি Cursor ডিক্লেয়ার করা হচ্ছে যা নির্দিষ্ট একটি department_id এর ভিত্তিতে employee_id এবং employee_name ফেচ করবে।
- FETCH: কুয়েরি থেকে রেকর্ড নিয়ে ভেরিয়েবলে সেট করা হচ্ছে।
- EXIT WHEN: যদি রেকর্ড না থাকে তবে লুপ বন্ধ হবে।
- DBMS_OUTPUT.PUT_LINE: প্রতি রেকর্ডের তথ্য আউটপুট হিসেবে প্রদর্শন করা হচ্ছে।
আউটপুট:
Employee ID: 101 Name: Alice
Employee ID: 102 Name: Bob
...
5. PL/SQL Exception Handling উদাহরণ
এখানে একটি Exception Handling উদাহরণ দেওয়া হচ্ছে যাতে SQL ত্রুটি সঠিকভাবে ধরতে এবং তা সঠিকভাবে পরিচালনা করতে পারি।
DECLARE
v_salary employees.salary%TYPE;
BEGIN
SELECT salary INTO v_salary FROM employees WHERE employee_id = 999; -- ভুল employee_id, এটি কোনো রেকর্ড ফেরত দিবে না
DBMS_OUTPUT.PUT_LINE('Salary: ' || v_salary);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Error: Employee not found!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Unknown error occurred.');
END;
ব্যাখ্যা:
- EXCEPTION: এর মাধ্যমে SQL ত্রুটি পরিচালনা করা হচ্ছে।
- NO_DATA_FOUND: যদি কোনো রেকর্ড না পাওয়া যায় তবে এটি কাস্টম ত্রুটি বার্তা দিবে।
- OTHERS: অন্য কোনো ত্রুটি ধরা পড়লে এটি একটি সাধারণ ত্রুটি বার্তা দিবে।
আউটপুট:
Error: Employee not found!
উপসংহার
এই উদাহরণগুলো PL/SQL এর বিভিন্ন ফিচার যেমন ভেরিয়েবল, ফাংশন, প্রোসিডিউর, কনট্রোল স্টেটমেন্ট, কার্সর, এবং এক্সসেপশন হ্যান্ডলিং এর ব্যবহার দেখিয়েছে। PL/SQL এর এই ক্ষমতাগুলি ব্যবহার করে আপনি সহজেই ডেটাবেস অপারেশনগুলোকে স্বয়ংক্রিয় করতে পারবেন এবং কর্মক্ষমতা উন্নত করতে পারবেন।
PL/SQL তে Procedure এবং Function দুটি গুরুত্বপূর্ণ অংশ, যেগুলি কোড পুনঃব্যবহারযোগ্য করতে এবং বিভিন্ন ডাটাবেস অপারেশনকে সহজ এবং দ্রুত করতে ব্যবহৃত হয়। নিচে, আমরা Procedure এবং Function এর বাস্তব উদাহরণ দেখবো।
১. Procedure উদাহরণ
PL/SQL Procedure হল এমন একটি স্টোরড প্রোগ্রাম যা কোনও নির্দিষ্ট কাজ সম্পন্ন করে এবং কোন ভ্যালু রিটার্ন করে না। প্রোসিডিউর সাধারণত ডেটাবেসে পরিবর্তন আনার জন্য ব্যবহৃত হয়, যেমন ইনসার্ট, আপডেট বা ডিলিট।
উদাহরণ: একটি প্রোসিডিউর যা একজন কর্মচারীর বেতন আপডেট করবে
ধরা যাক, আমাদের একটি employees নামক টেবিল রয়েছে এবং আমরা একটি প্রোসিডিউর তৈরি করতে চাই যা নির্দিষ্ট কর্মচারীর employee_id এর ভিত্তিতে তাদের বেতন আপডেট করবে।
CREATE OR REPLACE PROCEDURE update_employee_salary(
p_employee_id IN employees.employee_id%TYPE,
p_salary IN employees.salary%TYPE
)
IS
BEGIN
UPDATE employees
SET salary = p_salary
WHERE employee_id = p_employee_id;
-- Commit the changes
COMMIT;
DBMS_OUTPUT.PUT_LINE('Salary updated successfully!');
END;
/
ব্যাখ্যা:
- Procedure নাম:
update_employee_salary - Parameter: দুটি ইনপুট প্যারামিটার আছে -
p_employee_idএবংp_salary। এই প্যারামিটারগুলির মাধ্যমে আমরা কর্মচারীরemployee_idএবং আপডেট করার জন্য নতুন বেতন পাস করব। - কাজ: এই প্রোসিডিউরটি কর্মচারীর বেতন আপডেট করবে এবং তারপরে একটি সফল বার্তা প্রিন্ট করবে।
প্রোসিডিউর কল করা:
BEGIN
update_employee_salary(1001, 55000);
END;
/
এখানে, 1001 হল কর্মচারীর আইডি এবং 55000 হল নতুন বেতন। এই কলটি প্রোসিডিউরটি চালাবে এবং নির্দিষ্ট কর্মচারীর বেতন আপডেট করবে।
২. Function উদাহরণ
PL/SQL Function হল একটি স্টোরড প্রোগ্রাম যা একটি মান রিটার্ন করে। ফাংশন সাধারণত গণনা বা ডেটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়, যেখানে একটি মান রিটার্ন করা প্রয়োজন।
উদাহরণ: একটি ফাংশন যা কর্মচারীর বেতন বৃদ্ধি হিসাব করবে
ধরা যাক, আমাদের একটি ফাংশন তৈরি করতে হবে যা একটি নির্দিষ্ট কর্মচারীর বেতন এবং বেতন বৃদ্ধি শতাংশ নিয়ে তার নতুন বেতন রিটার্ন করবে।
CREATE OR REPLACE FUNCTION calculate_new_salary(
p_employee_id IN employees.employee_id%TYPE,
p_increase_percentage IN NUMBER
)
RETURN NUMBER
IS
v_current_salary employees.salary%TYPE;
v_new_salary NUMBER;
BEGIN
-- Get the current salary of the employee
SELECT salary INTO v_current_salary
FROM employees
WHERE employee_id = p_employee_id;
-- Calculate the new salary
v_new_salary := v_current_salary + (v_current_salary * p_increase_percentage / 100);
-- Return the new salary
RETURN v_new_salary;
END;
/
ব্যাখ্যা:
- Function নাম:
calculate_new_salary - Parameters:
p_employee_id(কর্মচারীর আইডি) এবংp_increase_percentage(বেতন বৃদ্ধির শতাংশ)। - Return Type:
NUMBER, কারণ ফাংশনটি নতুন বেতনটি রিটার্ন করবে। - কাজ: এই ফাংশনটি প্রথমে কর্মচারীর বর্তমান বেতন পাবে, তারপর বেতন বৃদ্ধির শতাংশের ভিত্তিতে নতুন বেতন হিসাব করবে এবং সেই নতুন বেতনটি রিটার্ন করবে।
ফাংশন কল করা:
DECLARE
v_new_salary NUMBER;
BEGIN
v_new_salary := calculate_new_salary(1001, 10);
DBMS_OUTPUT.PUT_LINE('The new salary is: ' || v_new_salary);
END;
/
এখানে, 1001 হল কর্মচারীর আইডি এবং 10 হল বেতন বৃদ্ধির শতাংশ (১০% বৃদ্ধি)। ফাংশনটি কল করে এবং নতুন বেতন প্রিন্ট করে।
প্রধান পার্থক্য:
| Feature | Procedure | Function |
|---|---|---|
| Return Value | Return করে না (void) | Return করে একটি মান (value) |
| Usage | সাধারণত ডেটা পরিবর্তন (INSERT, UPDATE, DELETE) | সাধারণত মান গণনা (Computation) |
| Call | কল করা হয় CALL অথবা BEGIN...END | কল করা হয় SELECT বা অন্য ফাংশন থেকে |
উপসংহার:
- Procedure সাধারণত ডেটাবেসে কিছু কার্যক্রম পরিচালনা করতে ব্যবহৃত হয়, যেমন তথ্য আপডেট করা বা ইনসার্ট করা, এবং এটি কোন মান রিটার্ন করে না।
- Function একটি নির্দিষ্ট মান রিটার্ন করে এবং সাধারণত মান গণনা বা ডেটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়।
PL/SQL তে Cursor এবং Collection দুটি গুরুত্বপূর্ণ কনসেপ্ট, যা ডেটাবেস অপারেশন পরিচালনার জন্য ব্যবহৃত হয়। এগুলি বিশেষ করে বড় পরিমাণের ডেটা পরিচালনা এবং বিভিন্ন ধরনের ডেটা প্রক্রিয়া করার সময় গুরুত্বপূর্ণ ভূমিকা পালন করে।
1. PL/SQL Cursor
Cursor হলো একটি ডেটাবেস অবজেক্ট, যা SQL কোয়েরির ফলাফল (result set) ধারাবাহিকভাবে প্রসেস করতে ব্যবহৃত হয়। PL/SQL তে, কুয়েরি চালানোর পর রিটার্ন হওয়া একাধিক রেকর্ড বা রো (row) প্রসেস করতে কুরসরের ব্যবহার করা হয়। কুরসরের মাধ্যমে একসাথে একাধিক রেকর্ডের উপর অপারেশন করা যায়।
Cursor এর দুটি ধরন:
- Implicit Cursor (অপেক্ষাকৃত কুরসর):
- Oracle স্বয়ংক্রিয়ভাবে একটি কুয়েরি চালানোর জন্য Implicit Cursor ব্যবহার করে, যেমন
SELECT INTOকোডে। আপনি সাধারণত এটি ই explicitly ডিক্লেয়ার করেন না। উদাহরণ:
DECLARE v_name VARCHAR2(50); BEGIN SELECT first_name INTO v_name FROM employees WHERE employee_id = 100; DBMS_OUTPUT.PUT_LINE(v_name); END;
- Oracle স্বয়ংক্রিয়ভাবে একটি কুয়েরি চালানোর জন্য Implicit Cursor ব্যবহার করে, যেমন
- Explicit Cursor (স্পষ্ট কুরসর):
- Explicit Cursor আপনি নিজেরাই ডিক্লেয়ার করে ব্যবহার করেন। এটি সাধারণত একাধিক রেকর্ড রিটার্ন করার জন্য ব্যবহৃত হয়। এর মাধ্যমে, কুয়েরি এক্সিকিউট করার পর প্রতিটি রেকর্ড একে একে প্রসেস করা যায়।
উদাহরণ:
DECLARE CURSOR emp_cursor IS SELECT first_name, last_name FROM employees; v_first_name employees.first_name%TYPE; v_last_name employees.last_name%TYPE; BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO v_first_name, v_last_name; EXIT WHEN emp_cursor%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Employee: ' || v_first_name || ' ' || v_last_name); END LOOP; CLOSE emp_cursor; END;
Cursor Attributes:
PL/SQL তে, কুরসরের বিভিন্ন স্টেটাস চেক করার জন্য কিছু predefined attributes আছে:
%FOUND: যদি রেকর্ড পাওয়া যায় তবে এটি TRUE।%NOTFOUND: যদি রেকর্ড না পাওয়া যায় তবে এটি TRUE।%ROWCOUNT: মোট কতটি রেকর্ড ফেচ করা হয়েছে তা জানায়।%ISOPEN: কুরসরটি খোলা রয়েছে কিনা তা চেক করে।
2. PL/SQL Collections
Collection হলো একটি ডেটা স্ট্রাকচার, যা একাধিক ভ্যালু একই টাইপের ভ্যারিয়েবল সংরক্ষণ করতে ব্যবহৃত হয়। PL/SQL এ প্রধানত তিন ধরনের কোলেকশন ব্যবহৃত হয়:
- Associative Arrays (Index-By Tables) – এই কোলেকশনটি একটি অ্যারে বা ম্যাপের মত কাজ করে, যেখানে ইনডেক্স হিসেবে বিভিন্ন ধরনের ডাটা ব্যবহার করা যেতে পারে (যেমন সংখ্যামূলক বা স্ট্রিং ইনডেক্স)।
- Nested Tables – এটি একটি অ্যারে হিসাবে কাজ করে, কিন্তু ইনডেক্স শূন্য থেকে শুরু হতে পারে এবং একটি টেবিলের মতো ডাটা সংরক্ষণ করে।
- VARRAY (Variable-Size Arrays) – এটি একটি অ্যারে যা একটি নির্দিষ্ট আকার ধারণ করে এবং এটি একটি সীমাবদ্ধ সংখ্যক উপাদান ধারণ করতে পারে।
Collection এর উদাহরণ:
- Associative Array Example:
DECLARE
TYPE name_array IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;
employees name_array;
BEGIN
employees(1) := 'John';
employees(2) := 'Mary';
employees(3) := 'James';
DBMS_OUTPUT.PUT_LINE('Employee at index 1: ' || employees(1));
DBMS_OUTPUT.PUT_LINE('Employee at index 2: ' || employees(2));
DBMS_OUTPUT.PUT_LINE('Employee at index 3: ' || employees(3));
END;
এখানে, employees নামক একটি অ্যাসোসিয়েটিভ অ্যারে ডিক্লেয়ার করা হয়েছে, যা VARCHAR2(50) টাইপের ডাটা ধারণ করবে এবং ইনডেক্স হিসেবে সংখ্যা ব্যবহার করা হচ্ছে।
- Nested Table Example:
DECLARE
TYPE emp_table IS TABLE OF VARCHAR2(50);
emp_names emp_table;
BEGIN
emp_names := emp_table('John', 'Mary', 'James');
FOR i IN 1..emp_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Employee ' || i || ': ' || emp_names(i));
END LOOP;
END;
এখানে, emp_names নামক একটি নেস্টেড টেবিল ডিক্লেয়ার করা হয়েছে এবং তাতে কিছু ভ্যালু অ্যাসাইন করা হয়েছে। তারপর একটি লুপের মাধ্যমে প্রতিটি ভ্যালু প্রিন্ট করা হচ্ছে।
- VARRAY Example:
DECLARE
TYPE dept_array IS VARRAY(3) OF VARCHAR2(50);
departments dept_array;
BEGIN
departments := dept_array('HR', 'Finance', 'IT');
FOR i IN 1..departments.LIMIT LOOP
DBMS_OUTPUT.PUT_LINE('Department ' || i || ': ' || departments(i));
END LOOP;
END;
এখানে, departments নামক একটি ভ্যারিয়েবল সাইজ অ্যারে ডিক্লেয়ার করা হয়েছে যা সর্বোচ্চ ৩টি ডিপার্টমেন্টের নাম ধারণ করতে পারে।
Collection Methods:
PL/SQL তে কোলেকশন পরিচালনার জন্য কিছু built-in মেথড ব্যবহার করা হয়। কিছু সাধারণ মেথড নিচে দেওয়া হলো:
EXTEND: কোলেকশনে নতুন আইটেম যোগ করার জন্য ব্যবহৃত হয়।DELETE: কোলেকশন থেকে একটি বা একাধিক আইটেম মুছে ফেলার জন্য ব্যবহৃত হয়।EXISTS: চেক করে যে কোলেকশনে নির্দিষ্ট ইনডেক্সে আইটেমটি রয়েছে কিনা।COUNT: কোলেকশনের আইটেমের সংখ্যা ফেরত দেয়।
উদাহরণ:
DECLARE
TYPE dept_array IS TABLE OF VARCHAR2(50);
departments dept_array;
BEGIN
-- কোলেকশন তৈরি এবং একাধিক আইটেম যোগ করা
departments := dept_array('HR', 'Finance', 'IT');
departments.EXTEND;
departments(4) := 'Marketing';
DBMS_OUTPUT.PUT_LINE('Total Departments: ' || departments.COUNT);
-- এক আইটেম মুছে ফেলা
departments.DELETE(2);
DBMS_OUTPUT.PUT_LINE('Total Departments after deletion: ' || departments.COUNT);
END;
এখানে EXTEND এবং DELETE মেথড ব্যবহার করা হয়েছে কোলেকশনের আইটেম বাড়ানোর এবং মুছে ফেলার জন্য।
Cursor এবং Collection এর কম্বিনেশন
Cursor এবং Collection একসাথে ব্যবহার করা হয় যখন আপনি অনেক রেকর্ড নিয়ে কাজ করছেন এবং সেই রেকর্ডগুলিকে কোলেকশনে ধারণ করতে চান। উদাহরণস্বরূপ, আপনি একটি cursor ব্যবহার করে ডেটা রিটার্ন করতে পারেন এবং তারপর সেই ডেটা একটি collection এ ফেচ করে প্রয়োজনে প্রসেস করতে পারেন।
উদাহরণ:
DECLARE
TYPE emp_table IS TABLE OF VARCHAR2(50);
emp_names emp_table;
CURSOR emp_cursor IS
SELECT first_name FROM employees WHERE department_id = 10;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor BULK COLLECT INTO emp_names LIMIT 100;
EXIT WHEN emp_cursor%NOTFOUND;
FOR i IN 1..emp_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Employee: ' || emp_names(i));
END LOOP;
END LOOP;
CLOSE emp_cursor;
END;
এখানে, BULK COLLECT INTO ব্যবহার করা হয়েছে, যা কুরসরের রেকর্ডগুলি কোলেকশনে একত্রিত করে এবং তারপর সেগুলি প্রসেস করা হচ্ছে।
উপসংহার
PL/SQL তে Cursor এবং Collection দুটি অত্যন্ত শক্তিশালী টুল যা ডেটাবেসের সাথে ইন্টারঅ্যাকশন করার সময় আরও কার্যকর এবং কার্যক্ষম কোড লেখার সুবিধা প্রদান করে। Cursors আপনাকে ডেটাবেস থেকে একাধিক রেকর্ড প্রসেস করার সুযোগ দেয়, যখন Collections আপনাকে একাধিক ভ্যালু ধরে রাখতে এবং প্রক্রিয়াজাত করতে সক্ষম করে।
PL/SQL-এ Triggers এবং Exception Handling দুটি গুরুত্বপূর্ণ কনসেপ্ট যা ডেটাবেস অপারেশনের মধ্যে স্বয়ংক্রিয় ক্রিয়া এবং ত্রুটি মোকাবিলার জন্য ব্যবহৃত হয়। নিচে এগুলির বিস্তারিত ব্যাখ্যা ও উদাহরণ দেওয়া হলো।
1. Trigger উদাহরণ
Trigger হল একটি বিশেষ ধরনের প্রোগ্রাম যা ডেটাবেসে কোনো নির্দিষ্ট ইভেন্ট (যেমন INSERT, UPDATE, DELETE) ঘটলে স্বয়ংক্রিয়ভাবে চালিত হয়। ট্রিগারগুলি সাধারণত ডেটাবেসের ইনটিগ্রিটি নিশ্চিত করতে ব্যবহৃত হয়, যেমন লগিং, ডেটা ভ্যালিডেশন, অথবা হিসাব রাখার জন্য।
Trigger টাইপস:
- BEFORE Trigger: ইভেন্টের আগে ট্রিগার চালানো হয়।
- AFTER Trigger: ইভেন্টের পরে ট্রিগার চালানো হয়।
- INSTEAD OF Trigger: কোনো
INSERT,UPDATE, বাDELETEইভেন্টের পরিবর্তে ট্রিগার চালানো হয় (যেমন ভিউতে পরিবর্তন করতে)।
উদাহরণ:
ধরা যাক, আপনার একটি employees টেবিল আছে এবং আপনি চান যে, কোনো কর্মচারীর বেতন যখন আপডেট হবে, তখন তার সাথে সংশ্লিষ্ট লগে সেই আপডেটের তথ্য রাখা হোক। এজন্য একটি AFTER UPDATE ট্রিগার তৈরি করা হবে।
-- Step 1: Create the Log Table
CREATE TABLE employee_salary_log (
log_id NUMBER PRIMARY KEY,
employee_id NUMBER,
old_salary NUMBER,
new_salary NUMBER,
update_time TIMESTAMP
);
-- Step 2: Create the Trigger
CREATE OR REPLACE TRIGGER trg_salary_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
-- Insert old and new salary details into the log table
INSERT INTO employee_salary_log (log_id, employee_id, old_salary, new_salary, update_time)
VALUES (employee_salary_log_seq.NEXTVAL, :OLD.employee_id, :OLD.salary, :NEW.salary, SYSDATE);
END;
এখানে,
- AFTER UPDATE ট্রিগারটি
employeesটেবিলে কোনো রেকর্ড আপডেট হওয়ার পর চলবে। :OLDএবং:NEWব্যবহার করে পুরনো এবং নতুন মানের মধ্যে পার্থক্য বের করা হয়েছে।- এই ট্রিগারটি একটি
employee_salary_logটেবিলে সেই পরিবর্তনের লগ রাখবে।
কীভাবে কাজ করবে:
যখন employees টেবিলে কোনো কর্মচারীর বেতন পরিবর্তিত হবে, তখন এই ট্রিগারটি চালু হবে এবং সংশ্লিষ্ট কর্মচারীর পুরনো এবং নতুন বেতনসহ একটি লগ তৈরি করবে।
2. Exception Handling উদাহরণ
Exception Handling হল একটি পদ্ধতি যা ডেটাবেস অপারেশনের সময় কোনো ত্রুটি (error) ঘটলে সেগুলিকে সঠিকভাবে মোকাবিলা করতে ব্যবহৃত হয়। PL/SQL-এ Exception Handling বিভিন্ন ধরনের ত্রুটির জন্য একটি নির্দিষ্ট ব্লক প্রস্তুত করে, যাতে ত্রুটি ঘটলে তা সঠিকভাবে পরিচালনা করা যায়।
Exception Handling এর স্টেপস:
- Predefined Exceptions: আগেই ডিফাইন করা ত্রুটির ধরন, যেমন
NO_DATA_FOUND,TOO_MANY_ROWS, ইত্যাদি। - User-defined Exceptions: আপনি নিজে যে ত্রুটি তৈরি করেন তা।
- EXCEPTION Block: যেখানে ত্রুটিগুলি ক্যাচ করা হয় এবং সেই অনুযায়ী ব্যবস্থা নেওয়া হয়।
উদাহরণ:
ধরা যাক, আপনি একটি employees টেবিল থেকে কর্মচারীর বেতন বের করতে চান, কিন্তু যদি কর্মচারী না পাওয়া যায়, তাহলে একটি কাস্টম ত্রুটি দেখাতে চান।
DECLARE
v_employee_id NUMBER := 101;
v_salary NUMBER;
BEGIN
-- Try to get the salary for a given employee
SELECT salary INTO v_salary
FROM employees
WHERE employee_id = v_employee_id;
-- If no data found, raise an exception
IF v_salary IS NULL THEN
RAISE_APPLICATION_ERROR(-20001, 'Employee not found with ID ' || v_employee_id);
END IF;
-- If salary is found, display it
DBMS_OUTPUT.PUT_LINE('Salary: ' || v_salary);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No employee found with ID ' || v_employee_id);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END;
এখানে:
SELECTস্টেটমেন্টটিemployeesটেবিল থেকেsalaryবের করার চেষ্টা করছে।- যদি কর্মচারী না পাওয়া যায়, তাহলে
NO_DATA_FOUNDpredefined exception ক্যাচ করা হবে। - যদি অন্য কোনো ত্রুটি ঘটে, তবে
WHEN OTHERSব্লকটি সেই ত্রুটিকে ক্যাচ করে এবং একটি ডিফল্ট ত্রুটি বার্তা দেখাবে।
কীভাবে কাজ করবে:
- যদি কর্মচারী
employee_id = 101পাওয়া না যায়, তাহলে "No employee found with ID 101" বার্তা প্রদর্শিত হবে। - অন্য কোনো ত্রুটি হলে, সিস্টেম ত্রুটির বার্তা দেখাবে।
Trigger এবং Exception Handling-এর সমন্বিত উদাহরণ
ধরা যাক, আপনি চান যখন কোনো কর্মচারী DELETE হবে, তখন সেই তথ্য একটি লগ টেবিলে রেকর্ড করা হোক। তবে, যদি কোনো কর্মচারী পাওয়া না যায়, তবে ত্রুটি ম্যানেজমেন্টের মাধ্যমে একটি কাস্টম ত্রুটি বার্তা দেখানো হবে।
-- Step 1: Create the Log Table
CREATE TABLE employee_delete_log (
log_id NUMBER PRIMARY KEY,
employee_id NUMBER,
deleted_at TIMESTAMP
);
-- Step 2: Create the Trigger
CREATE OR REPLACE TRIGGER trg_employee_delete
BEFORE DELETE ON employees
FOR EACH ROW
DECLARE
v_employee_exists NUMBER;
BEGIN
-- Check if the employee exists before deleting
SELECT COUNT(*) INTO v_employee_exists
FROM employees
WHERE employee_id = :OLD.employee_id;
IF v_employee_exists = 0 THEN
-- Raise custom exception if employee does not exist
RAISE_APPLICATION_ERROR(-20002, 'Employee with ID ' || :OLD.employee_id || ' does not exist');
END IF;
-- Insert delete log
INSERT INTO employee_delete_log (log_id, employee_id, deleted_at)
VALUES (employee_delete_log_seq.NEXTVAL, :OLD.employee_id, SYSDATE);
END;
এখানে,
- BEFORE DELETE ট্রিগারটি
employeesটেবিল থেকে রেকর্ড মুছে ফেলার আগে চেক করে যে ওই কর্মচারীটি টেবিলে আছে কিনা। - যদি কর্মচারী না থাকে, তবে
RAISE_APPLICATION_ERRORব্যবহার করে একটি কাস্টম ত্রুটি বার্তা সৃষ্টি হয়। - যদি কর্মচারী পাওয়া যায়, তবে একটি ডিলিট লগ
employee_delete_logটেবিলে ইনসার্ট করা হবে।
উপসংহার
Triggers এবং Exception Handling PL/SQL-এ অত্যন্ত গুরুত্বপূর্ণ দুটি কৌশল যা ডেটাবেস অপারেশনগুলিকে আরও শক্তিশালী, সুরক্ষিত এবং নির্ভরযোগ্য করে তোলে। Triggers স্বয়ংক্রিয় কাজ সম্পাদন করতে ব্যবহৃত হয়, এবং Exception Handling ত্রুটি পরিস্থিতি মোকাবিলার জন্য ব্যবহৃত হয়। এগুলি একসাথে ব্যবহার করে ডেটাবেসের প্রক্রিয়াগুলিকে আরও কার্যকরী এবং নিরাপদ করা সম্ভব।
Dynamic SQL হল একটি প্রক্রিয়া যেখানে SQL কোড রানটাইমে তৈরি এবং এক্সিকিউট করা হয়। এটি বিশেষভাবে তখন প্রয়োজনীয় যখন আপনি একাধিক SQL কুয়েরি চালাতে চান, যেগুলি ডাইনামিকভাবে তৈরি হয়, অর্থাৎ টেবিল বা কলাম নাম নির্ধারণ করতে হয় বা কুয়েরি গুলির আর্গুমেন্ট ভিন্ন হয়।
REST API Integration এর মাধ্যমে আপনি আপনার ডেটাবেসকে একটি ওয়েব সার্ভিস হিসেবে অ্যাক্সেস করতে পারেন, যেখানে আপনি HTTP রিকোয়েস্ট (যেমন GET, POST, PUT, DELETE) পাঠিয়ে ডেটাবেসের ডেটা অ্যাক্সেস বা ম্যানিপুলেট করতে পারবেন।
এখানে Dynamic SQL এবং REST API Integration এর মাধ্যমে কীভাবে ডেটাবেস থেকে ডাইনামিক SQL কুয়েরি রান করা এবং REST API এর মাধ্যমে রেসপন্স পাওয়া যায়, তার একটি উদাহরণ দেখানো হলো।
উদাহরণ: Dynamic SQL ব্যবহার করে REST API তৈরি করা
ধরা যাক, আমাদের একটি employees টেবিল রয়েছে এবং আমরা একটি RESTful API তৈরি করতে চাই, যা GET রিকোয়েস্টের মাধ্যমে টেবিল থেকে ডাইনামিকভাবে কর্মচারীদের ডেটা ফেরত দেবে, এমনকি কলাম নাম বা শর্তও ডাইনামিকভাবে পরিবর্তন হবে।
১. PL/SQL ব্লক তৈরি করা: Dynamic SQL with REST API
PL/SQL কোড:
এখানে আমরা PL/SQL ব্লক ব্যবহার করে ডাইনামিক SQL কুয়েরি তৈরি করব এবং ORDS এর মাধ্যমে এটি API হিসেবে এক্সপোজ করব।
CREATE OR REPLACE PROCEDURE get_employee_data (
p_column_name IN VARCHAR2,
p_value IN VARCHAR2
) AS
v_sql VARCHAR2(4000);
v_cursor SYS_REFCURSOR;
BEGIN
-- Dynamic SQL Query construction
v_sql := 'SELECT * FROM employees WHERE ' || p_column_name || ' = :value';
-- Execute dynamic SQL
OPEN v_cursor FOR v_sql USING p_value;
-- Fetch and output the result (Optional: Return as JSON)
FOR rec IN v_cursor LOOP
DBMS_OUTPUT.PUT_LINE('Employee ID: ' || rec.employee_id || ', Name: ' || rec.first_name || ' ' || rec.last_name);
END LOOP;
CLOSE v_cursor;
END;
/
এই কোডে আমরা p_column_name এবং p_value প্যারামিটার নিয়েছি। প্যারামিটারগুলির মাধ্যমে ডাইনামিক SQL কুয়েরি তৈরি করা হয়, এবং সেই কুয়েরি চালানো হয়।
যেমন যদি আপনি কলাম হিসেবে department_id এবং মান হিসেবে 90 পাঠান, তখন কুয়েরি হবে:
SELECT * FROM employees WHERE department_id = 90;
২. ORDS API তৈরি করা: REST API Definition
ORDS ব্যবহার করে, আমরা এই PL/SQL প্রোসিডিউরটি একটি RESTful API হিসেবে প্রকাশ করব।
BEGIN
ORDS.DEFINE_SERVICE(
p_module_name => 'Employee_Module',
p_base_path => '/employees/',
p_pattern => 'data/',
p_source_type => 'PLSQL',
p_source => 'BEGIN get_employee_data(:column_name, :value); END;'
);
END;
/
এটি একটি REST API তৈরি করবে, যেখানে column_name এবং value প্যারামিটার হিসেবে পাঠানো হবে। API URL হবে:
http://localhost:8080/ords/hr/employees/data/?column_name=department_id&value=90
এটি HTTP GET রিকোয়েস্টের মাধ্যমে department_id কলামের জন্য 90 মানের সাথে সমস্ত কর্মচারীর তথ্য ফিরিয়ে দেবে।
৩. HTTP GET Request Example
API ব্যবহার করে, আপনি HTTP GET রিকোয়েস্ট পাঠাতে পারবেন:
GET http://localhost:8080/ords/hr/employees/data/?column_name=department_id&value=90
এটি JSON আউটপুটে কর্মচারীদের তালিকা ফিরিয়ে দেবে:
[
{
"employee_id": 101,
"first_name": "John",
"last_name": "Doe",
"email": "jdoe@example.com",
"department_id": 90
},
{
"employee_id": 102,
"first_name": "Jane",
"last_name": "Smith",
"email": "jsmith@example.com",
"department_id": 90
}
]
৪. POST Method Example for Dynamic SQL
ধরা যাক, আপনি একটি POST রিকোয়েস্ট পাঠাতে চান, যা একটি নতুন কর্মচারী employees টেবিলে ইনসার্ট করবে এবং সেই ইনসার্ট ডেটার ID ফেরত দেবে।
PL/SQL Procs:
CREATE OR REPLACE PROCEDURE insert_employee (
p_first_name IN VARCHAR2,
p_last_name IN VARCHAR2,
p_email IN VARCHAR2,
p_salary IN NUMBER
) AS
BEGIN
INSERT INTO employees (first_name, last_name, email, salary)
VALUES (p_first_name, p_last_name, p_email, p_salary);
COMMIT;
END;
/
ORDS API Creation for POST:
BEGIN
ORDS.DEFINE_SERVICE(
p_module_name => 'Employee_Module',
p_base_path => '/employees/',
p_pattern => 'insert/',
p_source_type => 'PLSQL',
p_source => 'BEGIN insert_employee(:first_name, :last_name, :email, :salary); END;'
);
END;
/
এটি একটি POST API তৈরি করবে, যেখানে আপনি কর্মচারীর নাম, ইমেইল, এবং বেতন পাঠাতে পারবেন।
API URL:
POST http://localhost:8080/ords/hr/employees/insert
POST Data (JSON Format):
{
"first_name": "Michael",
"last_name": "Jordan",
"email": "mjordan@example.com",
"salary": 15000
}
এটি ডেটাবেসে নতুন কর্মচারী ইনসার্ট করবে।
উপসংহার
এখানে আমরা দেখলাম কীভাবে Dynamic SQL ব্যবহার করে ডাইনামিকভাবে SQL কুয়েরি তৈরি করা এবং ORDS (Oracle REST Data Services) এর মাধ্যমে সেই কুয়েরি একটি REST API হিসেবে এক্সপোজ করা যায়। এটি একটি শক্তিশালী পদ্ধতি যেখানে SQL কুয়েরি পরিবর্তনশীল (ডাইনামিক) হতে পারে, এবং API ব্যবহারকারীরা HTTP রিকোয়েস্টের মাধ্যমে এই ডেটা অ্যাক্সেস বা ম্যানিপুলেট করতে পারেন।
ORDS এর মাধ্যমে SQL ও PL/SQL কোডকে ওয়েব সার্ভিস হিসেবে প্রকাশ করা খুবই সহজ, এবং এটি ডেটাবেস অ্যাপ্লিকেশনগুলিকে আরো স্কেলেবল এবং ইন্টিগ্রেটেড করে তোলে।
Read more