পিএল/এসকিউএল

পিএল/এসকিউএল ( এসকিউএল-এর জন্য বিশেষ ভাষা ) হল ওরাকল কর্পোরেশনের এসকিউএল এবং ওরাকল রিলেশনাল ডাটাবেজের জন্য বিশেষ পরিশীলিত পোগ্রামিং ভাষা  । পিএল/এসকিউএল ওরাকল ডেটাবেজে (প্রথমিক ভাবে সংস্করণ ৬ এবং সংস্করণ ৭ থেকে প্রসিডিউর/ফাংশন/প্যাকেজ/ট্রিগার) টাইমস টেন ইন-মেমরি ডাটাবেজ (সংস্করণ ১১.২.১ থেকে), এবং আইবিএম ডিবি২ (সংস্করণ ৯.৭ থেকে) )  ব্যবহার করা হয়ে আসছে। এর পরবর্তী সংস্করণ গুলতে ওরাকল কর্পোরেশন ওরাকল ডেটাবেজের প্রতিটি ধারাবাহিক সংস্করণ প্রকাশের সাথে সাথে পিএল/এসকিউএল সংস্করণের কার্যকারিতা বৃদ্ধি করে চলেছে।

পিএল/এসকিউএল এ বিশেষভাবে যেমন শর্ত এবং লুপ অন্তর্ভুক্ত করা হয়েছে যা সাধারণ এসকিউএলে প্রথম দিকে ছিল না। এটি প্রোগ্রাম চলাকালীন (রান টাইম) কোন  ব্যতিক্রম/এরর বা এক্সেপনশন এর সমাধান দিতে পারে। এতে প্রোগ্রামিং ভাষার ধ্রুবক এবং ভেরিয়েবল, প্রসিডিউর, ফাংশন, প্যাকেজ, টাইপ এবং এই ধরনের ভেরিয়েবল, এবং ট্রিগার ব্যবহার করা যায়। পিএল/এসকিউএল এর কালেকশন অনেকটা অন্যান্য পোগ্রামিং ভাষার অ্যারে এর মত। ওরাকল ডাটাবেজের সংস্করণ ৮ থেকে অবজেক্ট-অরিয়েন্টেশনের বৈশিষ্ট্যগুলি এতে অন্তর্ভুক্ত করে চলেছে। যে কেউ চাইলে পিএল/এসকিউএল দিয়ে ইউনিট তৈরি করতে পারে যেমন প্রসিডিউর, ফাংশন, প্যাকেজ, টাইপ এবং ট্রিগার ইত্যাদি। যেগুলি ওরাকল ডেটাবেজ প্রোগ্রামযোগ্য ইন্টারফেসে ব্যবহার করে এমন অ্যাপ্লিকেশনে (একাধিক কোড না লিখে) পুনঃব্যবহারের জন্য ডাটাবেজে সংরক্ষণ করা হয়।

ঐতিহাসিকভাবে, পিএল/এসকিউএল এর প্রথম সর্বজনীন সংস্করণ  শুর হয় ১৯৯৫ সালে, যা ছিল ওরাকল এর যাত্রা শুরু হওয়ার তিন বছর পরে। ওরাকল এর সূচনা হয় ~১৯৯২ সালে। এটি আইএসও SQL/PSM এর নীতিমালা সমর্থন করে।

পিএল/এসকিউএল প্রোগ্রাম ইউনিট 
এসকিউএল এর উল্লেখযোগ্য কিছু সুবিধা থাকলেও এর কিছু সীমাবদ্ধতাও রয়েছে। যেমন কন্টোল স্টেটমেন্ট ( সিদ্ধান্ত গ্রহণ বা পুনরাবৃত্তিমূলক নিয়ন্ত্রণ/লুপ ) শুধুমাত্র এসকিউএলে ব্যবহার করা যায়না। পিএল/এসকিউএল ব্যবহার করে এসকিউএলে অন্যান্য পোগ্রামিং ভাষার মত সুবিধা পাওয়া যায় যেমন সিদ্ধান্ত গ্রহণ, পুনরাবৃত্তি (লুপ) ইত্যাদি। একটি পিএল/এসকিউএল প্রোগ্রাম ইউনিট নিম্নলিখিতগুলির মধ্যে যে কোনটি হতে পারে: পিএল/এসকিউএল নামহীন ব্লক, প্রসিডিউর, ফাংশন, প্যাকেজ স্পেসিফিকেশন, প্যাকেজ বডি, ট্রিগার, টাইপ স্পেসিফিকেশন, টাইপ বডি, লাইব্রেরি ইত্যাদি। প্রোগ্রাম ইউনিট হল পিএল/এসকিউএল এর সোর্স কোড যা কোড লেখার মাধ্যমে লেখা/ডেভেলপ করা হয়, কম্পাইল করা হয় এবং সর্বশেষে ডাটাবেজে এক্সিকিউট বা চালানো (রান) করা হয়।

পিএল/এসকিউএল নামহীন ব্লক 
একটি পিএল/এসকিউএল সোর্স প্রোগ্রামের মৌলিক একক হল ব্লক, যা একত্রে এর সাথে সম্পর্কিত ঘোষণা/ডিক্লেয়ার এবং বিবৃতি/স্টেটমেন্ট গুলোকে একত্রিত করে। একটি পিএল/এসকিউএল ব্লক ডিক্লেয়ার (DECLARE), বিগিন(BEGIN), এক্সেপশন (EXCEPTION), এবং ইন্ড (END) কীওয়ার্ড দ্বারা গঠিত হয়। এই কীওয়ার্ডগুলি ব্লকগুলোর একটিকে ঘোষণামূলক অংশ, একটি কার্যকরী অংশ এবং একটি ব্যতিক্রম-হ্যান্ডলিং অংশে ভাগ করা হয়।  ঘোষণা বিভাগটি ঐচ্ছিক যাতে ধ্রুবক এবং ভেরিয়েবল নির্ধারণ করে দিতে হয় এবং ব্লকের শুরুতে এটি করতে হয়। যদি একটি ভেরিয়েবল এর কোন নির্দিষ্ট মান উল্লেখ করা না হয় তাহলে স্বাভাবিক ভাবে এর মান নাল ধরে নেয়। ব্যতিক্রম-হ্যান্ডলিং (এক্সেপশন) অংশটিও ঐচ্ছিক যা রান টাইম ত্রুটিগুলি ব্যবস্থাপনা করতে ব্যবহার হয়। শুধুমাত্র এক্সিকিউটেবল অংশটি অবশ্যক। এক্সিকিউটেবল অংশ ছাড়া পিএল/এসকিউএল ব্লক রান হবে না কিন্তু ডিক্লেয়ার অথবা এক্সেপশন ছাড়া এর কোড চালানো সম্ভব। একটি ব্লকের একটি অথবা একাধিক ধাপ থাকতে পারে। 

