سرد، إرفاق، فصل قواعد بيانات على السيرفر برمجيا

This article is available in English too, check it out here.

المحتويات

محتويات هذا الموضوع:

  • المحتويات
  • نظرة خاطفة
  • مقدمة
  • السرد Enumerating
    • الجدول INFORMATION_SCHEMA.SCHEMATA
    • الجدول sys.sysdatabases
    • الجدول sys.databases
    • الإجراء sys.sp_databases
  • الإرفاق Attaching
    • الأمر CREATE DATABASE
    • الإجراء sys.sp_attach_db
    • الإجراء sys.sp_attach_single_file_db
  • الفصل Detaching
    • الأمر DROP DATABASE
    • الإجراء sys.sp_detach_db
  • التأمين Security
  • خاتمة

نظرة خاطفة

الدرس اليوم هو مشابه كثيرا لموسوعة لإجراءات وأوامر SQL Server. في هذا الدرس نتعرف على الأوامر والإجراءات التي يمكننا استخدامها برمجيا لعمل سرد Enumerating لقواعد البيانات الموجودة على السيرفر وكذلك لإرفاق Attach أو فصل Detach قاعدة بيانات من على السيرفر.

الدرس اليوم لا يتكلم عن كيفية استخدام الـ Management Studio أو أي أداة أو طريقة أخرى لها واجهة رسومية GUI، ولكنه يركز عن كيفية تطبيق هذه الأفكار برمجيا.

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

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

مقدمة

قد يسأل القارئ: لماذا قد أحتاج إلى معرفة كيفية سرد Enumerating، إرفاق Attach، أو حتى فصل Detach قواعد البيانات على السيرفر؟ هذا سؤال مهم والإجابة عنه تكون بسؤال أو أسئلة أخرى!

هل فكرت يوما بإنشاء برنامج لا يحتاج من العميل سوى الضغط على زر التنصيب Install؟ هل واجهتك مشاكل أثناء محاولة توزيع أو بيع برامجك عن طريق الإنترنت بسبب عملية التحضير أو التجهيز للبرنامج على جهاز العميل؟

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

فيمكننا مثلا من خلال ما سنتعلمه من أفكار في هذا الدرس أن نقوم بإنشاء برنامج يقوم بعمل الإرفاق Attach لقاعدة البيانات برمجيا أثناء عملية تنصيبه، ويقوم بفصلها Detach (عند الحاجة) أثناء عملية إزالته.

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

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

سيكون دأبنا في هذا الدرس هو شرح الفكرة (مثلا السرد Enumerating) ثم شرح الطرق التي بها يمكن تنفيذ هذه الفكرة. لاحظ أنه هناك طرق خاصة بنسخ SQL Server معينة.

بالطبع يمكن تطبيق الموجود في هذا الدرس على SQL Server Express أو أي نسخة أخرى (مثلا Developer، Enterprise، إلخ.)

السرد Enumerating

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

  • باستخدام الـ View الخاصة بالسيكويل المسماة INFORMATION_SCHEMA.SCHEMATA (خاصة بـ SQL Server 2000 فقط.)
  • باستخدام الجدول الخاص بالسيكويل المسمى sys.sysdatabases (خاص بـ SQL Server 2000 فقط.)
  • باستخدام الـ View الخاصة بالسكويل المسماة sys.databases (خاصة بـ SQL Server 2005 والإصدارات الأعلى.)
  • باستخدام الإجراء Stored Procedure الخاص بالسيكويل المسمى sys.sp_databases (يمكن تطبيقه في جميع النسخ.)

الجدول INFORMATION_SCHEMA.SCHEMATA

إذا كنت تستخدم الإصدار 2000 من الـ SQL Server فيمكنك الحصول على البيانات المطلوبة والتي هي قواعد البيانات المسجلة على السيرفر باستخدام الـ View المسمى INFORMATION_SCHEMA.SCHEMATA والذي تتعامل معه كما تتعامل مع أي جدول آخر ولكن الفرق أن هذا الـ View فليس مرتبط بقاعدة بعينها.

