الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيف الحصول على أخر رقم ID من SQLDB

مغلق
بدأه الشهاب الحارق في 8 مارس 2005 · 10 رد · 12,955 مشاهدة · في أرشيف قسم SQL Server
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

لدي مشكلة وهي : أولاً انني لا أقوم بجلب البيانات عند حدث التحميل load event

و لنعتبر أن هنالك عدد من الصفوف في قاعدة البيانا

الان السيناريوا هو عندما أقوم بإضافة صف جديد new row وبعد تعبئته بالبيانات

أضغط على زر التحديث فيظهر الـ ID يساوي واحد وعند الضغط على الزر next يذهب إلى الصف نفسه ولكن بالرقم الحقيقي

للــ ID من قاعدة البيانات وهنا تكمن المشكلة وإن كانت بشكل مؤقت حتى يخرج المستخدم من النموذج

والسبب أنني لا أستطيع أن أضيف شيء حتى أذهب للصف الثاني , طيب مافائدة الصف الأول الوهمي ؟؟؟

وبعد البحث عن هذه المشكلة تبين لي أنني لابد أن أسترجع أخر رقم للـ ID من قاعدة البيانات بعد عملية الـ Insert .

حاولت والنتيجة كانت لا حل حتى الآن .

الطلب: كيف أستطيع أن أحصل على أخر رقم تلقائي من قاعدة البيانات SQL DataBase

HOW TO: Retrieve the Identity Value While Inserting Records

بحث في الإنترنت كثيراً وعرفت من خلال ذلك أن الـ SQL DataAdapter يقوم بهذا بشكل تلقائي

بحيث يشترط عن طريق الـ Where بأن يكون الـ ID يساوي @@IDENTITY

لكن مع ذلك المشكلة مستمرة معي , وكذلك كتبت النصوص البرمحية التالية

 Private Sub DAMain_RowUpdated(ByVal sender As Object, ByVal e As System.Data.SqlClient.SqlRowUpdatedEventArgs) Handles DAMain.RowUpdated
        Try
            If e.Status = UpdateStatus.Continue AndAlso e.StatementType = StatementType.Insert Then
                'Get NewID
                Dim cmdGetIdentity As New SqlCommand("SELECT @@IDENTITY", CnnMain)
                cmdGetIdentity.CommandType = CommandType.Text
                e.Row("SerialNumber") = Int32.Parse(cmdGetIdentity.ExecuteScalar().ToString())
                e.Row.AcceptChanges()
                MsgBox(e.Row("SerialNumber"))
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

لكن دون جدوى والله المستعان فكيف الحل أحسن الله إليكم ؟

في المثال يتضح المقال

#2

لاسترجاع قيمة آخر حقل للحقل التلقائي في الجدول الموجود على SQLServer بالطبع ستكون هي أكبر قيمة ، استخدم الكود التلي:

Dim AoutNo as int36
Dim Str As String = "SELECT MAX(AoutNo) FROM tabel1 "
                Dim cmd As New OleDb.OleDbCommand(Str, OleDbConnection1)
OleDbConnection1.Open()
 AoutNo = cmd.ExecuteScalar
 OleDbConnection1.Close()

أتمنى أن تستفيد مما سبق

تم تعديل هذه المشاركة بواسطة seahmad في 8 مارس 2005 في 22:29

فلسطين الزاهية بألوان الحب والسلام

ذلك الطعم الزيتوني الذي يتدفق عسلاً من أفواه بساتينها وحدائقها

تشتاق إليها نفوس المتقين وترنوا للسجود فيها جباه المسلمين

#3
seahmad كتب:
لاسترجاع قيمة آخر حقل للحقل التلقائي في الجدول الموجود على SQLServer بالطبع ستكون هي أكبر قيمة ، استخدم الكود التلي:

Dim AoutNo as int36
Dim Str As String = "SELECT MAX(AoutNo) FROM tabel1 "
                Dim cmd As New OleDb.OleDbCommand(Str, OleDbConnection1)
OleDbConnection1.Open()
 AoutNo = cmd.ExecuteScalar
 OleDbConnection1.Close()

أتمنى أن تستفيد مما سبق

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

جرب استخدام هذه الأمر