উদাহরণ স্বরূপ:

<<label>>  -- this is optional

DECLARE—this section is optional

number1 NUMBER(2);

number2 number1%TYPE := 17;       -- value default

text1  VARCHAR2(12) := '   Hello world    ';

text2  DATE     := SYSDATE;    -- current date and time

BEGIN—this section is mandatory, must contain at least one executable statement

SELECT street_number

  INTO number1

  FROM address

  WHERE name = 'INU';

EXCEPTION—this section is optional

  WHEN OTHERS THEN

   DBMS_OUTPUT.PUT_LINE('Error Code is ' || TO_CHAR(sqlcode));

   DBMS_OUTPUT.PUT_LINE('Error Message is ' || sqlerrm);

END;

এই প্রতীক টি := একটি ভেরিয়েবলে মান সংরক্ষণ করতে অ্যাসাইনমেন্ট অপারেটর হিসাবে কাজ করে।

পিএল/এসকিউএল ব্লক একটির মধ্যে আরেকটি ব্লক হতে পারে, যাকে নেস্টেড বলা হয়। যেহেতু ব্লক গুলো এক্সিউটেবল স্টেটমেন্ট সেহেতু একটি ব্লক অন্য ব্লকে ব্যবহার হতে পারে। এই ব্লক অথবা কোড গুলো কোন ইন্টার একটিভ টুলস ব্যবহার করে লেখা যেতে পারে। যেমন সাদা মাটা ভাবে (কমান্ড লাইন ইন্টার ফেসের মত) ওরাকলের এসকিউএল প্লাস (SQL*Plus) এ রান করা যেতে পারে। এটি ছাড়া পেশাদার ডেভেলোপাররা ওরাকলের নিজস্ব এসকিউএল ডেভেলপার (ফ্রি) কোড ইডিটর অথবা তৃতীয় পক্ষের কোড এডিটর (যেমন- টোড়, পিএল/এসকিউএল, ভিএস কোড, বি-বেভার ইত্যাদি) ব্যবহার করে থাকতে পারে। পিএল/এসকিউএল একটি ওরাকল প্রিকম্পাইলার বা ওসিআই প্রোগ্রামের মধ্যে এমবেড/রান করা যেতে পারে। ইন্টারেক্টিভ টুল বা প্রোগ্রামটি ব্লকটিকে কম্পাইল করে চালায়। ব্লকটি ডাটাবেজে সংরক্ষণ করা হয় না যার কারণে, একে নামহীন ব্লক বলা হয়।

ফাংশন 
কোন কিছুর একক মান গণনা করা অথবা তার মান ফেরত/রিটার্ণ করাতে পিএল/এসকিউএল এর ফাংশনের ব্যবহার হয়ে থাকে। তবে এই মানটি পিএল/এসকিউএল এর সমর্থিত ডাটা টাইপ হতে হবে। যেমন- এটি হতে পারে সংখ্যা, তারিখ অথবা অক্ষর (স্ট্রিং)। আবার এটি কালেকশন যেমন অ্যারে/ নেস্টেড টেবিল) রিটার্ণ করতে পারে। ওরাকল কর্পোরেশনের নিজস্ব কিছু ফাংশন তৈরি করা আছে। যেগুলো ব্যবহার করে ব্যবহারকারী তার মত করে নিজস্ব ফাংশন বানাতে পারে। যাকে ইউজার-ডিফাইন্ড ফাংশন বলা হয়।

পিএল/এসকিউএল ফাংশনের গঠন/সিনট্যাক্স দেখতে নিচের মত: CREATE OR REPLACE FUNCTION <function_name> [(input/output variable declarations)] RETURN return_type
[AUTHID <CURRENT_USER | DEFINER>] <IS|AS>  -- heading part
amount number;  -- declaration block
BEGIN  -- executable part
	<PL/SQL block with return statement>
    RETURN <return_value>;
[Exception
	none]
    RETURN <return_value>;
END;CREATE OR REPLACE FUNCTION <function_name> [(input/output variable declarations)] RETURN return_type
[AUTHID <CURRENT_USER | DEFINER>] [<AGGREGATE | PIPELINED>] <IS|USING>
	[declaration block]
BEGIN
	<PL/SQL block with return statement>
    PIPE ROW <return type>;
    RETURN;
[Exception
	exception block]
    PIPE ROW <return type>;
    RETURN;
END;একটি ফাংশন শুধুমাত্র ইন(IN) প্যারামিটার ব্যবহার করা উচিত। এবং রিটার্নের মাধ্যমে এটি আউট মান প্রদান করে। তবে ক্ষেত্র বিশেষে আউট অথবা ইন-আউট প্যারামিটারও করা যেতে পারে। তবে সেটি বিশেষ কোন উদ্দেশ্য ছাড়া ব্যবহার না করাই শ্রেয়।

প্রসিডিউর 
ফাংশন পোগ্রাম ইউনিট গুলোর মত প্রসিডিউর গুলোর একটি নাম উল্লেখ করা থাকে। যাতে করে সেই নাম ধরে এটিকে পোগ্রামের বিভিন্ন স্থানে প্রয়োজন অনুসারে ডাকা যেতে পারে। প্রসিডিউর আর ফাংশনের মূল পার্থক্য হল- ফাংশন এসকিউএল এর স্টেটমেন্ট হিসেবে ব্যবহার করা যেতে পারে, যেখানে প্রসিডিউর স্টেটম্যানতে সরাসরি ব্যবহার করা যায়না। বিশেষত প্রসিডিউর একাধিক মান রিটার্ন করতে পারে আর একটি মান প্রদান/রিটার্ণের ক্ষেত্রে ফাংশন ব্যবহার করা হয়।

