delphi4arab منتديات دلفي للعرب
تخريج قيمة تلقائية للحقول التعريفية - نسخة قابلة للطباعة

+- delphi4arab منتديات دلفي للعرب (https://delphi4arab.net/forum)
+-- قسم : منتديات دلفي للعرب التعليمية (https://delphi4arab.net/forum/forumdisplay.php?fid=3)
+--- قسم : سؤال و جواب حول دلفي (https://delphi4arab.net/forum/forumdisplay.php?fid=15)
+--- الموضوع : تخريج قيمة تلقائية للحقول التعريفية (/showthread.php?tid=976)

الصفحات: 1 2


تخريج قيمة تلقائية للحقول التعريفية - kachwahed - 22-06-2009

السلام عليكم
في برامج قواعد البيانات، في جدول هناك حقل تعريفي (اسمه عادة بالشكل NameFieldID)، بحيث تخريج قيمة تعريفية لهذا الحقل تتكون عادة من لاحقة (suffix) ورقم متزايد تلقائيا، مثل CL0001 أو FV0001.
ما هي أفضل طريقة للقيام بتخريج مثل هذه القيم؟ وما هي القواعد التي تجب مراعتها في ذلك؟ )يعني هل أكتبها في الحدث BeforePost، وهل أضيف إليها لاحقة من حقل آخر...).
شكرا كثيرا


تخريج قيمة تلقائية للحقول التعريفية - محمد عبد العزيز - 22-06-2009


افظل هذا شيئ نسبي (هناك اشياء يراها اشخاص اخطاء واخرون رائعة Big Grin)
لو كانت القاعدة تسمح Trigger والحدث استخدم "BeforeInsert"
ان كانت القاعدة لا تسمح يمكن اضافة Function ترجع لك الرقم
هنا يمكن ان يكون الحقل String او Integer
ان كان لديك دليل فريد على ذلك الحقل يمكن ان تاخذ اخر Table.Last وتظيف اليه واحد
او يمكن استخدام استعلام بشيئ مثل MAX للحصول على اكبر رقم وتظيف اليه واحد
وبرمجيا تظيف اليه اصفار يسارا حسب الطول المختار + الحرفين

والسلام عليكم



تخريج قيمة تلقائية للحقول التعريفية - kachwahed - 23-06-2009

إقتباس : (هناك اشياء يراها اشخاص اخطاء واخرون رائعة Big Grin)
...كانت مجرد وجهة نظر :o، ...وأحيانا يتفقون :p

اكتفيت بكتابة شيء مثل:
PHP كود :
if not (DataSet.State = dsInsert) then Exit;
  
DataSet.FieldByName('BookID').AsString := 'BK'+
  
Format('%0.4d',[DataSet.RecordCount+1]); 

في الحدث BeforePost.
... لكن المشكلة إذا حذف تسجيل سابق، فسيحدث خلل عند إضافة تسجيل جديد
مثلا:
في هذا المثال: ستكون قيمة الحقل في أول تسجيل: BK0001 والذي بعده BK0002
لكن ماذا سيحدث لو قام المستخدم بحذف السطر المعرف بـ : BK0001 ثم حاول إضافة حقل جديد...
سيفاجئ برسالة خطأ لأن القيمة المخرجة هي BK0002 وهي نفس القيمة في السطر السابق، ذلك لأن الحقل مفتاح أساسي لا يقبل قيم مكررة.
ما أفضل طريقة للتخلص من ذلك؟
شكرا مسبقا Big Grin



تخريج قيمة تلقائية للحقول التعريفية - محمد عبد العزيز - 23-06-2009


حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
1- إنسى RecordCount ولاتستخدمها - فكر



تخريج قيمة تلقائية للحقول التعريفية - محمد نسمان - 23-06-2009

DeltaAziz كتب :
حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
1- إنسى RecordCount ولاتستخدمها - فكر

هذا هوا الحل Smile

اذا كان برنامجك يعمل عليه مستخدم واحد فاسهل طريقة كما ذكر اخي محمد ان تعمل Max للحقل وتضيف عليه واحد

لكن سوف تظهر مشكلة في حال قيام مجموعة من المستخدمين بالعمل عليه في نفس الوقت، لذا يمكن استخدام الحل الذي ذكره اخي محمد المتعلق بال Triggers وانا استخدمه مع SQL Server وهناك حل اخر، عن طريق انشاء جدول جديد يحتوي على حقل يعمل كالعداد، وفي حال تخزين سجل جديد يتم اخذ القيمة من الحقل في هذا الجدول واضافة عليه واحد مثلاً وتخزين القيمة الجديدة، لكن يجب عليك ان تعمل Lock للجدول حتى لا ياخذ اكثر من مستخدم نفس الرقم (lock اقصده على الجدول في قاعدة البيانات وليس ضمن دلفي)، وذلك يعتمد على قاعدة البيانات المستخدمة.


تخريج قيمة تلقائية للحقول التعريفية - Prince - 23-06-2009

هناك طريقه (و لكل شيخ طريقته :d )

بما انك تستخدم آليه اضافة رقم مكون من 4 خانات مسبوق بالحرفين BK

كود :
{*********} if not (DataSet.State = dsInsert) then Exit; DataSet.FieldByName('BookID').AsString := 'BK'+ Format('%0.4d',[GetMax+1]); {*********} function GetMax : Integer; var S : String; Max, CValue : Integer; begin With Table do begin First; Max := 1; While not EOF do begin S := Copy(Table.FieldByName('BookID').AsString,3,4); CValue := StrToInt(S); if CValue > Max then Max := CValue; Next; end; end; Result := Max; end;



تخريج قيمة تلقائية للحقول التعريفية - kachwahed - 24-06-2009

إقتباس :حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
بارك الله فيك أستاذ وجزاك خيرا، سأفعل ما بوسعي.

شكرا كثيرا محمد نسمان على التدخل، مع افتراض استعمال TADOTable (باستبعاد الاستعلامات SQL) ودون استعمال محرك SQL Server (أي لا توجد Stored Proc).
شكرا كثيرا أخي Prince على الدالة (ينقصها DisableControls و EnableControls لتسريع الفحص Big Grin) ، لكن انتبه في استعمال First و Next عند استدعاء الدالة في BeforePost أو ما يشبهها، كود تفحص الجدول بهذه الطريقة هو آخر حل، كتبت دالة CheckKeyID(DataSet: TDataSet): Boolean بنفس الطريقة، للتحقق من وجود المفتاح ثم حذفتها Big Grin.

حسنا...
إقتباس : إنسى RecordCount ولاتستخدمها - فكر
يبقى لدينا:
1- استعمال RecNo بدلا عنها Big Grin، بشيء مثل:
PHP كود :
private
    
MaxRec: Integer;
...
procedure TForm2.ADOTable1BeforeInsert(DataSet: TDataSet);
begin
  MaxRec 
:= DataSet.RecNo + 1;
end;

procedure TForm2.ADOTable1BeforePost(DataSet: TDataSet);
begin
  
if not (DataSet.State = dsInsert) then Exit;
  
DataSet.FieldByName('BookID').AsString := 'BK'+ Format('%0.4d',[MaxRec+1]);
end; 
لكن في هذه الحالة يبقى لدينا نفس المشكل، مع مشكل جديد، هو رسالة خطأ عند إضافة (Insert) تسجيل في وسط الجدول، لأن RecNo ستأخذ حتما قيمة مكررة بخلاف RecordCount.

2- حساب أكبر قيمة بشكل يدوي، مثال ( MaxRec هو integer لتخزين أعلى قيمة):
PHP كود :
procedure TForm2.ADOTable1BeforeInsert(DataSet: TDataSet);
begin
  MaxRec 
:= StrToInt(Copy(DataSet.fieldbyname('BookID').asString, 3,5));
end;

procedure TForm2.ADOTable1BeforePost(DataSet: TDataSet);
begin
  DataSet
.FieldByName('BookID').AsString := 'BK'+ Format('%0.4d',[MaxRec+1]);
end; 
هناك من يستعمل الحدث OnNewRecord عوضا عن BeforePost.
في هذه الحالة نكون قد تخلصنا من إشكالية تكرار نفس القيمة عند حذف قيم سابقة، لأن الخلية ستأخذ العدد الموالي لآخر عدد في الجدول، يبقى إشكال صغير وهو عند إضافة تسجيل عند وسط الجدول، هذا يمكن تفاديه بإضافة DataSet.Last في الحدث BeforeInsert، وبذلك نجبر المستعمل على إضافة تسجيلاته في آخر الجدول.
وبهذا أظن المشكلة حلت، لكن ماذا لو أراد المستعمل إضافة تسجيل في وسط الجدول :confused: هل سنقنعه بألا يفعل ذلك Big Grin
شكرا كثيرا لكم، بارك الله فيكم جميعا، وجزاك الله خيرا أستاذ.



تخريج قيمة تلقائية للحقول التعريفية - Eagle - 27-06-2013

السلام عليكم ورحمة الله وبركاته

عندي برنامج مبيعات عملته يعمل على جهاز واحد وبعد ذلك تم التوسع على شبكة
المشكلة في حالة عمل عدة مستخدمين على جدول الفاتورة الاساسي والحفظ في نفس الوقت يحدث
تكرار في الرقم ID أو تظهر رسالة .........Row Cannot update
فما الحل الصحيح في التعامل مع برامج الشبكات
استخدم دلفي 7 وقاعدة بيانات SQL 2005 **** منكم الرد وجزاكم الله خيرا


تخريج قيمة تلقائية للحقول التعريفية - Eagle - 27-06-2013

محمد نسمان كتب :هذا هوا الحل Smile

اذا كان برنامجك يعمل عليه مستخدم واحد فاسهل طريقة كما ذكر اخي محمد ان تعمل Max للحقل وتضيف عليه واحد

لكن سوف تظهر مشكلة في حال قيام مجموعة من المستخدمين بالعمل عليه في نفس الوقت، لذا يمكن استخدام الحل الذي ذكره اخي محمد المتعلق بال Triggers وانا استخدمه مع SQL Server وهناك حل اخر، عن طريق انشاء جدول جديد يحتوي على حقل يعمل كالعداد، وفي حال تخزين سجل جديد يتم اخذ القيمة من الحقل في هذا الجدول واضافة عليه واحد مثلاً وتخزين القيمة الجديدة، لكن يجب عليك ان تعمل Lock للجدول حتى لا ياخذ اكثر من مستخدم نفس الرقم (lock اقصده على الجدول في قاعدة البيانات وليس ضمن دلفي)، وذلك يعتمد على قاعدة البيانات المستخدمة.

اتمنى توضيح Triggers وكيفية استخدامه لاخد أكبر قيمة من جدول بحيث في حالة وجود عدة مستخدمين لايحصل تكرار كيف يتم عمل Lock للجدول بحيث لايمكن اكثر من مستخدم نفس الرقم
وشكرا


تخريج قيمة تلقائية للحقول التعريفية - AnoirsoftDeveloper - 28-06-2013

السلام عليكم
إليك طريقتي التي أستعملها

أقوم بإنشاء جدول يقوم بحفظ آخر قيمة تم إضافتها و أسميه Compter

ثم أنشئ حقول حسب الإحتياج

ClientID
...
.
.

ثم أكتب في الحدث OnBeforePost الخاص بـجدول الزبائن Client

كود :
procedure Tform1.TableClientBeforePost(DataSet: TDataSet); begin if TableClient.State = dsInsert then begin TableCompter.edit; TableCompterClientID.Value:=TableCompterClientID.Value+1; TableCompter.Post; end; end;
واكتب في الحدث OnNewRecord

كود :
procedure TfrmMain.TableClientNewRecord(DataSet: TDataSet); begin // هنا أكتب اللاحقة التي تريدها TableClientID.Value:=TableCompterClientID.value+1; end;
تحياتي