الانتقال إلى المحتوى

الرجوع الي خطوة معينة من كود Pl/sql


MMA

Recommended Posts

إخواني الكرام ، تحية طيبة وبعد ،

أولاً ، أعتزر إذا كان الموضوع متكرر ( والله أعلم ) ، حيث أنني بحثت علي جملة GoTo ولم أجد لها أي أثر !!!

المهم ، أنا مشكلتي هو أنني قمت بإجراء Procedure وكتبت به مجموعة من السطور البرمجية ، ولكنني أرغب في نهاية السطر يتم الرجوع الي سطر معين بأعلي الكود بحيث أن أجعلة يراجع خطوات برمجية معينة !!!

مثال وهمي :

Declare
  X   Number;
Begin
  X := 1;
  NextLoop:
  X := X + 1;
  If(X <= 10)Then
	GoTo  NextLoop;
  End If;
End;



الهدف الأساسي من القطعة البرمجية السابقة ليس إنشاء Loop بل الرجوع الي خطوة معينة عند الطلب !!!

أتمني أن تكونوا فهمتم ما أقصدة

ولكنني حقيقتاً في الوضع الحالي أستخدم أسلوب إستدعاء الإجراء procedure ككل من جديد علي أساس شرط معين أو باراميتر معين كما يلي :


Procedure PName(P1  Number Default Null)
As
Begin
  -----------------------;
  -----------------------;
  -----------------------;
  -----------------------;
  -----------------------;
  -----------------------;
  If(Not P1 Is Null)Then
  PName(15);
  End If;
End;
/






شكراً ، ويارب أجد حل أفضل :rolleyes: :P

مصطفي محمود

رابط هذا التعليق
شارك

مبدائياً أنا لا أنصحك بأستخدام ال GOTO بكثرة لأن قراءة الكود فيما بعد سيكون صعب و معقد ..... و كما تعرف من المفيد ان نحاول قدر الامكان ان يكون الكود سهل القراءة لأننا فى اى وقت لاحق قد نطر لصيانته و معالجته ..... اما لما تريده فالحل الافضل هو ال Exception Handling .

انا بحثت عن ال GOTO فى ال PL/SQL User's Guide and Reference 10g Release 2

و وجدت ما تريد .... من ص 129 الى 131

و هو يشرح ال GOTO بعدة أمثلة ...... منها :-

DECLARE
  p   VARCHAR2 (30);
  n   PLS_INTEGER   := 37;				 -- test any integer > 2 for prime
BEGIN
  FOR j IN 2 .. ROUND (SQRT (n))
  LOOP
  IF n MOD j = 0
  THEN												  -- test for prime
	 p := ' is not a prime number';				 -- not a prime number
	 GOTO print_now;
  END IF;
  END LOOP;

  p := ' is a prime number';

  <<print_now>>
  DBMS_OUTPUT.put_line (TO_CHAR (n) || p);
END;
/



DECLARE
  done   BOOLEAN;
BEGIN
  FOR i IN 1 .. 50
  LOOP
  IF done
  THEN
	 GOTO end_loop;
  END IF;

  <<end_loop>>	   -- not allowed unless an executable statement follows
  NULL;							   -- add NULL statement to avoid error
  END LOOP;					  -- raises an error without the previous NULL
END;
/



DECLARE
  v_last_name   VARCHAR2 (25);
  v_emp_id	  NUMBER (6)	:= 120;
BEGIN

  <<get_name>>
  SELECT last_name
 INTO v_last_name
 FROM employees
WHERE employee_id = v_emp_id;

  BEGIN
  DBMS_OUTPUT.put_line (v_last_name);
  v_emp_id := v_emp_id + 5;

  IF v_emp_id < 120
  THEN
	 GOTO get_name;						  -- branch to enclosing block
  END IF;
  END;
END;
/



اتمنى انا يكون كلامى واضح ...... و لو فى اى حاجه غامضه ابقى قولى .

مع تمنياتى بالتوفيق لك .

فى سلامة الله

رابط هذا التعليق
شارك

أولاً أخي أنا أشكرك كل الشكر علي حسن معاونتك لي ، حيث صراحتاً أنا كنت أحاول أوظف أمر الـ GoTo ولمنني دون إدراج السطر الذي سيتم الإرتجاع الية بين علامتي << >> ، فأشكرك كل الشكر

أما بالنسبة لنصيحتك فهي غالية جداً وفعلاً كلام سليم 100 %