পদ্ধতিগুলি ফাংশনগুলির সাথে সাদৃশ্যপূর্ণ যে তাদের নামকরণ করা হয়েছে প্রোগ্রাম ইউনিট যা বারবার আহ্বান করা যেতে পারে। প্রাথমিক পার্থক্য হল যে ফাংশনগুলি একটি SQL স্টেটমেন্টে ব্যবহার করা যেতে পারে যেখানে পদ্ধতিগুলি তা পারে না । আরেকটি পার্থক্য হল যে পদ্ধতিটি একাধিক মান ফেরত দিতে পারে যেখানে একটি ফাংশন শুধুমাত্র একটি একক মান প্রদান করা উচিত। 

প্রসিডিউর লেখার শুরুতেই অবশ্যিক ভাবে এর একটি শিরোনাম অংশ থাকে যাতে এর একটি নাম দিতে হয়। আর তার সাথে একটি ঐচ্ছিক অংশে প্যারামিটার লিস্ট (যদি থাকে) উল্লেখ করতে হয়। এর পরেই আসে ডিক্লারেটিভ, এক্সিকিউটেবল এবং এক্সেপশন হ্যান্ডেলিং অংশ, যা নামহীন ব্লকের মতই। একটি সাধারণ প্রসিডিউর দেখতে অনেকটা এই রকমঃCREATE PROCEDURE create_email_address ( -- Procedure heading part begins
  name1 VARCHAR2,
  name2 VARCHAR2,
  company VARCHAR2,
  email OUT VARCHAR2
) -- Procedure heading part ends
AS
-- Declarative part begins (optional)
error_message VARCHAR2(30) := 'Email address is too long.';
BEGIN -- Executable part begins (mandatory)
  email := name1 || '.' || name2 || '@' || company;
EXCEPTION -- Exception-handling part begins (optional)
WHEN VALUE_ERROR THEN
  DBMS_OUTPUT.PUT_LINE(error_message);
END create_email_address;উপরের উদাহরণটি নাম হীন প্রসিডিউর পদ্ধতি থেকে আলাদা। এটি এমন পদ্ধতিতে তৈরি করা হয় যা একটি ডাটাবেজের স্কিমাতে সংরক্ষিত থাকে। এটিকে  ক্রিয়েট প্রসিডিউর স্টেটমেন্ট বলা হয়। পিএল/এসকিউএল প্যাকেজের মধ্যেও প্রসিডিউর বানানো যেতে পারে যকে প্যাকেজ প্রসিডিউর বলা হয়। নাম বিহীন প্রসিডিউর গুলোকে নেস্টেড প্রসিডিউর, যেগুলো সংরক্ষিত থাকে নাএবং নাম সহ অথবা প্যাকেজ প্রসিডিউর গুলো ডাটাবেজে সংরক্ষিত থাকে বিধায় এগুলোকে "স্টোর্ড প্রসিডিউর" বলা হয়।

প্রসিডিউর এর ক্ষেত্রে তিন ধরনের প্যারামিটার থাকতে পারে: IN, OUT এবং IN OUT।

 একটি IN প্যারামিটার শুধুমাত্র ইনপুট হিসাবে ব্যবহৃত হয়। এই IN প্যারামিটার রেফারেন্স (কলামের নাম ব্যবহার করে)  দ্বারা পাস করা হয়, যদিও এটি আরও অনেক ভাবে পরিবর্তন করা যেতে পারে।
 একটি আউট প্যারামিটার প্রাথমিকভাবে নাল(ফাকা)  হয়। প্রোগ্রামটি চালানোর পর একটি মান নির্ধারণ করে এবং সেই মানটি কলিং প্রোগ্রামে ফেরত দেওয়া হয়।
 একটি IN OUT প্যারামিটারের একটি প্রাথমিক মান থাকতে পারে আবার নাও থাকতে পারে। সেই প্রাথমিক মানটিকে বলা প্রোগ্রাম দ্বারা পরিবর্তিত হতে পারে বা নাও হতে পারে। প্যারামিটারে করা যেকোনো পরিবর্তন ডিফল্টভাবে কপি করে কলিং প্রোগ্রামে ফেরত দেওয়া হয় কিন্তু - NO-COPY উল্লেখ করে দিলে - রেফারেন্স দ্বারা পাস করা যেতে পারে।

পিএল/এসকিউএল এ ওরাকল ডাটাবেজের স্ট্যান্ডার্ড ext-proc প্রক্রিয়ার মাধ্যমে বাহ্যিক প্রসিডিউরও ব্যবহার করা যেতে পারে।

প্যাকেজ 
প্যাকেজ হল ধারণাগতভাবে যুক্ত ফাংশন, প্রসিডিউর, ভেরিয়েবল, পিএল/এসকিউএল টেবিল এবং রেকর্ড টাইপ স্টেটমেন্ট, ধ্রুবক, কার্সার ইত্যাদির  সমন্বয়ে গঠিত অংশ। প্যাকেজগুলির মাধ্যমে একই কোড বার বার না লিখে প্যাকেজের মধ্যে লিখেই সবখানে ব্যবহার করা যায়। প্যাকেজ এর দুটি অংশ থাকে, ১। প্যাকেজ স্পেসিফিকেশন এবং ২। একটি ঐচ্ছিক প্যাকেজ বডি। স্পেসিফিকেশন হল অ্যাপ্লিকেশনের ইন্টারফেস; এটি টাইপ, ভেরিয়েবল, ধ্রুবক, ব্যতিক্রম, কার্সার এবং উপপ্রোগ্রাম ঘোষণা/ ডিক্লেয়ার করে। বডিতে কোডের পুরো অংশ থাকে এবং স্পেসিফিকেশনে সংক্ষিপ্ত অংশ থাকে। প্যাকেজের দুটি সুবিধা হল:

 মডুলার অ্যাপ্রোচ, এনক্যাপসুলেশন/বিজনেস লজিক উন্মুক্ত না করতে, নিরাপত্তা, কর্মক্ষমতা উন্নতি, পুনরায় ব্যবহারযোগ্যতা। এসবের মাধ্যমে মূলত ফাংশন ওভারলোডিং এবং এনক্যাপসুলেশনের মতো অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং এর সুবিধা পাওয়া যায়।  
 প্যাকেজ ভেরিয়েবল ব্যবহার উপযোগী করে তোলে। তাতে বার বার কোডের অংশ বিশেষ পরিবর্তন না করে সেশনে ভ্যালু পরিবর্তন করে ডাইনামিকভাবে ব্যবহার করা যায়।