الجدول INFORMATION_SCHEMA.SCHEMATA له التركيب التالي:

شكل 1 - تركيب جدول INFORMATION_SCHEMA.SCHEMATA

شكل 1 - تركيب جدول INFORMATION_SCHEMA.SCHEMATA

لا تقلق حيال هذا الجدول أو الموجود فيه فإننا لا يهمنا من هذا الجدول (بالنسبة لموضوعنا اليوم) غير العمود CATALOG_NAME والذي يحوي اسم قاعدة البيانات.

الكود التالي يوضح كيفية الحصول على أسماء قواعد البيانات الموجودة على السيرفر (لاحظ أن الكود يعمل فقط على نسخة SQL Server 2000.)

    // C# Code
    SqlConnection conn = new SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI");
    SqlCommand cmd = new SqlCommand("", conn);
    SqlDataReader rdr;
    cmd.CommandText = "SELECT DISTINCT    CATALOG_NAME    FROM    INFORMATION_SCHEMA.SCHEMATA";
    conn.Open();
    rdr = cmd.ExecuteReader();
    while (rdr.Read())
    {
        Console.WriteLine(rdr.GetString(0));
    }
    rdr.Dispose();
    cmd.Dispose();
    conn.Dispose();
    ' VB.NET
    Dim conn As New SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI")
    Dim cmd As New SqlCommand("", conn)
    Dim rdr As SqlDataReader
    cmd.CommandText = "SELECT DISTINCT    CATALOG_NAME    FROM    INFORMATION_SCHEMA.SCHEMATA"
    conn.Open()
    rdr = cmd.ExecuteReader()
    While (rdr.Read())
        Console.WriteLine(rdr.GetString(0))
    End While
    rdr.Dispose()
    cmd.Dispose()
    conn.Dispose()

الجدول sys.sysdatabases

الطريقة الثانية وهي باستخدام الجدول المسمى sys.sysdatabases الموجود في SQL Server 2000 كجدول. أما في SQL Server 2005 فتم تطبيقه كـ View وهذا لمراعاة التوافقية Compatibility وعدم توقف البرامج التي تعمل بالنظام القديم للنسخة 2000. ويحتمل -بل ومن الأكيد- أنه سيتم إزالة هذا الجدول في الإصدارات المقبلة من SQL Server ولهذا فإنه يفضل ألا تعتمد عليه أبدا إلا إذا كنت متأكد من أن إصدار SQL Server هو 2000 أو 2005.

التركيب الخاص بهذا الجدول هو كالتالي:

شكل 2 - تركيب جدول sys.sysdatabases

شكل 2 - تركيب جدول sys.sysdatabases

مثل الجدول السابق في الطريقة الأولى، يهمنا فقط في درسنا هذا اسم القاعدة وهي الموجودة في العمود name. هناك أيضا العمود filename والذي يحوي اسم ملف القاعدة.

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

    // C# Code
    cmd.CommandText = "SELECT [name]    FROM    sys.sysdatabases";
    ' VB.NET Code
    cmd.CommandText = "SELECT [name]    FROM    sys.sysdatabases"

الجدول sys.databases

وهذه هي الطريقة الثالثة وهي خاصة بالنسخة 2005 والإصدارات الأحدث منها. وهذه الـ View هي كبيرة جدا بها العشرات من الأعمدة تحوي كل جميع التفاصيل لجميع قواعد البيانات. ونظرا لطولها لن نذكر تركيبها وسنكتفي بذكر العمود name فقط والذي يحوي اسم القاعدة.

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

    // C# Code
    cmd.CommandText = "SELECT [name]    FROM    sys. databases";
    ' VB.NET Code
    cmd.CommandText = "SELECT [name]    FROM    sys. databases"

الإجراء sys.sp_databases

