delphi4arab منتديات دلفي للعرب

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

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

والسلام عليكم
إقتباس : (هناك اشياء يراها اشخاص اخطاء واخرون رائعة 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

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

هذا هوا الحل Smile

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

لكن سوف تظهر مشكلة في حال قيام مجموعة من المستخدمين بالعمل عليه في نفس الوقت، لذا يمكن استخدام الحل الذي ذكره اخي محمد المتعلق بال Triggers وانا استخدمه مع SQL Server وهناك حل اخر، عن طريق انشاء جدول جديد يحتوي على حقل يعمل كالعداد، وفي حال تخزين سجل جديد يتم اخذ القيمة من الحقل في هذا الجدول واضافة عليه واحد مثلاً وتخزين القيمة الجديدة، لكن يجب عليك ان تعمل Lock للجدول حتى لا ياخذ اكثر من مستخدم نفس الرقم (lock اقصده على الجدول في قاعدة البيانات وليس ضمن دلفي)، وذلك يعتمد على قاعدة البيانات المستخدمة.
هناك طريقه (و لكل شيخ طريقته :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;
إقتباس :حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
بارك الله فيك أستاذ وجزاك خيرا، سأفعل ما بوسعي.

شكرا كثيرا محمد نسمان على التدخل، مع افتراض استعمال 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
شكرا كثيرا لكم، بارك الله فيكم جميعا، وجزاك الله خيرا أستاذ.
السلام عليكم ورحمة الله وبركاته

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

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

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

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

أقوم بإنشاء جدول يقوم بحفظ آخر قيمة تم إضافتها و أسميه 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;
تحياتي
الصفحات : 1 2