توليد أرقام حسابات فريدة - مكالمة متكررة

StackOverflow https://stackoverflow.com/questions/98497

  •  01-07-2019
  •  | 
  •  

سؤال

مرحبًا، أحتاج إلى إنشاء أرقام حسابات فريدة مكونة من 9 أرقام.هذا هو الكود الزائف الخاص بي:

function generateAccNo()

    generate an account number between 100,000,000 and 999,999,999

    if the account number already exists in the DB 
        call generateAccNo()    /* recursive call */
    else
        return new accout number
    end if

end function

يبدو أن الوظيفة تعمل بشكل جيد، ولكنني أشعر بالقلق قليلاً بشأن المكالمة العودية.

هل سيؤدي هذا إلى حدوث أي تسرب للذاكرة (PHP 5 تحت Apache)؟

فهل هذه طريقة مقبولة لمعالجة هذه المشكلة؟

شكرا لمساهمتك.

هل كانت مفيدة؟

المحلول

أنت تدرك أن هذا قد يتسبب في تجاوز سعة المكدس، أليس كذلك؟كلما زاد عدد العملاء، تزداد احتمالية عدم العثور على رقم حساب مقبول.

وأيضًا، لماذا لا يمكنك عمل أرقام حسابات تسلسلية وزيادة رقم واحد فقط في كل مرة؟باستخدام هذا الأسلوب، عليك فقط قراءة الحد الأقصى للمعرف الموجود حاليًا في قاعدة البيانات وزيادته فقط.

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

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

نصائح أخرى

لا أعتقد حقًا أن الأمر يتعلق بالتكرار مقابل.الحلقات، كلاهما عرضة للمشاكل مع نمو مجموعة البيانات وإذا لم يتم تنفيذ إنشاء الأرقام العشوائية بشكل صحيح.تتبادر إلى ذهني فكرتان:

.GUID

إذا كان المعرف الفريد حقًا مطلوبًا بأقل جهد ممكن، ففكر في المعرف الفريد العمومي (GUID)، فمن المرجح أن تكون قاعدة البيانات الخاصة بك قادرة على تعيينه لك عند الإدراج، إذا لم تقم بإنشاء واحد في التعليمات البرمجية.إنه مضمون أن يكون فريدًا على الرغم من أنه ليس سهل الاستخدام للغاية.ومع ذلك، بالاشتراك مع AccountRecordId المتسلسل الذي تم إنشاؤه بواسطة قاعدة البيانات عند الإدراج، سيكون لديك مجموعة قوية

.المفتاح المركب:عشوائي + متسلسل

إحدى الطرق لتلبية جميع الاحتياجات، على الرغم من أنها تبدو ظاهريًا مبتذلة بعض الشيء، هي إنشاء رقم حساب مركب من مفتاح db متسلسل مكون من 5 أرقام (أو أكثر) ثم 5 أرقام أخرى عشوائية.إذا كان الرقم العشوائي مكررًا فلن يهم لأن المعرف التسلسلي سيضمن تفرد رقم الحساب بالكامل

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

function generateAccNo()

    generate an account number between 100,000,000 and 999,999,999

    while ( the account number already exists in the DB ) {
         generate new account number;
    }
    return new account number

end function

يعد الإنشاء والاختبار بشكل عشوائي أسلوبًا دون المستوى الأمثل لإنشاء أرقام حسابات فريدة، إذا كان هذا الرمز مخصصًا لأي شيء آخر غير لعبة.

يبدو الأمر جيدًا، لكنني أعتقد أنك بحاجة إلى نوع من حالة الموت، كم مرة ستترك هذا الأمر يعمل قبل أن تستسلم؟

أعلم أن هذا يبدو غير مرجح مع نطاق الأرقام الكبير، ولكن قد يحدث خطأ ما ويعيدك إلى المكالمة السابقة، والتي ستطلق على نفسها مرة أخرى اسم "ad-nauseum".

يعد إنشاء أرقام الحسابات بشكل تسلسلي خطرًا أمنيًا - يجب أن تجد خوارزمية أخرى للقيام بذلك.

وبدلاً من ذلك، يمكنك الاحتفاظ بجدول منفصل يحتوي على مخزن مؤقت لأرقام الحسابات التي تم إنشاؤها والمعروفة بأنها فريدة.يجب أن يحتوي هذا الجدول على معرف عدد صحيح متزايد تلقائيًا.عندما تريد رقم حساب، ما عليك سوى سحب السجل الذي يحتوي على أقل فهرس في المخزن المؤقت وإزالته من هذا الجدول.قم بإجراء بعض العمليات بانتظام والتي تعمل على تجديد المخزن المؤقت والتأكد من أنه يتمتع بالسعة >> الاستخدام العادي.وتتمثل الميزة في أن مقدار الوقت الذي يقضيه المستخدم النهائي في إنشاء رقم حساب سيكون ثابتًا بشكل أساسي.

يجب أن أشير أيضًا إلى أن مشكلة المعالجة العامة أو مخاطر التكرار أو التكرار هي الحتمية والعبء الزائد لاستعلامات قاعدة البيانات المتكررة.يعجبني حل TheZenker العشوائي + المتسلسل.مضمون لإنشاء معرف فريد دون إضافة تكاليف غير ضرورية.

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

يمكنك وضعها في حلقة while:

function generateAccNo()

    while (true) {    

      generate an account number between 100,000,000 and 999,999,999

      if the account number already exists in the DB 
          /* do nothing */
      else
          return new accout number
      end if
    }

end function

ولم لا:

lock_db
do
    account_num <= generate number
while account_num in db

put row with account_num in db

unlock_db

لماذا لا تتعامل قاعدة البيانات مع هذا؟في SQL Server، يمكنك فقط الحصول على عمود هوية يبدأ بـ 100000000.أو يمكنك استخدام sql في أي قاعدة بيانات لديك.فقط احصل على الحد الأقصى للمعرف بالإضافة إلى 1.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top