الطريقة الأخيرة وهي باستخدام الإجراء sys.sp_databases وهو أيضا خاص بالسيكويل سيرفر ولكنه لحسن الحظ موجود في جميع النسخ. هذا الإجراء لا يأخذ أي مدخلات ولكنه يقوم بإرجاع جدول بسيط يتكون من ثلاثة أعمدة فقط:

  • DATABASE_NAME:
    اسم قاعدة البيانات.
  • DATABASE_SIZE:
    حجم قاعدة البيانات بالكيلو بايت.
  • REMARKS:
    خاصة بالـ SQL Server نفسه. دائما لها القيمة لا شيئ NULL.

الكود الذي يوضح كيفية الحصول على أسماء قواعد البيانات الموجودة على السيرفر هو نفس الكود الأول تماما ولكن مع تغيير في الأمر:

    // C# Code
    cmd.CommandText = "exec sys.sp_databases";
    ' VB.NET Code
    cmd.CommandText = "exec sys.sp_databases"

الإرفاق Attaching

بنفس الطريقة التي اتبعناها في القسم السابق، نتبعها في هذا القسم وهو كيفية إرفاق Attach قاعدة بيانات على السيرفر. فسوف نبدأ بشرح الأفكار أو الطرق التي تؤدي بنا إلى تنفيذ هذه العملية وهي كالتالي:

  • باستخدام الأمر CREATE DATABASE
  • باستخدام الإجراء sys.sp_attach_db
  • باستخدام الإجراء sys.sp_attach_single_file_db

الأمر CREATE DATABASE

الطريقة الأولى لعمل إرفاق Attach لقاعدة بيانات على السيرفر وهي باستخدام الأمر CREATE STATEMENT والذي يستخدم لإنشاء قاعدة بيانات على السيرفر وكذلك لعمل إرفاق لقاعدة موجودة مسبقا.

وهذا الأمر له التركيب التالي (حالة الإرفاق):

CREATE DATABASE database_name
    ON <filespec> [ ,...n ]
    FOR ATTACH [;]

الخانة database_name تأخذ اسم قاعدة البيانات -وليس اسم الملف- الذي يظهر على السيرفر ويستخدم من خلال الكود (يجب أن يكون هذا الاسم مميزا أي أنه ليس موجودا على السيرفر وإلا ستفشل العملية.) بينما الخانة تأخذ اسم الملف الخاص بالقاعدة وكذلك اسم ملف السجل Log الخاص بها. نلاحظ أن أسماء هذه الملفات يتم ذكرها بطريقة خاصة سنتعرف عليها في خلال لحظات.

الكود التالي يقوم بإرفاق قاعدة البيانات database.mdf باسم MyDatabase على السيرفر.

    // C# Code
    SqlConnection conn = new SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI");
    SqlCommand cmd = new SqlCommand("", conn);
    cmd.CommandText =
        "CREATE DATABASE 'MyDatabase' ON " +
        "PRIMARY ( FILENAME =  'database.mdf' ) " +
        "FOR ATTACH";
    conn.Open();
    cmd.ExecuteNonQuery();
    cmd.Dispose();
    conn.Dispose();
    ' VB.NET Code
    Dim conn As New SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI")
    Dim cmd As New SqlCommand("", conn)
    cmd.CommandText = "CREATE DATABASE 'MyDatabase' ON " & _
        "PRIMARY ( FILENAME =  'database.mdf' ) " & _
        "FOR ATTACH"
    conn.Open()
    cmd.ExecuteNonQuery()
    cmd.Dispose()
    conn.Dispose()

نلاحظ في هذا الكود أنه يجب إما تحديد العنوان Address الكامل لقاعدة البيانات (مثلا C:\Users\…..\database.mdf) أو تحديد العنوان القريب من المجلد الحالي (الذي يحوي البرنامج في الغالب.)

نلاحظ أيضا أنه إن لم يتم تحديد ملف السجل Log وهو هذا الملف ذا الامتداد LDF، سوف يقوم SQL Server بإنشاء ملف جديد تلقائيا.

هذه الطريقة في تعريف أسماء الملفات تسمى FileGroups وهي مشهورة في SQL Server. يمكنك استخدام الـ MSDN في البحث عنها.