SELECT @@IDENTITY AS 'Identity'
#4
public static int add_temp_site(MainSite s)
  {
 	 int site_id = 0;
 	 SqlConnection conn = new SqlConnection(globals.conn_string);
 	 SqlCommand cmd = new SqlCommand();

 	 // init connection
 	 cmd.Connection = conn;

 	 // set procedure's name
 	 cmd.CommandText = "dbo.sp_add_temp_site";

 	 // site name
 	 cmd.Parameters.Add("@site_name", s.site_name);

 	 // site url
 	 cmd.Parameters.Add("@site_url", s.site_url);

 	 // site description
 	 cmd.Parameters.Add("@site_desc", s.site_desc);

 	 cmd.CommandType = CommandType.StoredProcedure;

 	 try
 	 {
    conn.Open();
    SqlDataReader r = cmd.ExecuteReader();
    while (r.Read())
    {
   	 // الرقم التسلسلي للموقع
   	 site_id = Convert.ToInt32(r["v_site_id"]);
    }
    r.Close();
 	 }
 	 catch
 	 {
 	 }
 	 finally
 	 {
    conn.Close();
    conn.Dispose();
    cmd.Dispose();
 	 }
 	 return site_id;
  }

الإجرائية sp_add_temp_site مكتوبة كما يلي:

insert ...............................................................

// important HERE HERE HERE
select v_site_id = SCOP_IDENTITY()

العبارة الأخير هي التي تعيد الرقم التسلسلي للسجل الذي أضفته, بمكن استخدامه بهذه الطريقة أو عن طريقة كتابة sql منفصلة ضمن برنامجك...

#5
اقتباس
أو عن طريقة كتابة sql منفصلة ضمن برنامجك...

يمكن ايضا باستعمال الدالة

 @ident_current(TableName)

حيث TableName اسم الجدول الذينريد استرجاع آخر قيمة identity منه، بشرط أن يحتوي على حقل identity .

مثال: إجراء مخزن يقوم بإضافة سجل جديد واسترجاع رقمه مباشرة:

create procedure sp_InsertNewCustomer
@CustName varchar(70), -- until the end of the parameters list
as
insert into tblCustomers values(@CustName, .................
)

select @ident_current("tblCustomers")  as CustAutoNo 
go

ولتنفيذ هذا الإجراء:

SqlConnection conn = new SqlConnection(strCn);
  SqlCommand cmd = new SqlCommand();
SQL="exec sp_InsertNewCustomer " 
sql+= ' put the parameters list values here

try
 cn.open()
 dim dtr as new SqlDataReader()
 dtr=cmd.ExecuteReader(SQL)
 do while dtr.Read()
     iCustNo=dtr("CustAutoNo")
 loop

 me.txtCustNo.text=iCustNo.ToString()
catch ex as Exception()
  msgbox ex.message
finally
  dtr.close()
  cmd.close()
  cn.close()
end try

بالتوفيق بإذن الله.

تم تعديل هذه المشاركة بواسطة walcom في 9 مارس 2005 في 12:35

فكر بطريقة أخرى

#6

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

تعليق بسيط على خطأ إملائي في كود أخونا الحبيب وليد

هو يقصد هذه الدالة IDENT_CURRENT

وليس في بدايتها علامة @

ولا أعلم أن هناك دوال في بدايتها علامة @ واحدة بل اثنتين ، وإلا ستكون متغير

أم الدالة المقصودة هنا فهي بدون علامات أصلاً IDENT_CURRENT

وطبعاً وليد أستاذنا وجل من لا يسهو :)

وأخي الكريم إسماعيل

الدالة SCOP_IDENTITY تعيد آخر IDENTITY على مستوى قاعدة البيانات كلها ، أي في أي جدول أياً كان وليس في الجدول الحالي ، فهل هذا ما قصدته ؟

والله الموفق

تم تعديل هذه المشاركة بواسطة محمد النحراوي في 9 مارس 2005 في 22:38

#7

آسف على الخطأ، وهذا هو السطر الصحيح:

ident_current(TableName)

ليكون الإجراء المخزن كالتالي:

create procedure sp_InsertNewCustomer
@CustName varchar(70), -- until the end of the parameters list
as
insert into tblCustomers values(@CustName, .................
)

declare @CustAutoNo int
select @CustAutoNo= ident_current("tblCustomers")   as CustAutoNumber

go

لم يكن الكود أمامي لحظتها ، كتتبه مما استطعت تذكره، ولم أجربه.

الدالة ident_current ترجع آخر identity number في الجدول، وجعلتها في procedure وتنفذ عقب جملة الإدخال مباشرة لضمان عدم إدخال سجل آخر قبل إرجاع الidentity الخاص بالسجل الذي أدخل قبله.

ويمكن استعمال المتغير @CustAutoNo في أي جملة SQL تلي جملة إسناد القيمة إليه

-------------------------------

نقلت الموضوع لقسم SQL Server.

تم تعديل هذه المشاركة بواسطة walcom في 16 أغسطس 2005 في 19:07

فكر بطريقة أخرى

#8