ولكن أخي معزرتاً ، أنا واجهتني مشكلة في الأوراكل حينما أنشأ Cursor ، المطلوب أنني أربط مع جدول معين هذا الجدول سيتم جلبة عن طريق الـ Cursor ولكنني أثناء عملية الجلب Fetch كنت أرغب في إجراء Insert أكثر من مرة علي أساس شرط معين ولكن الـ Cursor عند فتحة Open لا يتغير محتوياتة إلا بعد إغلاقة Close ومن ثم فتحة من جديد Open !!!

عكس الـ SQL-Server حيث يقوم بتحديث تلقائي للـ Cursor ، ولكن هذا صحيح إحدي العيوب لأن من المنطق جلب المحتويات الحالية !!!

أما طلبي لأمر GoTo سببة هو أنني أرغب في إنشاء تقرير هذا التقرير يحتوي علي مجموعات الأصناف بحيث إذا تم تحديد مجموعة معينة يتم عرض كل محتوياتها من أصناف ، ولكن أخي أنا أرغب في وضع المجموعات علي هيئة Tree بحيث أن هناك علاقة خيالية منها الي لها !!!

Create Table Item_Group
(
  Group_ID	Number(20),
  Group_Code VarChar2(20),
  Group_Name VarChar2(50),
  Group_GroupID Number(20),
  Group_Master  Number(1)
)
/



حيث أن الـ Group_GroupID هو يمثل حقل مجموعة من نفس الجدول ، والمطلوب بالضبط عند إختيار مجموعة تكون مجموعة رئيسية يتم جلب كافة المجموعات الغير رئيسية أياً كانت تحتوي علي مجموعات رئيسية أو لا .


أخي الغالي ، ممكن سؤال آخر ويارب أجد جواب !!!

أنا في الـ SQL يمكنني بناء جملة إستعلام تحديد Select علي متغير نصي ومن ثم أرتجع بالقيمة النصية بقيمة إستعلام يتحول الي مجموعة من الـ Records ، مثال وهمي :

Cursor Cur_Emp Is Execute Immediate 'Select * From Emp';



وسؤال آخر ، من الطبيعي إستخدام جداول Temp هل هذه الجداول يجب إنشائها ومن ثم تركها بصفة مستمرة ، أم يجوز إجراء Create و Drop للجدول كما يشاء كما أعتدت مع SQL-Server ؟؟


آسف جداً علي كثرة أسألتي


شكراً

تم تعديل بواسطة MMA
رابط هذا التعليق
شارك

للسؤال الاول ......لا يجوز استخدام ال execute immediate مع ال cursor ..... فهذا هو الحل :-

SQL> declare
 2  Cursor Cur_Emp Is Execute Immediate 'Select * From Emp';
 3  begin
 4  null;
 5  end;
 6  /
Cursor Cur_Emp Is Execute Immediate 'Select * From Emp';
			  *