ومع تغيير في الأمر في الكود السابق، يمكننا إرفاق نفس قاعدة البيانات ولكن مع إرفاق الملف LDF الخاص بها.

    // C# Code
    cmd.CommandText = "CREATE DATABASE 'MyDatabase' ON " +
        "PRIMARY ( FILENAME =  'database.mdf' ), " +
        "FILEGROUP MyDatabase_Log ( FILENAME = 'database.ldf')" +
        "FOR ATTACH";
    ' VB.NET Code
    cmd.CommandText = "CREATE DATABASE 'MyDatabase' ON " & _
        "PRIMARY ( FILENAME =  'database.mdf' ), " & _
        "FILEGROUP MyDatabase_Log ( FILENAME = 'database.ldf')" & _
        "FOR ATTACH"

الإجراء sys.sp_attach_db

الطريقة الثانية لعمل إرفاق Attach لقاعدة البيانات هي باستخدام الإجراء المسمى sys.sp_attach_db. الكود التالي يوضح التركيب الخاص بهذا الإجراء:

sp_attach_db [ @dbname= ] 'dbname'    , [ @filename1= ] 'filename_n' [ ,...16 ]

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

مع تغيير في الكود السابق نستطيع أن نقوم بتنفيذ عملية الإرفاق باستخدام الأمر التالي:

    // C# Code
    cmd.CommandText = "exec sys.sp_attach_db    MyDatabase,    'database.mdf'";
    ' VB.NET Code
    cmd.CommandText = "exec sys.sp_attach_db    MyDatabase,    'database.mdf'"

الإجراء sys.sp_attach_single_file_db

الطريقة الأخيرة معنا في طرق الإرفاق Attaching لقواعد البيانات على السيرفر هي باستخدام الإجراء sys.sp_attach_single_file_db وهو مشابه كثيرا (إن لم يكن مماثلا) للإجراء السابق.

مع التغيير أيضا في أي من الأكواد السابقة نستطيع تنفيذ عملية الإرفاق باستخدام الأمر التالي:

    // C# Code
    cmd.CommandText = "exec sys.sp_attach_single_file_db    MyDatabase,    'database.mdf'";
    ' VB.NET Code
    cmd.CommandText = "exec sys.sp_attach_single_file_db    MyDatabase,    'database.mdf'"

الفصل Detaching

كما تعودنا في القسمين الآخرين من ذكر الطرق المؤدية إلى تنفيذ الأمر أولا، نطبق هذا الأمر في القسم الأخير وهو عملية الفصل Detach أي فصل قاعدة بيانات مرفقة من على السيرفر أي إزالتها بدون حذف ملفها. ويتم ذلك بواحدة من طريقتين متوفرتين في جميع إصدارات SQL Server وهما:

  • أمر DROP_DATABASE
  • إجراء sys.sp_detach_db

الأمر DROP DATABASE

الطريقة الأولى التي نستطيع من خلالها فصل قاعدة بيانات من على السيرفر وهي باستخدام أمر T-SQL المسمى DROP DATABASE. فمصطلح Drop في قاموس SQL Server يرمز إلى عملية الإزالة لأي تكوين من مكونات القاعدة مثلا جدول، إجراء، أو نحوها. وهذا الأمر له التعريف التالي:

DROP DATABASE database_name [ ,...n ] [;]

الكود التالي يقوم بفصل قاعدة البيانات المجودة على السيرفر باسم MyDatabase.

    // C# Code
    SqlConnection conn = new SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI");
    SqlCommand cmd = new SqlCommand("", conn);
    cmd.CommandText = "DROP DATABASE MyDatabase";
    conn.Open();
    cmd.ExecuteNonQuery();
    cmd.Dispose();
    conn.Dispose();
    ' VB.NET Code
    Dim conn As New SqlConnection("Server=(local);Data Source=;Integrated Security=SSPI")
    Dim cmd As New SqlCommand("", conn)
    cmd.CommandText = "DROP DATABASE MyDatabase"
    conn.Open()
    cmd.ExecuteNonQuery()
    cmd.Dispose()
    conn.Dispose()

