المشاركات : 2,293
المواضيع 157
:
: 81
الإنتساب : Dec 2008
السلام عليكم
في برامج قواعد البيانات، في جدول هناك حقل تعريفي (اسمه عادة بالشكل NameFieldID)، بحيث تخريج قيمة تعريفية لهذا الحقل تتكون عادة من لاحقة (suffix) ورقم متزايد تلقائيا، مثل CL0001 أو FV0001.
ما هي أفضل طريقة للقيام بتخريج مثل هذه القيم؟ وما هي القواعد التي تجب مراعتها في ذلك؟ )يعني هل أكتبها في الحدث BeforePost، وهل أضيف إليها لاحقة من حقل آخر...).
شكرا كثيرا
المشاركات : 3,703
المواضيع 101
:
: 579
الإنتساب : Feb 2008
افظل هذا شيئ نسبي (هناك اشياء يراها اشخاص اخطاء واخرون رائعة
)
لو كانت القاعدة تسمح Trigger والحدث استخدم "BeforeInsert"
ان كانت القاعدة لا تسمح يمكن اضافة Function ترجع لك الرقم
هنا يمكن ان يكون الحقل String او Integer
ان كان لديك دليل فريد على ذلك الحقل يمكن ان تاخذ اخر Table.Last وتظيف اليه واحد
او يمكن استخدام استعلام بشيئ مثل MAX للحصول على اكبر رقم وتظيف اليه واحد
وبرمجيا تظيف اليه اصفار يسارا حسب الطول المختار + الحرفين
والسلام عليكم
المشاركات : 2,293
المواضيع 157
:
: 81
الإنتساب : Dec 2008
إقتباس : (هناك اشياء يراها اشخاص اخطاء واخرون رائعة
)
...كانت مجرد وجهة نظر :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 وهي نفس القيمة في السطر السابق، ذلك لأن الحقل مفتاح أساسي لا يقبل قيم مكررة.
ما أفضل طريقة للتخلص من ذلك؟
شكرا مسبقا
المشاركات : 3,703
المواضيع 101
:
: 579
الإنتساب : Feb 2008
حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
1- إنسى RecordCount ولاتستخدمها - فكر
المشاركات : 80
المواضيع 8
:
: 0
الإنتساب : Mar 2009
DeltaAziz كتب :
حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
1- إنسى RecordCount ولاتستخدمها - فكر
هذا هوا الحل
اذا كان برنامجك يعمل عليه مستخدم واحد فاسهل طريقة كما ذكر اخي محمد ان تعمل Max للحقل وتضيف عليه واحد
لكن سوف تظهر مشكلة في حال قيام مجموعة من المستخدمين بالعمل عليه في نفس الوقت، لذا يمكن استخدام الحل الذي ذكره اخي محمد المتعلق بال Triggers وانا استخدمه مع SQL Server وهناك حل اخر، عن طريق انشاء جدول جديد يحتوي على حقل يعمل كالعداد، وفي حال تخزين سجل جديد يتم اخذ القيمة من الحقل في هذا الجدول واضافة عليه واحد مثلاً وتخزين القيمة الجديدة، لكن يجب عليك ان تعمل Lock للجدول حتى لا ياخذ اكثر من مستخدم نفس الرقم (lock اقصده على الجدول في قاعدة البيانات وليس ضمن دلفي)، وذلك يعتمد على قاعدة البيانات المستخدمة.
المشاركات : 16
المواضيع 3
:
: 0
الإنتساب : Dec 2008
هناك طريقه (و لكل شيخ طريقته :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;
المشاركات : 2,293
المواضيع 157
:
: 81
الإنتساب : Dec 2008
إقتباس :حسنا ساساعدك لايجاد الحل دون اعطائك اياه (تجده بنفسك)
بارك الله فيك أستاذ وجزاك خيرا، سأفعل ما بوسعي.
شكرا كثيرا محمد نسمان على التدخل، مع افتراض استعمال TADOTable (باستبعاد الاستعلامات SQL) ودون استعمال محرك SQL Server (أي لا توجد Stored Proc).
شكرا كثيرا أخي Prince على الدالة (ينقصها DisableControls و EnableControls لتسريع الفحص
) ، لكن انتبه في استعمال First و Next عند استدعاء الدالة في BeforePost أو ما يشبهها، كود تفحص الجدول بهذه الطريقة هو آخر حل، كتبت دالة CheckKeyID(DataSet: TDataSet): Boolean بنفس الطريقة، للتحقق من وجود المفتاح ثم حذفتها
.
حسنا...
إقتباس : إنسى RecordCount ولاتستخدمها - فكر
يبقى لدينا:
1- استعمال RecNo بدلا عنها
، بشيء مثل:
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: هل سنقنعه بألا يفعل ذلك 
شكرا كثيرا لكم، بارك الله فيكم جميعا، وجزاك الله خيرا أستاذ.
المشاركات : 7
المواضيع 4
:
: 2
الإنتساب : Dec 2010
السلام عليكم ورحمة الله وبركاته
عندي برنامج مبيعات عملته يعمل على جهاز واحد وبعد ذلك تم التوسع على شبكة
المشكلة في حالة عمل عدة مستخدمين على جدول الفاتورة الاساسي والحفظ في نفس الوقت يحدث
تكرار في الرقم ID أو تظهر رسالة .........Row Cannot update
فما الحل الصحيح في التعامل مع برامج الشبكات
استخدم دلفي 7 وقاعدة بيانات SQL 2005 **** منكم الرد وجزاكم الله خيرا
المشاركات : 7
المواضيع 4
:
: 2
الإنتساب : Dec 2010
محمد نسمان كتب :هذا هوا الحل 
اذا كان برنامجك يعمل عليه مستخدم واحد فاسهل طريقة كما ذكر اخي محمد ان تعمل Max للحقل وتضيف عليه واحد
لكن سوف تظهر مشكلة في حال قيام مجموعة من المستخدمين بالعمل عليه في نفس الوقت، لذا يمكن استخدام الحل الذي ذكره اخي محمد المتعلق بال Triggers وانا استخدمه مع SQL Server وهناك حل اخر، عن طريق انشاء جدول جديد يحتوي على حقل يعمل كالعداد، وفي حال تخزين سجل جديد يتم اخذ القيمة من الحقل في هذا الجدول واضافة عليه واحد مثلاً وتخزين القيمة الجديدة، لكن يجب عليك ان تعمل Lock للجدول حتى لا ياخذ اكثر من مستخدم نفس الرقم (lock اقصده على الجدول في قاعدة البيانات وليس ضمن دلفي)، وذلك يعتمد على قاعدة البيانات المستخدمة.
اتمنى توضيح Triggers وكيفية استخدامه لاخد أكبر قيمة من جدول بحيث في حالة وجود عدة مستخدمين لايحصل تكرار كيف يتم عمل Lock للجدول بحيث لايمكن اكثر من مستخدم نفس الرقم
وشكرا
المشاركات : 95
المواضيع 16
:
: 0
الإنتساب : Jul 2009
السلام عليكم
إليك طريقتي التي أستعملها
أقوم بإنشاء جدول يقوم بحفظ آخر قيمة تم إضافتها و أسميه 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;
تحياتي
حتى وان كنت على الطريق الصحيح ان لم تتقدم سوف يدهسك من خلفك