دیتابیس اوراکل برای هر دستور SQL یک فضای حافظه به نام CONTEXT AREA ایجاد می کند که اطلاعات پردازشی دستور در این محل ذخیره می شود.
CURSOR یک اشاره گر به CONTEXT AREA است و PL/SQL با استفاده از CURSOR این فضا را کنترل می کند و اطلاعات آن را نمایش می دهد. برای مثال با استفاده از CURSOR می توان تعداد کل سطرهای دستکاری شده توسط یک دستور DML را مشاهده نمود یا محتویات داده در هر سطر از یک QUERY را بدست آورد.
انواع CURSOR
1.CURSORهای از نوع IMPLICIT یا ضمنی
هر زمان که یک دستور DMLای یا یک دستور SELECT INTO توسط اوراکل اجرا می شود به صورت اتوماتیک و به روش ضمنی یک CURSOR برای آن دستور ایجاد می شود.
برای دستورات INSERT محتویات CURSOR شامل اطلاعاتی است که باید درج شود و برای دستورات UPDATE و DELETE سطرهایی که مورد تاثیر قرار می گیرند.
برنامه نویس نمی تواند این نوع از CURSORها و اطلاعات آنها را کنترل کنند ولی می توانند اطلاعات و وضعیت CURSOR را از طریق ویژگی ها جدول زیر مشاهده کنند. با استفاده از این ویژگی ها که با عبارت SQL آغاز می شود می توان به اطلاعات آخرین CURSOR از نوع ضمنی دست یافت.
مثال: جدول مشتریان به این شکل می باشد:
حال برنامه زیر را اجرا می کنیم:
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line(‘no customers selected’);
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ‘ customers selected ‘);
END IF;
END;
/
در این برنامه به حقوق تمام مشتریان 500 واحد اضافه شده است. بنابراین CURSOR که به صورت ضمنی تعریف شده است دارای مقدار صحیح برای ویژگی FOUND% است و ویژگی ROWCOUNT% آن نیز برابر با تعداد سطرهای UPDATE شده خواهد بود.
خروجی:
6 customers selected
PL/SQL procedure successfully completed.
خروجی جدول:
نکته: با توجه به ماهیت CURSOR از نوع ضمنی و زمانی که صفر یا چند سطر توسط دستور برگردانده می شود ممکن است به خطای EXCEPTION از نوع NO_DATA_FOUND یا TOO_MANY_ROWS برخورد کنیم.
2.CURSOR از نوع صریح یا EXPLICIT
این نوع از CURSORها توسط برنامه نویسان و به منظور کنترل اطلاعات CONTEXT AREA ایجاد می شود.
CURSORهای از نوع صریح در قسمت DECLARE بلاک برنامه تعریف می شوند. هر CURSOR از نوع صریح برای یک دستور SELECT که بیشتر از یک سطر را برمی گرداند ایجاد می شود.
در ادامه سینتکس ساخت CURSOR از نوع صریح را می بینید:
CURSOR cursor_name IS select_statement;
زمانی که از CURSOR به روش صریح استفاده می شود دیتابیس اوراکل یک سیکل اجرایی برای آن CURSOR تعریف می کند. در ادامه شکل مربوط به این سیکل اجرایی را می بینید و هر مرحله از این سیکل را توضیح می دهیم.
مرحله DECLARE:
ابتدا باید در قسمت DECLARE یک بلاک یا پکیج به شکل زیر CURSOR را تعریف کنیم:
CURSOR c_customers IS
SELECT id, name, address FROM customers;
مرحله OPEN:
با استفاده از دستور زیر یک CURSOR از نوع صریح OPEN می شود و از این مرحله به بعد آماده دستیابی خواهد بود.
OPEN c_customers;
بعد از OPEN شدن یک CURSOR اوراکل دستور SELECT مربوط به آن را پارس کرده و سپس اجرا می کند و CURSOR را روی اولین سطری که آن دستور برمی گرداند تنظیم می کند. در این مرحله CONTEXT AREA تشکیل می شود.
مرحله FETCH
در این مرحله به یک سطر از دستور توسط CURSOR اشاره می شود و مقدارهای این سطر در متغیرها ذخیره می شوند.
FETCH c_customers INTO c_id, c_name, c_addr;
هر FETCH یک سطر را دستیابی می کند و با FETCH بعدی سطر بعدی دستیابی می شود.
مرحله CLOSE
با CLOSE کردن یک CURSOR فضای CONTEXT AREA آزاد می شود.
CLOSE c_customers;
نکته 1: اگر اجرای یک بلاک از نوع ANONYMOUS، تابع یا پروسیجرخاتمه یاید به صورت اتوماتیک CURSORهای از نوع صریح CLOSE می شوند.
نکته 2: اگر یک CURSOR که هنوز OPEN نشده است را CLOSE کنیم خطای EXCEPTION از نوع INVALID_CURSOR دریافت می کنیم.
نکته 3: ویژگی هایی که می توان بعد از نام یک CURSOR از نوع صریح استفاده کرد را در جدول زیر می بینید:
مثال: نام و شماره تمام مشتریان را نمایش دهید.
DECLARE
c_id customers.id%type;
c_name customerS.Name%type;
c_addr customers.address%type;
CURSOR c_customers is
SELECT id, name, address FROM customers;
BEGIN
OPEN c_customers;
LOOP
FETCH c_customers into c_id, c_name, c_addr;
EXIT WHEN c_customers%notfound;
dbms_output.put_line(c_id || ‘ ‘ || c_name || ‘ ‘ || c_addr);
END LOOP;
CLOSE c_customers;
END;
/
در این برنامه تا زمانی که ویژگی NOTFOUND% برای CURSOR برقرار نشده است، نام و شماره مشتریان چاپ می شود.
خروجی:
1 Ramesh Ahmedabad
2 Khilan Delhi
3 kaushik Kota
4 Chaitali Mumbai
5 Hardik Bhopal
6 Komal MP
PL/SQL procedure successfully completed.
نکته: می توان به CURSORهای از نوع صریح، پارامتر ارسال نمود. بنابراین می توان هر زمان آن CURSOR را با آرگومنت های متفاوت OPEN کنیم.
مثال: یک مرتبه CURSOR را با حداقل و حداکثر قیمت بین 50 و 100 و بار دیگر با 800 و 1000 درنظر می گیریم.
DECLARE
r_product products%rowtype;
CURSOR c_product (low_price NUMBER, high_price NUMBER)
IS
SELECT *
FROM products
WHERE list_price BETWEEN low_price AND high_price;
BEGIN
— show mass products
dbms_output.put_line(‘Mass products: ‘);
OPEN c_product(50,100);
LOOP
FETCH c_product INTO r_product;
EXIT WHEN c_product%notfound;
dbms_output.put_line(r_product.product_name || ‘: ‘ ||r_product.list_price);
END LOOP;
CLOSE c_product;
— show luxury products
dbms_output.put_line(‘Luxury products: ‘);
OPEN c_product(800,1000);
LOOP
FETCH c_product INTO r_product;
EXIT WHEN c_product%notfound;
dbms_output.put_line(r_product.product_name || ‘: ‘ ||r_product.list_price);
END LOOP;
CLOSE c_product;
END;
/
بسیار عالی و ممنون از مطالب مفیدتون