ট্রিগার 
ডাটাবেজ ট্রিগার অনেকটা সংরক্ষিত প্রসিডিউরের (নাম সহ) এর মতই। যখন নির্দিষ্ট কোন ঘটনা (পূর্ব নির্ধারিত) ঘটে তখন ওরাকল ডাটাবেজ নিজে থেকে এটি চালিয়ে দেয়। পিএল/এসকিউএল ট্রিগারের একটি নাম সহ ডাটাবেজে সংক্ষিত থাকে এবং সেই নাম ধরে এটিকে বার বার কল/রান করানো যায়। সংরক্ষিত প্রসিডিউরের মত একটি ট্রিগারকে যখন তখন রান অথবা চালানো যায় না। ট্রিগারকে কেবল মাত্র সক্রিয় (এনাবল) অথবা নিষ্ক্রিয় (ডিজেবল) করে রাখা যায়। সক্রিয় অবস্থায় ট্রিগারে উল্লেখিত নির্দিষ্ট ঘটনার প্রেক্ষিতে ডাটাবেজ নিজে থেকেই এটি চালিয়ে দেয়। অর্থাৎ এটি অনেকটা বন্দুকের মত কেবল মাত্র ট্রিগারিং ইভেন্ট ঘটলেই এটি ফায়ার করে অর্থাৎ কাজ করে। অন্যথায় ট্রিগার নিষ্ক্রিয় থাকলে এটি ফায়ার করে না।

প্রসিডিউর বা ফাংশনের মত ট্রিগার তৈরির নির্দিষ্ট নির্দেশনা বা স্টেটমেন্ট (ক্রিয়েট ট্রিগার) আছে। ট্রিগারের মধ্যেই ট্রিগারিং ইভেন্ট বা ঘটনা উল্লেখ করে দিতে হয়। যাতে করে এটি কখন কাজ করবে সেটি বুঝা যায়। ট্রিগার মূলত টেবিল, ভিউ, স্কিমা অথবা ডাটাবেজের উপরেই কাজ করে। ট্রিগারিং ইভেন্ট বা ঘটনা নির্দিষ্ট করার পাশাপাশি এর সময় অর্থাৎ ঘটনাটি ঘটার আগে কাজ করবে না পরে কাজ করবে সেটিও উল্লেখ করে দিতে হয়। যেমন- একটি টেবিলে ডাটা ইনসার্ট বা ঢুকানোর সময় প্রতটি সারির জন্য কাজ করবে অথবা শধু মাত্র টেবিল তৈরির সময় কাজ করবে সেটিও স্টেটমেন্টে উল্লেখ করতে হবে।

যদি একটি ট্রিগার টেবিল অথবা ভিউ এর উপর নির্ভর করে বানানো হয় তবে সেটি "ডাটা ম্যানুপুলেশন ল্যাংগুয়েজ" বা ডাটা বিন্যাসের স্টেটমেন্ট এর সমন্বয়ে গঠিত হয়। যাকে সংক্ষেপে ডিএমএল ট্রিগার বলে। আবার ট্রিগারটি যদি স্কিমা কিংবা ডাটাবেজের কোন ইভেন্টের জন্য তৈরি হয় তবে সেটি "ডাটা ডেফিনেশন ল্যাংগুয়েজ" বা ডাটাবেজ অপারেশন স্টেটমেন্ট এর সমন্বয়ে হয়। এ ধরণের ট্রিগারকে সিস্টেম ট্রিগারও বলা হয়।

একটি বিশেষ ট্রিগার হচ্ছে ইনস্টিড অব ট্রিগার (কিছুর পরিবর্তে ট্রিগার)। এটি ডিএমএল ট্রিগারও হতে পারে আবার সিস্টেম ট্রিগার বা ডিডিএল ট্রিগারও হতে পারে। ট্রিগারিং ইভেন্টে উল্লেখিত স্টেটমেন্ট এর পরিবর্তে ডাটাবেজ এটি ফায়ার করে থাকে।

ট্রিগার এর উদ্দেশ্য 
নিম্ন লিখিত উদ্দেশ্য গুলো বাস্তবায়নে ট্রিগার (কোড) লেখা হয়ে থাকেঃ

 কোন কলামে স্বয়ংক্রিয়ভাবে মান/ভ্যালু পরিবর্তন করার ক্ষেত্রে
 প্রাইমারি কী এবং ফরেন কী এর মিল রাখার জন্য (রেফারেনশিয়াল ইন্ট্রিগ্রিটি)
 একটি টেবিলে প্রবেশ অথবা তথ্য এক্সেস এর ইভেন্ট রাখতে
 অডিটিং করার ক্ষেত্রে
 একাধিক টেবিলে ডাটা সিক্রোনাইজ এর ক্ষেত্রে 
 নিরাপত্তা জনিত বিধিনিষেধ প্রদানের ক্ষেত্রে 
 অবৈধ লেনদেন প্রতিরোধ করতে

ডাটার প্রকারভেদ 
পিএল/এসকিউএল-এর প্রধান ডেটাটাইপগুলির মধ্যে রয়েছে সংখ্যা (NUMBER), অক্ষর (CHAR), ভ্যারিয়েবল অক্ষর (VARCHAR2), তারিখ (DATE) এবং সময় ও তারিখ একত্রে (TIMESTAMP)।

সংখ্যাসূচক ভেরিয়েবল 
variable_name number([P, S]) := 0;কোন ভ্যারিয়েবলে যদি অংক সংখ্যা রাখার প্রয়োজন পড়ে তবে প্রোগ্রামাররা নাম্বার বা সংখ্যা ডাটা টাইপ নির্বাচন করে। এই ডাটা টাইপটির দুটি ঐচ্ছিক অংশ হচ্ছে প্রিসিশন (P) এবং স্কেল (S), যা কমা দিয়ে আলাদা করে লিখতে হয়। প্রিসিশন দিয়ে মূলত ভ্যারিয়েবলে কয়টি ডিজিট রাখা যাবে তা নির্দেশ করে আর স্কেল দিয়ে সংখ্যাটি দশমিকের পরে কয়ঘর পর্যন্ত জায়গা নিতে পারবে তা বুঝায়।

