ما الفرق بين المؤشرات الصريحة والضمنية في Oracle؟

StackOverflow https://stackoverflow.com/questions/74010

  •  09-06-2019
  •  | 
  •  

سؤال

أنا صدئ بعض الشيء في لغة المؤشر في PL/SQL.هل يعرف أحد هذا؟

هل كانت مفيدة؟

المحلول

المؤشر الضمني هو المؤشر الذي يتم إنشاؤه "تلقائيًا" لك بواسطة Oracle عند تنفيذ استعلام.من الأسهل برمجته، لكنه يعاني من ذلك

  • عدم الكفاءة (يحدد معيار ANSI أنه يجب إحضاره مرتين للتحقق مما إذا كان هناك أكثر من سجل واحد)
  • ثغرة أمنية تجاه أخطاء البيانات (إذا حصلت على صفين، فسيؤدي ذلك إلى ظهور استثناء TOO_MANY_ROWS)

مثال

SELECT col INTO var FROM table WHERE something;

المؤشر الصريح هو المؤشر الذي تقوم بإنشائه بنفسك.يتطلب الأمر المزيد من التعليمات البرمجية، ولكنه يوفر مزيدًا من التحكم - على سبيل المثال، يمكنك فقط الفتح والجلب والإغلاق إذا كنت تريد السجل الأول فقط ولا تهتم إذا كان هناك سجل آخر.

مثال

DECLARE   
  CURSOR cur IS SELECT col FROM table WHERE something; 
BEGIN
  OPEN cur;
  FETCH cur INTO var;
  CLOSE cur;
END;

نصائح أخرى

يتم تعريف المؤشر الصريح على هذا النحو في كتلة الإعلان:

DECLARE 
CURSOR cur IS 
  SELECT columns FROM table WHERE condition;
BEGIN
...

يتم تطبيق المؤشر الضمني مباشرة في كتلة التعليمات البرمجية:

...
BEGIN
   SELECT columns INTO variables FROM table where condition;
END;
...

1. المؤشر:عندما يصدر PLSQL عبارات SQL ، فإنها تنشئ منطقة عمل خاصة لتحليل وتنفيذ بيان SQL يسمى المؤشر.

2. ضمنيًا:عندما يصدر أي كتلة PL/SQL القابلة للتنفيذ بيان SQL.PL/SQL ينشئ المؤشر الضمني ويدير تلقائيًا يعني أن Enpricit Open & Close يحدث.تم استخدامه عند إرجاع بيان SQL صف واحد فقط. يحتوي على 4 سمات SQL ٪ ROWCOUNT ، SQL ٪ وجدت ، SQL ٪ notfound ، SQL ٪ isopen.

3. صريح:يتم إنشاؤه وإدارته من قبل المبرمج.يحتاج إلى كل مرة صريحة مفتوحة ، جلبها وإغلاقها.يتم استخدامه عند إرجاع بيان SQL أكثر من صف واحد.يحتوي أيضًا على 4 سمات cur_name ٪ rowcount ، cur_name found ، cur_name ٪ notfound ، cur_name ٪ isopen.يقوم بمعالجة عدة صفوف باستخدام الحلقة.يمكن للمبرمج تمرير المعلمة أيضًا إلى المؤشر الصريح.

  • مثال:المؤشر الصريح

 

declare 
   cursor emp_cursor 
   is 
   select id,name,salary,dept_id 
   from employees; 
   v_id employees.id%type; 
   v_name employees.name%type; 
   v_salary employees.salary%type; 
   v_dept_id employees.dept_id%type; 
   begin 
   open emp_cursor; 
   loop 
   fetch emp_cursor into v_id,v_name,v_salary,v_dept_id; 
   exit when emp_cursor%notfound;
   dbms_output.put_line(v_id||', '||v_name||', '||v_salary||','||v_dept_id); 
   end loop;                    
   close emp_cursor; 
   end;

المؤشر الصريح هو المؤشر الذي تعلنه، مثل:

CURSOR my_cursor IS
  SELECT table_name FROM USER_TABLES

المؤشر الضمني هو المؤشر الذي تم إنشاؤه لدعم أي SQL مضمن تكتبه (سواء كان ثابتًا أو ديناميكيًا).