أخي العزيز محمد التابع SCOP_IDENTITY يعيد آخر IDENTITY تم إدراجه ضمن نفس المجال أي عند استخدام إجرائية مخزنة سيتم إعادة آخر رقم لآخر جدول تمت عملية إضافة سجل جديد أي أن هذا التابع يعمل ضمن مجال محدد أي ضمن تابع أو إجرائية أو trigger.....

أما ident_current فيعيد آخر رقم للجدول ضمن أي مجال وأي جلسة أي أنه إذا كلن هناك مستخدم آخر يقوم بعملية إضافة سجل جديد فإن هذه الدالة ستعيد نتائج غير متوقعة...

#9

السلام عليكم

أخي إسماعيل أنت تقول :

اقتباس
أما ident_current فيعيد آخر رقم للجدول ضمن أي مجال وأي جلسة أي أنه إذا كلن هناك مستخدم آخر يقوم بعملية إضافة سجل جديد فإن هذه الدالة ستعيد نتائج غير متوقعة...

هذه أصلاً هي مزية استخدام ident_current وليست العيب الذي به

وأوضح لك

مثلاً عندنا 50 مستخدم يعملون في نفس الداتابيس ، منهم 5 حاليا يقومون بالإدخال في نفس الجدول ، فإذا كنت أنت المستخدم رقم 4 وتدخل بياناتك ثم دخل المستخدم رقم 5 وأدخل بياناته قبلك وحفظها ، فأنت هنا وباستخدام هذه الدالة (وهذه مزيتها) تحصل على آخر رقم identity مدخل وهكذا لن تتأثر عملية الإدخال لأنها لا تعتمد على المستخدم الحالي بل تعتمد على كافة العمليات على مستوى الداتابيس ، ولكن للجدول المحدد ..

والآن نوضح ما هي وظيفة الدالة SCOPE_IDENTITY ، لاحظ أنها لا تحمل أية بارمترات فلا يتم تمرير اسم جدول ولا أي شيء ، فماذا يعني هذا ؟

يعني أنك لو قمت بعمل إدخال لجدول العملاء وكان آخرidentity هو 10 ثم انتقلت لجدول الموردين لتدخل بيانات وكان عدد الموردين في الجدول هو 15 فإذا استخدمت SCOPE_IDENTITY هل تعلم ماذا سترجع لنا ؟ ستعيد لنا آخر identity على مستوى قاعدة البيانات أي ستعيد 10 وهو آخر ما تم التعامل معه في جدول العملاء وهنا طبعاً ستحدث مشكلة

أما إذا أردنا أن نرجع آخر identity على مستواك أنت فقط ومستوى الجدول الحالي (أو العملية الحالية) نستخدم الدالة @@IDENTITY

والله تعالى أعلم

تم تعديل هذه المشاركة بواسطة محمد النحراوي في 10 مارس 2005 في 20:55

#10

السلام عليكم

أخواني أحسن اللهُ إليكم

بصراحة ماتوقعت هذه الردود شاكرلكم تعاونكم الّا منقطع

يا أخوان أنا رقم الأخير للـ ID تمكنت من الحصول عليه بهذا الشكل كما ذكرت سابقاً

    Private Sub DAMain_RowUpdated(ByVal sender As Object, ByVal e As System.Data.SqlClient.SqlRowUpdatedEventArgs) Handles DAMain.RowUpdated
        Try
            If e.Status = UpdateStatus.Continue AndAlso e.StatementType = StatementType.Insert Then
                'Get NewID
                Dim cmdGetIdentity As New SqlCommand("SELECT @@IDENTITY", CnnMain)
                cmdGetIdentity.CommandType = CommandType.Text
                e.Row("SerialNumber") = Int32.Parse(cmdGetIdentity.ExecuteScalar().ToString())
                e.Row.AcceptChanges()
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

الان مشكلتي هي عملية الـ duplicate Row عندما أقوم بالتحديث وهذا يحدث مع الـ dataView

والسبب كما ذكرت أنفاً أنه الـ dataset لا يتم تعبأتها عند تحميل النموذج إذا وجدت الحل سأخبركم (الموضوع معقد نوعاً ما )

السلام عليكم

في المثال يتضح المقال

#11

السلام عليكم أخي الكريم ،

هل وجدت الحل لمشكلتك لأني أصادف نفس المشكلة الآن وهو عند تخزين السجل الجديد يظهر سجل آخر برقم ID آخر مع العلم أن الID يعتبر Identity أي ترقيم تلقائي في قاعدة بيانات SQlServer

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

تم تعديل هذه المشاركة بواسطة ندى الصباح في 26 يوليو 2005 في 17:53

هذا الموضوع مغلق.

مواضيع مشابهة