সাংখ্যিক ভেরিয়েবলের ক্ষেত্রে আরও কিছু সুনির্দিষ্ট ধরণ রয়েছে। তার মধ্যে উল্লেখযোগ্য কয়েকটি হলঃ বাইনারি_ফ্লোট, বাইনারি_ডাবল, ডেসিমাল, ডাবল প্রিসিশন, ফ্লোট, ইন্টেজার, রিয়েল, স্মল-ইন্ট, বাইনারি-ইন্টেজার ইত্যাদি। ক্ষেত্র বিশেষে একেকটি ব্যবহার হয়। যেমন পূর্ণ সংখ্যার ক্ষেত্রে ইন্টেজার বা ফ্লোট ডাটা টাইপ ব্যবহার করা হয়ে থাকে।

অক্ষর ভ্যারিয়েবল 
variable_name varchar2(20) := 'Text';

-- e.g.: 
address varchar2(20) := 'lake view road';সংখ্যা বাদে অক্ষর বা টেক্সট এর ক্ষেত্রে প্রোগ্রামাররা সাধারণত ভারকার২ ডাটা টাইপ ব্যবহার করে থাকে। এর পাশেই বন্ধনীর মধ্যে ভ্যারিয়েবলটি সর্বোচ্চ কয়টি অক্ষর ধারণ বা রাখতে পারবে সেটি নির্ধারণ করে দিতে হয়।

অক্ষর ভেরিয়েবলের জন্যেও আরও কিছু নির্দিষ্ট ডাটার ধরণ রয়েছে। যেমনঃ ভারক্যার (মূলত ভারক্যার২ এর শুরুর দিকের ভার্শন), ক্যার (ক্যারেক্টারের সংক্ষেপিত), লং, রও, লং রও, এনক্যার, এনক্যার২, সি লব, বি লব, বি ফাইল ইত্যাদি।

তারিখ ভ্যারিয়েবল 
variable_name date := to_date('01-01-2005 14:20:23', 'DD-MM-YYYY hh24:mi:ss');তারিখ ভ্যারিয়েবলে তারিখ এবং সময় রাখা যায়। এক্ষেত্রে সময় বাদ দিয়ে সুধু মাত্র তারিখটি রাখা হয়। তবে কেবল মাত্র সময় রাখার জন্য নির্দিষ্ট বা বিশেষ কোন ভ্যারিয়েবল নেই। এক্ষেত্রে আরেকটি বিশেষ ডাটার ধরণ হচ্ছে টাইমস্ট্যাম্প। যাতে তারিখের পাশাপাশি সেকেন্ড, মিলিসেকেন্ড বা ন্যানো সেকেন্ড পর্যন্ত সময় রাখা যায়।

টু-ডেট নামে একটি  বিশেষ ফাংশন রয়েছে যা দিয়ে তারিখের ফর্মেট ঠিক করে দেওয়া যায় বা স্ট্রিং থেকে তারিখে পরিবর্তন করা যায়। এই ফাংশনের মধ্যে কোটেড করে ফর্মেটটি উল্লেখ করে দিতে হয়। যেমনঃ  to_date('31-12-2004', 'dd-mm-yyyy')বা to_date ('31-Dec-2004', 'dd-mon-yyyy', 'NLS_DATE_LANGUAGE = American')তারিখ ডাটা থেকে ক্যার ডাটাতে পরিবর্তন করার করার ক্ষেত্রে TO_CHAR (date_string, format_string) এই ফাংশন ব্যবহার করা হয়ে থাকে।

এছাড়াও পিএল/এসকিউএল ANSI তারিখ এবং তারিখের ব্যবধান বের করা যায়।  নিম্নলিখিত ভাবে ১৮-মাসের ব্যবধান বের করা সম্ভব। WHERE dateField BETWEEN DATE '2004-12-30' - INTERVAL '1-6' YEAR TO MONTH
  AND DATE '2004-12-30'

ব্যতিক্রম (এরর) ব্যবস্থাপনা 
ব্যতিক্রম—কোড এক্সিকিউশনের সময় ত্রুটি সাধারণ ভাবে দুই ধরনেরহয়ে থাকে।

১। ব্যবহারকারী-নির্ধারিত  এবং

২। পূর্বনির্ধারিত- (সম্ভ্যাব্য বা অনুমেয়)।

ব্যবহারকারীর নির্ধারিত ব্যতিক্রম গুলো আলাদা ভাবে প্রোগ্রামাররা রেইজ বা রেইজ এপ্লিকেশন এরর কমান্ডের মাধ্যমে নির্দেশ করে থাকে। যখন স্বাভাবিক ভাবে কার্য সম্পাদন করা সম্ভব হয় না সে সকল পরিস্থিতি বা এরর নিয়ন্ত্রণ করতে ব্যাতিক্রম বা এক্সেপশন ব্যবহার করা হয়। রেইজ কমান্ডের সিনট্যাক্স নিম্নরূপঃ RAISE <exception name>;ওরাকল কর্পোরেশনের নিজস্ব কিছু এক্সেপশন বা ব্যক্তিক্রম রয়েছে। যখন স্টেটমেন্টে কোন ডাটা পাওয়া যায়না (নো_ডাটা_ফাউন্ড), অথবা অধিক ডাটা (টু_মেনি_রোউস) পাওয়া যায় তখন এগুলো ব্যবহারের মাধ্যমে এক্সেপশন নিয়ন্ত্রণ করা যায়। প্রতিটি এক্সেপশন এর নিজস্ব একটি এসকিউএল নাম্বার রয়েছে এবং তার সাথে একটি এসকিউএল ম্যাসেজ যুক্ত করা আছে। প্রোগ্রামাররা এই এসকিউএল কোড এবং এসকিউএল ইআরআরএম ফাংশন দিয়ে এগুলো নির্ধারন করে দিতে পারে।

নির্দিষ্ট কলামের জন্য ডেটাটাইপ 
 Variable_name Table_name.Column_name%type;
এই সিনট্যাক্স রেফারেন্স করা টেবিলের ডাটার ধরণ অনুসারে কলামের ডাটার ধরণ নির্ধারণ করে দেওয়া যায়। এতে করে টেবিলের কলামের ডাটার ধরণ পরিবর্তন হলে এখানেও পরিবর্তন হয়ে যাবে।

প্রোগ্রামাররা সিনট্যাক্স সহ ব্যবহারকারী-নির্ধারিত ডেটাটাইপগুলি উল্লেখ করে দেয়: type data_type is record (field_1 type_1 := xyz, field_2 type_2 := xyz, ..., field_n type_n := xyz);উদাহরণ স্বরূপ:declare
  type t_address is record (
    name address.name%type,
    street address.street%type,
    street_number address.street_number%type,
    postcode address.postcode%type);
  v_address t_address;