تعد المؤشرات الضمنية هذه الأيام أكثر كفاءة من المؤشرات الصريحة.

http://www.Oracle.com/technology/oramag/Oracle/04-sep/o54plsql.html

http://asktom.Oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1205168148688

ردا على السؤال الأول.مباشرة من أوراكل توثيق

المؤشر هو مؤشر لمنطقة SQL الخاصة التي تخزن معلومات حول معالجة بيان محدد أو DML.

تتطلب المؤشرات الضمنية ذاكرة عازلة مجهولة.

يمكن تنفيذ المؤشرات الصريحة مرارًا وتكرارًا باستخدام اسمها. ويتم تخزينها في مساحة ذاكرة محددة من قبل المستخدم بدلاً من تخزينها في ذاكرة مؤقتة مجهولة، وبالتالي يمكن الوصول إليها بسهولة بعد ذلك.

باستخدام المؤشرات الصريحة، لديك سيطرة كاملة على كيفية الوصول إلى المعلومات في قاعدة البيانات.أنت تقرر متى تفتح المؤشر، ومتى تريد جلب السجلات من المؤشر (وبالتالي من الجدول أو الجداول في عبارة SELECT الخاصة بالمؤشر)، وعدد السجلات التي تريد جلبها، ومتى تغلق المؤشر.تتوفر معلومات حول الحالة الحالية للمؤشر من خلال فحص سمات المؤشر.

يرى http://www.unix.com.ua/orelly/Oracle/prog2/ch06_03.htm للتفاصيل.

جوجل هو صديقك: http://docstore.mik.ua/orelly/Oracle/prog2/ch06_03.htm

تصدر PL/SQL مؤشرًا ضمنيًا كلما قمت بتنفيذ عبارة SQL مباشرة في الكود الخاص بك ، طالما أن هذا الرمز لا يستخدم مؤشرًا صريحًا.يطلق عليه مؤشر "ضمني" لأنك ، المطور ، لا تعلن صراحة المؤشر لبيان SQL.

المؤشر الصريح هو عبارة محددة تم تعريفها بشكل صريح في قسم الإعلان في الكود الخاص بك ، وفي هذه العملية ، تم تعيين اسم.لا يوجد شيء مثل المؤشر الصريح للتحديث وحذف وإدراج البيانات.

المؤشر عبارة عن نافذة محددة في جدول أوراكل، ويعني ذلك مجموعة من السجلات الموجودة في جدول أوراكل، وتستوفي شروطًا معينة.يمكن للمؤشر تحديد كافة محتويات الجدول أيضًا.باستخدام المؤشر، يمكنك التعامل مع أعمدة Oracle، وجعلها مستعارة في النتيجة.مثال على المؤشر الضمني هو ما يلي:

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      FOR C1_REC IN C1
      LOOP
         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;
   END;
END;
/

مع ل...حلقة...END LOOP تقوم بفتح المؤشر وإغلاقه تلقائيًا، بعد أن يتم تحليل جميع سجلات المؤشر.

مثال على المؤشر الصريح هو ما يلي:

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      OPEN c1;

      LOOP
         FETCH c1 INTO c1_rec;

         EXIT WHEN c1%NOTFOUND;

         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;

      CLOSE c1;
   END;
END;
/

في المؤشر الصريح، تقوم بفتح المؤشر وإغلاقه بطريقة صريحة، والتحقق من وجود السجلات وتحديد شرط الخروج.

يقوم المؤشر الضمني بإرجاع سجل واحد فقط ويتم استدعاؤه تلقائيًا.ومع ذلك، يتم استدعاء المؤشرات الصريحة يدويًا ويمكنها إرجاع أكثر من سجل واحد.

أعلم أن هذا سؤال قديم، ولكن أعتقد أنه سيكون من الجيد إضافة مثال عملي لإظهار الفرق بين الاثنين من وجهة نظر الأداء.

من وجهة نظر الأداء، تكون المؤشرات الضمنية أسرع.