الإجراء sys.sp_detach_db

الطريقة الثانية والأخيرة في كيفية فصل Detach قاعدة بيانات من على السيرفر هي باستخدام الإجراء sys.sp_detach_db وهو مشابه كثيرا (إن لم يكن مماثلا) لسابقه وهو له التعريف التالي:

sp_detach_db [ @dbname= ] 'database_name' [;]

مثلما تعودنا من اختصار الأكواد للإيضاح والبساطة، بتغيير الأمر في الكود السابق نستطيع فصل قاعدة البيانات MyDatabase من على السيرفر

    // C# Code
    cmd.CommandText = "sys.sp_detach_db MyDatabase";
    ' VB.NET Code
    cmd.CommandText = "sys.sp_detach_db MyDatabase"

التأمين Security

يجب مراعاة أنه يجب للمستخدم أن يكون له صلاحيات الإرفاق وفك الإرفاق على السيرفر لكي يتمكن من تنفيذ الأوامر. قم بالرجوع إلى MSDN لمزيد من التفاصيل بالنسبة لاعتبارات التأمين Security Considerations بالنسبة لكل أمر وكل إجراء تعرضنا له.

خاتمة

تعرفنا في هذا الدرس على الكثير من الأوامر والإجراءات، وفي دروس أخرى بإذن الله تعالى سنتعرف على الكثير وسنبحث عن الكثير في SQL Server و ADO.NET.

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

اخترنا لك:

أحدث المواضيع:

هل أعجبتك؟ شارك بها...
  • نادر أسامة سليمان

    شكر الله لك المجهود الرائع للترجمة العربية. أنا محترف SQL لكثير من الأعوام التي لا أتذكرها :) ولكن أكثر ماجذبني هو القدرة المتميزة للترجمة للعربية. فقد أستفدت كثيراً من هذه الترجمة وأعتقد اننا بحاجة لكثير من المحتوي العربي حتى تنشأ لدنيا مجموعة من المصطلحات المتعارف عليها

    • شكرا جزيلا لك أخي شكرا لمشاركتك معنا.

      أنا أعمل الآن على ترجمة مقالاتي الإنجليزية كي يستطيع العرب الاستفادة أيضا منها.

      :)

  • نادر أسامة سليمان

    شكر الله لك المجهود الرائع للترجمة العربية. أنا محترف SQL لكثير من الأعوام التي لا أتذكرها :) ولكن أكثر ماجذبني هو القدرة المتميزة للترجمة للعربية. فقد أستفدت كثيراً من هذه الترجمة وأعتقد اننا بحاجة لكثير من المحتوي العربي حتى تنشأ لدنيا مجموعة من المصطلحات المتعارف عليها

    • شكرا جزيلا لك أخي شكرا لمشاركتك معنا.

      أنا أعمل الآن على ترجمة مقالاتي الإنجليزية كي يستطيع العرب الاستفادة أيضا منها.

      :)

  • عنييد

    والله مبدع
    لكن كنت اتمنى ن الكود يعمل على نسخة اعلى من نسخة SQL Server 2000

    • هو فعلا بيعمل على إصدارات أعلى من 2000
      جميع الكود يعمل على جميع الإصدارات عدا الطرقتين الأولى والثانية في موضوع السرد Enumeration ففيها بعض التفصيل

  • عنييد

    والله مبدع
    لكن كنت اتمنى ن الكود يعمل على نسخة اعلى من نسخة SQL Server 2000

    • هو فعلا بيعمل على إصدارات أعلى من 2000
      جميع الكود يعمل على جميع الإصدارات عدا الطرقتين الأولى والثانية في موضوع السرد Enumeration ففيها بعض التفصيل

  • Pingback: Programmatically Enumerating, Attaching, and Detaching SQL Server Databases | Just Like a Magic()