begin
  select name, street, street_number, postcode into v_address from address where rownum = 1;
end;এই নমুনা প্রোগ্রামটি তার নিজস্ব ডেটাটাইপ অনুসারে ডাটা ধরে রাখবে। t_address নামক রেকর্ডে, ক্ষেত্রগুলির নাম, রাস্তা, রাস্তার_নম্বর এবং পোস্টকোড এর তথ্য যেভাবে রয়েছে সেভাবেই ডাটার ধরণ নির্ধারণ হবে।

সুতরাং উদাহরণ অনুসারে, একই ভাবে ডাটাবেজ থেকে প্রোগ্রামের ক্ষেত্রগুলিতে ডেটা অনুলিপি করা সম্ভব হবে।

এই ডেটাটাইপ ব্যবহার করে প্রোগ্রামার v_address নামক একটি ভেরিয়েবলকে নির্ধারন করেছে এবং এটি ADDRESS টেবিল থেকে ডেটা লোড করতে পারবে।

প্রোগ্রামাররা ডট-নোটেশনের মাধ্যমে নিচের মত করে এট্রিবিউটে ডাটা সেট করে দিতে পারেঃ 
 v_address.street := 'High Street';

শর্তসাপেক্ষ বিবৃতি/স্টেটমেন্ট 
নিম্নলিখিত কোড সেগমেন্টটি IF-THEN-ELSIF-ELSE কিভাবে লিখতে হয় তার সিনট্যাক্স এর একটি উদাহরণ দেওয়া হল। ELSIF এবং ELSE অংশগুলি ঐচ্ছিক তাই সহজ ভাবে IF-THEN বা IF-THEN-ELSE দিয়েই শর্তসাপেক্ষ বা কন্ডিশনাল স্টেটমেন্ট লেখা যায়। IF x = 1 THEN
  sequence_of_statements_1;
ELSIF x = 2 THEN
  sequence_of_statements_2;
ELSIF x = 3 THEN
  sequence_of_statements_3;
ELSIF x = 4 THEN
  sequence_of_statements_4;
ELSIF x = 5 THEN
  sequence_of_statements_5;
ELSE
  sequence_of_statements_N;
END IF;পিএল/এসকিউএল এর IF-THEN-ELSIF-ELSE কাঠামোকে সরল করতে অনেক সময় এসকিউএল এর CASE স্টেটমেন্টও ব্যবহার করা যেতে পারে।  উদাহরণঃ CASE
  WHEN x = 1 THEN sequence_of_statements_1;
  WHEN x = 2 THEN sequence_of_statements_2;
  WHEN x = 3 THEN sequence_of_statements_3;
  WHEN x = 4 THEN sequence_of_statements_4;
  WHEN x = 5 THEN sequence_of_statements_5;
  ELSE sequence_of_statements_N;
END CASE;CASE বিবৃতি পূর্বনির্ধারিত সিলেক্টরের সাথে ব্যবহার করা যেতে পারে:CASE x
  WHEN 1 THEN sequence_of_statements_1;
  WHEN 2 THEN sequence_of_statements_2;
  WHEN 3 THEN sequence_of_statements_3;
  WHEN 4 THEN sequence_of_statements_4;
  WHEN 5 THEN sequence_of_statements_5;
  ELSE sequence_of_statements_N;
END CASE;

অ্যারে ব্যবস্থাপনা 
পিএল/এসকিউএল এ অ্যারেকে "কালেকশন" বলে থাকে। এ ভাষাতে তিন ধরনের কালেকশন রয়েছে:

 সহযোগী অ্যারে (সারণী দ্বারা সূচী)
 নেস্টেড টেবিল
 ভি-অ্যারে (ভেরিয়েবল-আকার অ্যারে)

প্রোগ্রামারদের প্রায়শই ভি-অ্যারের জন্য সর্বোচ্চ সীমা নির্ধারন করে দিতে হয়, যা ইনডেক্স-বাই টেবিল অথবা নেস্টেড টেবিলের ক্ষেত্রে দরকার পড়ে না। এই ভাষাতে কালেকশনের ডাটা গুলোকে পরিবর্তন করার জন্য বিভিন্ন সুনির্দিষ্ট পদ্ধতি ব্যবহার করা হয়। যেমন ফার্স্ট, লাস্ট, নেক্সট, প্রিয়র, এক্সটেন্ড, ট্রিম, ডিলেট ইত্যাদি।

সহযোগী অ্যারে (সারণী দ্বারা সূচী) 
সূচী দ্বারা সারণি, অ্যারে সংখ্যা বা স্ট্রিং দ্বারা ইন্ডেক্স করা যেতে পারে।  এটি একটি জাভা মানচিত্রের সমান্তরাল, যাতে কী-ভ্যালুর জোড়া নিয়ে গঠিত। এটি একক ডাইম্যানশনের হয়ে থাকে।

নেস্টেড টেবিল 
নেস্টেড টেবিল হচ্ছে মূলত একটি টেবিলের মধ্যে আরও একাধিক টেবিল। অর্থাৎ একটি কলামের মধ্যে আরো ছোট ছোট টেবিল তৈরি করার মত। এটি অনেকটা অ্যারের মত। তবে অ্যারে তে ডাটা বা উপাত্ত গুলো মেমোরিতে থাকে আর নেস্টেড টেবিলের মাধ্যমে ডাটা গুলো ডাটাবেজে সংরক্ষণ করা যায়।

ভি-অ্যারেে (ভ্যারিয়েবল-সাইজ অ্যারেে)

ভি-অ্যার বুঝার জন্য ভ্যারিয়েবল বুঝা জরুরি। এটি একক ডাইমেনশনের একটি কালেকশন যেটি নেস্টেড টেবিলের মতই অনেকটা। তবে ভি-অ্যারের সাইজ ভ্যারিয়েবল ডিক্লেয়ার করার মধ্যে সীমাবদ্ধ থাকে।

কার্সর
কার্সর হচ্ছে ডাটাবেজের একটি পয়েন্টার। কোন সিলেক্ট স্টেটমেন্টের মাধ্যমে অথবা ডাটা ম্যানুপুলেশন অর্থাৎ ডাটা সম্পাদন করার জন্য (ইনসার্ট, আপডেট, ডিলেট অথবা মার্জ) করার জন্য এস কিউ এল এর একটি নিজস্ব এরিয়া। কার্সরের মধ্যে সারি সারি (এক বা একাধিক) আকারে উপাথ থাকে যেগুলো এসকিউএল এর মাধ্যমে তুলে আনা হয়। কার্সরে তুলে আনা সারি গুলোকে সক্রিয় উপাত্ত সেট বলা হয়।