ERROR at line 2:
ORA-06550: line 2, column 19:
PLS-00103: Encountered the symbol "EXECUTE" when expecting one of the
following:
( select <a SQL statement>


SQL> ed
Wrote file afiedt.buf

 1  declare
 2  Cursor Cur_Emp Is Select * From Emp;
 3  begin
 4  null;
 5* end;
SQL> /

PL/SQL procedure successfully completed.



اما السؤال الثانى :-

يمكنك عمل create و drop لأى جدول لديك بدون اى مشاكل على الاطلاق ...... و هذا الكود يمكنك استخدامه عندما تريد ان تظهر كل الجداول التى لديك فى الاسكيمة :-

SQL> select * from tab;

TNAME						  TABTYPE  CLUSTERID
------------------------------ ------- ----------
DEPT						   TABLE
EMP							TABLE
BONUS						  TABLE
SALGRADE					   TABLE
EMP2						   TABLE



اتمنى ان تكون الاجابه واضحة ...... ولا تتردد فى سؤالك مرة اخرى عن اى شىء غامض لديك .

مع تمنياتى لك بالتوفيق.

تم تعديل بواسطة hanyfreedom
رابط هذا التعليق
شارك

شكراً أخي الكريم ، بس أنا كان لي فكر آخر ،

السؤال الأول :

ليس القصد منه هو بناء Cursor يحتوي علي قيمة نصية بل كيفية تنفيذ قيمة نصية علي هيئة Select !!!!

بمعني أدق ، أنا أستخدم الكود التالي داخل النموذج :

Forms_DDL('Select * From Emp');



وهذا من داخل الـ PL/SQL Database :

Execute Immediate 'Select * From Emp';



في الوضع الحالي أنا أنشأ جدول يحتوي علي البيانات ومن ثم أرتجع البيانات في Cursor كما يلي :

Forms_DDL('Create Table Employee As Select * From Emp Where Emp_Sex = 1');
Declare
  Cursor Cur_Emp Is Select * From Employee;
Begin
  Null;
End;
/



لكن أخي لاحظ أن الجدول Employee شبية بالجدول Temp !!!!

فإذا كان جدول الـ Temp غير موجود يعرض لي رسالة بعدم وجود جدول الـ Temp عند سطر الـ Cursor ، مع العلم أنني لا أرغب في وجود جدول الـ Temp بصفة مستمرة مجرد جلب البيانات فقط لا غير ومن ثم حذفها كما يلي :

Forms_DDL('Drop Table Employee');



فما الحل إذاً ، الحل الوحيد في SQL/Server هو دالة شبيهة بـ Forms_DDL ولكن لها إمكانية أفضل وهي القدرة علي إرتجاع نتائج التنفيذ كما يلي :

Create Procedure List_Emp
As
Begin
  Execute Execute_SQL 'Select * From Emp'
End;
/



وبمجرد إستدعائة يرتجع كافة السجلات المحددة ، ولكن ماذا عن الأوراكل !!!

السؤال الثاني :

تقريباً مشابه للسؤال الأول ، ولكن أثناء إنشاء Procedure !!!

بمعني أدق ، الـ Procedure يحتوي علي مجموعة من جمل الإستعلام وجمل DDL ، ومن ثم إستخدام الـ Cursor الضمني أو التعريفي مما يؤدي الي حدوث خطأ ( علي نفس السؤال السابق ) ، فكيف يمكنن إنشاء مثل هذا الإجراء ؟؟؟؟


جزاك الله كل خير

شكراً

رابط هذا التعليق
شارك

طب إخواني ، إسمحوا لي أن أبسط لكم الأمور أكثر !!!

أنا كتبت الكود التالي في Form Builder :

Begin
  Forms_DDL('Select * From Emp');
End;



والموضوع مشي معايا تمام ، لكن معني هذا أن هناك حل يمكنني جلب ما تم إرتجاعة ( أليس كذلك )

ياريت يكون سؤالي هذه المرة واضح

شكراً

رابط هذا التعليق
شارك

بالنسبة لأخر حاجه قولتها ...... فعلى حد علمى انه مش هينفع تسترد البيانات الا من وضع البيانات فى variables من خلال cursor و من ثم وضعها فى حقول الفورمز ( و طبعاً هنا هنكون أستثنينا ال forms_ddl ) ......... و الملف المرفق هو شرح عملى لما قلته .

قولى ايه بالظبط الشكل النهائى اللى انت عاوزه يطلع عندك على الشاشة النهائية ل end user
علشان اقدر افهم الفكرة الكلية لمشكلتك

لو تقدر ترفق مع شرحك عينة fmb و ال source code ان امكان يبقى كويس .

و شكراً

CURSOR.zip

تم تعديل بواسطة hanyfreedom
رابط هذا التعليق
شارك

الأخ الغالي ، تحية طيبة وبعد ،

في الحقيقة أنا الحمد لله أعلم كيفية إستخدام الـ Cursor جيداً سواء من داخل قاعدة البيانات أو من داخل الـ Database ، وهذا يرجع الي المنتدي الكريم ( حقاً مدرسة كبيرة وكريمة ) .

ولكن أخي أنا ما أقصدة ما يلي :

أنا أرغب في إنشاء جدول من داخل الديفيلوبار ومن ثم تخزين بيانات بداخلها وإرتجاع القيم بأي طريقة سواء Cursor أو غيرها المهم أرتجع كل القيم التي قمت بتخزينها بالجدول وبعد عرض محتوياتها أقم بحذفها علي الفور مثل جداول الـ Temp ، ولكن أخي عندما فكرت في تنفيذ البرنامج وأنا مصمم Cursor يحتوي علي جملة إستعلام من جدول غير موجود من الطبيعي سيعرض لي خطأ ولم ينفذ البرنامج من البداية ، أنظر المثال التالي :

نفرض أننا لدينا جدول يدعي Emp وبه حقل إسم الموظف يدعي Emp_Name ، المطلوب إدراج جدول جديد يحتوي علي كافة أسماء الموظفين علي أساس راتب معين ( كعلي سبيل المثال ) ، ومن ثم عرض سجلات هذا الجدول كما بالمثال الوهمي التالي :


Begin
  Forms_DDL('Create Table Temp_Emp As Select Emp_Name From Emp Where Emp_Salary = 1500');
  Declare
  Cursor Cur Is Select Emp_Name From Temp_Emp;
  ID_Name  VarChar2(50);
  Begin
  Open Cur;
  Fetch Cur Into ID_Name;
  While Cur%Found
  Loop
	 Message(ID_Name);
	 Message(ID_Name);
	 Fetch Cur Into ID_Name;
  End Loop;

  Close Cur;

  Forms_DDL('Drop Table Temp_Emp');
  End;
End;



لكن أخي لاحظ جيداً ، عند تشغيل النموذج Ctrl+R سيرفض النموذج الفتح ، أو حتي لو قمنا بإنشاء ملف fmx بإستخدام Ctrl+T سيرفض أيضاً لأن قاعدة البيانات لا تحتوي علي جدول Temp_Emp من أساسة ، ولكن الجدول الفعلي هو Emp ، صحيح يمكنني صناعة ما أشاء من خلال جدول Emp ولكن هناك حالات خاصة يجعلني أنشأ جداول الـ Temp ، والمشكلة أنني إذا أنشأت جدول Temp سيصبح قاعدة البيانات بها جداول مساعدة كثيرة Temp ويحدث لي لخبطة !!!

ها هي مشكلتي ، أرغب في إنشاء جدول والتعامل معه بكل سهولة ويسر ومن ثم أحذفة كما أشاء دون عرض رسالة تفيد بعدم وجود الجدول عند إنشاء الـ Cursor لذلك ظننت أن الأمر التالي سينفع :

Forms_DDL('Select * From Temp_Emp');



وهذا هو ما كنت أفعلة مع الـ SQL-Server ، فهل هناك حل آخر


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



جزاك الله كل خير

شكراً

تم تعديل بواسطة MMA
رابط هذا التعليق
شارك

الأخ / مصطفى

يمكنك استخدام اسلوب ال array او المصفوفه لتحميل بيانات الجدول فى الذاكرة ... والتعامل معها ...

اليك هذه المشاركة السابقة بالمنتدى

إضغط هنا : انشاء مصفوفه -array - للتعامل مع بيانات جدول

ايضا ... إضغط هنا

ارجوا ان يكون هذا ما تبحث عنه

رابط هذا التعليق
شارك

ارجوا ان يكون هذا ما تبحث عنه


:rolleyes: بصراحة أخي أنا لم أقصد المصفوفات نهائياً !!!


لكن أخي ، أنظر الي المرفق



شكراً

Simble.zip

رابط هذا التعليق
شارك

طب إخواني أسمحوا لي أن أعرض لكم تفسير آخر وهو كما موضح بالمرفق !!!


أنا لدي جدول يدعي الصنف ، لكل صنف يمكن أن يكون له أكثر من سعر مثل ( سعر جملة / سعر مستهلك / سعر خاص / ----- الي آخرة ) فكان الحل الأمثل لي هو عند إنشاء كارت الصنف أنشأ جريد يحتوي علي أكثر من عمود بحيث أن لكل عمود يمثل سعر معين ، لكل وحدة ( حبة - شريط - علبة - كارتونة - شوال - .... الي آخرة ) ، صحيح أنا أدرج الأسعار بجدول لكن المستخدم يراة كأنة في صف واحد ويرجع الفضل الي اللعب بالبرمجة وإستخدام آداة الـ Grid !!!

وكان هذا ما كنت أفعلة في الفيجوال 6.0 ، ولكن الآن في الأوراكل وجدت أن هناك بلوكات ممتازة ، فكيف أفعل كما شرحت بالمرفق




شكراً

Mail.zip

تم تعديل بواسطة MMA
رابط هذا التعليق
شارك

أنا آسف جداً أخواني لأنني وضعت سؤالي الأخير بهذا القسم حيث كان من واجبي إدراجه بقسم الفورمس .

أكرر أسفي للجميع

سأعرض مشكلتي بقسم الفورمز

شكراً

رابط هذا التعليق
شارك

انضم إلى المناقشة

يمكنك المشاركة الآن والتسجيل لاحقاً. إذا كان لديك حساب, سجل دخولك الآن لتقوم بالمشاركة من خلال حسابك.

زائر
أضف رد على هذا الموضوع...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   تمت استعادة المحتوى السابق الخاص بك.   مسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

جاري التحميل
×
×
  • أضف...

برجاء الإنتباه

بإستخدامك للموقع فأنت تتعهد بالموافقة على هذه البنود: سياسة الخصوصية