دعونا نرى الفرق في الأداء بين الاثنين:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2    l_loops  NUMBER := 100000;
  3    l_dummy  dual.dummy%TYPE;
  4    l_start  NUMBER;
  5
  6    CURSOR c_dual IS
  7      SELECT dummy
  8      FROM   dual;
  9  BEGIN
 10    l_start := DBMS_UTILITY.get_time;
 11
 12    FOR i IN 1 .. l_loops LOOP
 13      OPEN  c_dual;
 14      FETCH c_dual
 15      INTO  l_dummy;
 16      CLOSE c_dual;
 17    END LOOP;
 18
 19    DBMS_OUTPUT.put_line('Explicit: ' ||
 20                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 21
 22    l_start := DBMS_UTILITY.get_time;
 23
 24    FOR i IN 1 .. l_loops LOOP
 25      SELECT dummy
 26      INTO   l_dummy
 27      FROM   dual;
 28    END LOOP;
 29
 30    DBMS_OUTPUT.put_line('Implicit: ' ||
 31                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 32  END;
 33  /
Explicit: 332 hsecs
Implicit: 176 hsecs

PL/SQL procedure successfully completed.

لذلك، هناك فرق كبير واضح للعيان.

مزيد من الأمثلة هنا.

في PL/SQL، المؤشر هو مؤشر إلى منطقة السياق هذه.أنه يحتوي على جميع المعلومات اللازمة لمعالجة البيان.

المؤشرات الضمنية:يتم إنشاء المؤشرات الضمنية تلقائيًا بواسطة Oracle عند تنفيذ عبارة SQL، عندما لا يكون هناك مؤشر صريح للعبارة.لا يستطيع المبرمجون التحكم في المؤشرات الضمنية والمعلومات الموجودة فيها.

المؤشرات الصريحة:المؤشرات الصريحة هي مؤشرات يحددها المبرمج للحصول على مزيد من التحكم في منطقة السياق.يجب تحديد مؤشر صريح في قسم الإعلان في كتلة PL/SQL.يتم إنشاؤه على بيان SELECT الذي يقوم بإرجاع أكثر من صف واحد.

بناء الجملة لإنشاء مؤشر صريح هو:

CURSOR cursor_name IS select_statement; 

تحتوي كل عبارة SQL يتم تنفيذها بواسطة قاعدة بيانات Oracle على مؤشر مرتبط بها، وهي منطقة عمل خاصة لتخزين معلومات المعالجة.يتم إنشاء المؤشرات الضمنية بواسطة خادم Oracle لجميع عبارات DML وSELECT.

يمكنك الإعلان عن المؤشرات الصريحة واستخدامها لتسمية منطقة العمل الخاصة، والوصول إلى معلوماتها المخزنة في كتلة البرنامج الخاصة بك.

كما هو مذكور في الإجابات الأخرى، فإن المؤشرات الضمنية أسهل في الاستخدام وأقل عرضة للخطأ.

و ضمني مقابل.المؤشرات الصريحة في Oracle PL/SQL يُظهر أن المؤشرات الضمنية أسرع بما يصل إلى مرتين من المؤشرات الصريحة أيضًا.

ومن الغريب أن أحدا لم يذكر بعد ضمني لمؤشر LOOP:

begin
  for cur in (
    select t.id from parent_trx pt inner join trx t on pt.nested_id = t.id
    where t.started_at > sysdate - 31 and t.finished_at is null and t.extended_code is null
  )
  loop
    update trx set finished_at=sysdate, extended_code = -1 where id = cur.id;
    update parent_trx set result_code = -1 where nested_id = cur.id;
  end loop cur;
end;

مثال آخر على SO: PL/SQL للمؤشر الضمني للحلقة.

إنها طريقة أقصر من النموذج الصريح.

يوفر هذا أيضًا حلاً لطيفًا لـ تحديث جداول متعددة من CTE.

صريح...

يتم تحديد المؤشر foo * من بلاه؛ابدأ Open Fetch Exit عند إغلاق المؤشر Yada Yada Yada

لا تستخدمها، استخدم ضمنيًا

يتم تحديد المؤشر foo * من بلاه؛

لـ n في حلقة foo x = n.some_column end loop

أعتقد أنه يمكنك حتى القيام بذلك

لـ n في حلقة (اختر * من بلاه) ...

التزم بالكلمات الضمنية، فهي تغلق نفسها، وتكون أكثر قابلية للقراءة، وتجعل الحياة سهلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top