কার্সর দুই ধরনের হতে পারে যেমনঃ এক্সপ্লিসিট অথবা ইমপ্লিসিট। ইমপ্লিসিট কার্সর ডাটাবেজ নিজে নিজে ব্যবস্থাপনা করে আর এক্সপ্লিসিট কার্সর ব্যবহারকারীকে নিয়ন্ত্রণ করতে হয়। বেশিরভাগ ক্ষেত্রে কার্সর লুপের সাথে ব্যবহার করা হয়। ফর লুপ এর ক্ষেত্রে এক্সপ্লিসিট কার্সর ব্যবহার তখনই করা উচিত যদি সেই কার্সরটি পুনঃরায় ব্যবহার করার প্রয়োজন পড়ে। অন্যথায় ইমপ্লিসিট কার্সর ব্যবহার করাই ভাল। কার্সরের কয়েকটি স্তর আছে যেমন কার্সর খোলা বা বন্ধ করা অথবা ফেচ করার মাধ্যমে ডাটা তুলে আনা।

লুপিং (ঘুর্ণন) 
প্রসিডিউর বা পদ্ধতিগত ভাষা হিসেবে পিএল/এসকিউল ভাষাতেও কিছু পুনঃরাবৃত্তি মূলক কাজের জন্য কৌশল রয়েছে, যেমন প্রাথমিক/সাধারণ লুপ স্টেটমেন্ট, হোয়াইল লিউপ, ফর লুপ এবং কার্সর ফর লুপ।

লুপ বা ঘুর্ণন এর কাজ হচ্ছে কোডের মাধ্যমে একটি কাজ কোডের মাধ্যমেই সেটিকে একাধিক বার ঘুর্ণনে ফেলে করে নেওয়া। অর্থাৎ ধরুন আমার ১ থেকে ১০ পর্যন্ত দেখাতে হবে। তার জন্য ১০ বার হয়তো ১,২,৩... এইভাবে করে ১০ টি সংখ্যা দেখাতে পারবো। কিন্তু এই কাজটি লুপ ম্যাকানিজমের মাধ্যমে করতে পারলে চেইনের মাধ্যমে এটি ১০ বার সংখ্যাটি দেখাবে তার সাথে প্রতিবার ১ যোগ করে নিবে। এটিই হচ্ছে মূলত লুপের কাজ।

ওরাকল এর ভার্সন ৭.৩ থেকে রেফ কার্সর নামে আরেকটি বিশেষ সংযোজন নিয়ে আসে যেটি স্টোর্ড প্রসিডিউর এবং ফাংশনে ব্যবহার করে ডাটা তুলে এনে রাখা যায়। যার কারণে কার্সর ফর লুপ এর ব্যবহার অনেকটা এটা দিয়ে করে ফেলা যায়। পরবর্তীতে ৯ আই সংস্করণে সিস_রেফ কার্সর নামে আরেকটি টাইপ নিয়ে আসে যাতে নিজে থেকে রেফ কার্সর এর টাইপ উল্লেখ করে দিতে হয়না।

লুপ স্টেটমেন্ট/ বিবৃতি 
<<parent_loop>>
LOOP
	statements

	<<child_loop>>
	loop
		statements
		exit parent_loop when <condition>; -- Terminates both loops
		exit when <condition>; -- Returns control to parent_loop
	end loop child_loop;
        if <condition> then
           continue; -- continue to next iteration
        end if;

	exit when <condition>;
END LOOP parent_loop;

EXIT কী- ওয়ার্ড ব্যবহার করে অথবা এক্সেপশন দিয়ে লুপ থামিয়ে দেওয়া যায়।।

FOR loops 
DECLARE
    var NUMBER;
BEGIN
    /* N.B. for loop variables in PL/SQL are new declarations, with scope only inside the loop */
    FOR var IN 0 .. 10 LOOP
        DBMS_OUTPUT.PUT_LINE(var);
    END LOOP;

    IF var IS NULL THEN
        DBMS_OUTPUT.PUT_LINE('var is null');
    ELSE
        DBMS_OUTPUT.PUT_LINE('var is not null');
    END IF;
END;Output:
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  var is null

ফর লুপের জন্য কার্সর 
FOR RecordIndex IN (SELECT person_code FROM people_table)
LOOP
  DBMS_OUTPUT.PUT_LINE(RecordIndex.person_code);
END LOOP;কার্সর ফর লুপের মধ্যে সংক্রিয়ভাবে ডাটাবেজ কার্সরটিকে খুলে, তার মধ্যে ডাটা রাখে এবং নিজে থেকেই কাজ শেষ হলে এটি বন্ধ করে দেয়।

পিএল/এসকিউ প্রোগ্রামাররা কার্সর এর সিলেক্ট স্টেটমেন্টটি আগে থেকেই নির্ধারণ করে দিতে পারে তাতে করে কোড টি গুছানো হয় এবং পুনঃরায় ব্যবহার করা সহজ হয় (বিশেষ করে জটিল বা বড় কুয়েরির ক্ষেত্রে)।DECLARE
  CURSOR cursor_person IS
    SELECT person_code FROM people_table;
BEGIN
  FOR RecordIndex IN cursor_person
  LOOP
    DBMS_OUTPUT.PUT_LINE(recordIndex.person_code);
  END LOOP;
END;(".") নোটেশন ব্যবহার করে কার্সর এর সিলেক্ট স্টেটমেন্ট থেকে কলাম (person_code) ব্যবহার করা হয়:RecordIndex.person_code

ডায়নামিক এসকিউএল 
ডায়নামিক এসকিউএল বলতে মূলত এমন স্টেটমেন্ট বুঝায় যা ক্ষেত্র বিশেষে কোডে পরিবর্তন ছাড়াই নিজস্ব ভাবে চলতে পারে। অর্থাৎ সরাসরি কোড গুলোকে এমন ভাবে লেখা হয় যেখানে পরিবর্তন দরকার সেখানে তা সংক্রিয় ভাবে পরিবর্তন করে নেয়।

ডাটা ম্যানুপুলেশন ল্যংগুয়েজ এ পিএল/এসকিউএল কোড এর মধ্যে সরাসরি এসকিউএল স্টেটমেন্ট লিখে কার্য সম্পাদন করা হয়। কিন্তু ডাটা ডেফিনেশন ল্যংগুয়েজের ক্ষেত্রে জটিল এবং ডায়নামিক ভাবে এসকিউএল কোড লেখার প্রয়োজন পড়ে।

পিএল/এসকিউএল এর মাধ্যমে ডায়নামিক এসকিউএল কোড লেখার ক্ষেত্রে ওরাকলের পূর্বের সংস্করণ গুলোতে DBMS_SQL প্যাজেক লাইব্রেরি ব্যবহার করার দরকার পড়ত। কিন্তু পরবর্তী সংস্করণ গুলোতে আরো সহজতর ভাবে "ন্যাটিব ডায়নামিক এসকিউল" এর মাধ্যমে EXECUTE IMMEDIATE  সিন্ট্যাক্স ব্যবহার করে কার্য সম্পাদন করা যায়।

সমজাতীয় ভাষা 
অন্যান্য ভাষা রিলেশনাল ডাটাবেজের সাথে যেভাবে কাজ করে পিএল/এসকিউএলও সাদৃশ্যপূর্ণ ভাবে পদ্ধতিগত ভাষা হিসেবে কাজ করে। যেমনঃ সিবেইজ ASE এবং মাইক্রোসফট এসকিউএল সার্ভার এ ব্যবহার করা হয় ট্রান্সেক্ট-এসকিউএল আর পোস্টগ্রি-এসকিউএল এ ব্যবহার করা হয় PL/pgSQL (যেটি পিএলএসকিউএল এর একটি ইমুলেটর হিসেবে কাজ করে), মারিয়াডিবি তে পিএল/এসকিউল এর সমগোত্রীয় পার্সার ব্যবহার করা হয়, IBM Db2 তে এসকিউল প্রসিডিয়ার ভাষা নামক আরেকটি ভাষা ব্যবহার করা হয়। যেগুলোড় প্রতিটি ISO SQL’s SQL/PSM এর নিয়ম নীতি মেনে চলে।

পিএল/এসকিউল এর নির্মাতারা এর সিনট্যাক্স এমন ভাবে সাজিয়েছেন যা অ্যাডা ভাষার সাথে সামঞ্জস্য। এ দুটো ভাষা অ্যাডা এবং পিএল/এসকিউএল এর পূর্বপুরুষ হিসেবে প্যাসকেল পোগ্রামিং ভাষা কে ধরা হয়। যার কারণে বহুলাংশে প্যাসকেলের সাথেও এর কিছুটা মিল খুঁজে পাওয়া যায়। তবে বোরল্যান্ড ডেলফি বা ফ্রি প্যাসকেল এর প্রণীত অব্জেক্ট প্যাসকেল এর সাথে পিএল/এসকিউএল এর প্যাকেজের গঠণের কোন মিল নেই। পিএল/এসকিউলে প্রোগ্রামাররা পাবলিক এবং প্রাইভেট গ্লোভাল ডাটা-টাইপ, ধ্রুবক এবং স্ট্যাটিক ভ্যারিয়েবল ব্যবহার করতে পারেন।

পিএল/এসকিউএলে ক্লাস উল্লেখ করে সেগুলোকে অবজেক্ট হিসেবেও তাৎক্ষণিক ব্যবহারের সুবিধা দেয়। যেটি অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং ভাষার সুবিধা হিসেবে অবজেক্ট প্যাসকেল, সি++ এবং জাভা তে পাওয়া যায়। পিএল/এসকিউএল এ আরেকটি ক্লাস আছে "এবস্ট্রাক্ট ডাটা টাইপ" (ADT) বা "ইউজার ডিফাইন্ড টাইপ" (UDT) যা ওরাকলে এসকিউএল ডাটা টাইপ হিসেবে ব্যবহার করা যায়। ফলে এটি ওরাকল এসকিউএল ইঞ্জিন এবং ওরাকল পিএল/এসকিউএল ইঞ্জিন দুটোতেই ব্যবহার করা যায়। এবস্ট্রাক্ট ডাটা টাইপ গুলোও পিএল/এসকিউএলে লেখা। যার ফলে এবস্ট্রাক্ট ডাটা টাইপ গুলো ক্লাস হিসেবেও পিএল/এসকিউএলে ব্যবহার করা যায় এবং কলামের উপাত্ত হিসেবে ডাটাবেজের টেবিলে সংরক্ষণ করা যায়।

ট্রান্সেক্ট-এসকিউএল এবং পিল/এসকিউএল এর হালকা সাদৃশ্যতা থাকলেও মৌলিকভাবে দুটির ভিন্নতা রয়েছে। বৈশিষ্টগত অমিলের পাশাপাশি কোডিং এর ক্ষেত্রেও এর ভিন্নতা পরিলক্ষিত হয়। এছাড়াও কনকারেন্সি এবং লকিং বৈশিষ্টের কারণে ওরাকল থেকে এসকিউএল সার্ভার এর পার্থক্য খুঁজে পাওয়া যায়।

জনপ্রিয় ছোট ডাটাবেজ এসকিউএল লাইট এর জন্য ব্যবহৃত স্টেপস্কিলাইটেও পিএল/এসকিউএলের কম্পাইলার ব্যবহার করে যা মূলত পিএল/এসকিউএলের সিনট্যাক্স। ওরাকলের বেকার্লি ডিবি 11g R2 সংস্করণে এসকিউএল এর সাপোর্ট দেওয়ার জন্য এসকিউলাইট এপিআই ব্যবহার করা হয়েছে। যার ধারাবাহিকতায় স্টেপস্কিলাইট তৃতীয় পক্ষের টুলস ব্যবহার করে  পিএলএসকিউল এর কোড বেকার্লি ডিবিতেও ব্যবহার করা যায়।

আরও দেখুন 

 টি-এসকিউএল
 এসকিউএল পি এল
 এসকিউএল/পিএসএম
 পিএল/এসকিউএল এডিটর
 রিলেশনাল ডাটাবেজ ব্যবস্থাপনা পদ্ধতি

তথ্যসূত্র 

এসকিউএল
ওরাকল সফটওয়্যার
অপর্যালোচিত অনুবাদসহ পাতা