استخدام المؤشرات والحلقات في Transact-SQL. المؤشرات في MySQL الإجراءات المخزنة المؤشرات في خادم SQL

يسمح لك الأمر DECLARE CURSOR باسترداد السجلات من صف جدول تلو الآخر للمعالجة. يسمح هذا بمعالجة صف تلو الآخر بدلاً من معالجة مجموعة البيانات التقليدية التي تقوم بها SQL.

كتقريب أولي، يتم استخدام الخطوات التالية عند العمل باستخدام المؤشر.

يتم إنشاء المؤشر باستخدام الأمر DECLARE. يتم فتح المؤشر باستخدام الأمر OPEN.

يتم تنفيذ العمليات باستخدام المؤشر باستخدام أمر FETCH. يتم إغلاق المؤشر باستخدام الأمر CLOSE.

يحدد الأمر DECLARE CURSOR عبارة SELECT. يمكن استرداد كل صف تم إرجاعه بواسطة عبارة SELECT ومعالجته بشكل فردي. يوضح مثال Oracle التالي وجود مؤشر في كتلة الإعلان بالإضافة إلى العديد من المتغيرات الأخرى. بعد ذلك، في كتلة BEGIN...END اللاحقة، يتم فتح المؤشر، ويتم التحديد منه، ويتم إغلاق المؤشر.

CURSOR title_price_cursor هو عنوان محدد، السعر من العناوين

عندما لا يكون السعر فارغًا؛ title_price_val title_price_cursor ROWTYPE؛ new_price NUMBER(10.2);

فتح title_price_Cursor;

جلب title_price_cur-sor إلى title_price_val؛

new_price:= "title_price_val.price" * 1.25 أدخل في قيم new_title_price

(title_price_val.title، new_price) إغلاق title_price_cursor؛ نهاية؛

نظرًا لأن هذا المثال يستخدم PL/SQL، فلن نشرح الكثير من التعليمات البرمجية في هذا الكتاب. ومع ذلك، تعرض كتلة DECLARE بوضوح تعريف المؤشر. في كتلة PL/SQL القابلة للتنفيذ، تتم تهيئة المؤشر باستخدام أمر OPEN، ويتم استرداد القيم باستخدام أمر FETCH، وأخيرًا يتم إغلاق المؤشر باستخدام أمر CLOSE.

عبارة SELECT هي أساس المؤشر، لذلك من الجيد اختبارها بالكامل قبل تضمينها في عبارة DECLARE CURSOR. يمكن أن تعمل عبارة SELECT على الجدول أو العرض الأساسي. ولذلك، يمكن أن تعمل مؤشرات القراءة فقط مع طرق العرض غير القابلة للتحديث. يمكن أن تحتوي عبارة SELECT على عبارات مثل ORDER BY وGROUP BY وHAVING طالما أن هذه العبارات لا تقوم بتحديث الجدول المصدر. إذا تم تعريف المؤشر على أنه للتحديث، فمن المستحسن إزالة هذه الجمل من عبارة SELECT.

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

في مثال DB2 البسيط التالي، سوف نعلن عن مؤشر يبحث عن أرقام الأقسام، وأسماء الأقسام، وأرقام المديرين في admin_group "XO1".

أعلن dept_cursor CURSOR

لـ SELECT dept_nbr، dept_name، mgr_nbr

أين admin_group = "X01"

ORDER BY d"ept_name ASC, dept_nbr DESC, mgr_nbr DESC;

يقوم مثال Microsoft SQL Server التالي بتعريف المؤشر الخاص بجدول الناشرين وفتحه. يحدد المؤشر السجل الأول الذي يطابق عبارة SELECT من جدول الناشرين ويدرجه في جدول آخر. ثم ينتقل بعد ذلك إلى السجل التالي، ثم التالي، حتى تتم معالجة كافة السجلات. وأخيراً، يتم إغلاق المؤشر وتحرير الذاكرة (يتم استخدام الأمر DEALLOCATE فقط في Microsoft SQL Server).

أعلن @publisher_name VARCHAR(20)

قم بإعلان مؤشر pub_cursor لاختيار اسم pub_name من الناشرين في أي بلد "الولايات المتحدة الأمريكية"

جلب التالي من pub_cursor إلى Publisher_name

بينما @s>FETCH_STATUS=0

أدخل في قيم الناشرين الأجانب("j>اسم_الناشر)

إغلاق pub_cursor DEALLOCATE pub_cursor

في هذا المثال، يمكنك رؤية المؤشر يتحرك عبر مجموعة من السجلات. (هذا المثال يهدف فقط إلى توضيح الفكرة، حيث أن الواقع موجود أفضل طريقةالحل لهذه المشكلة، وهي تعليمات INSERT، SELECT.)

ينطبق على:قاعدة SQL Server (منذ 2008). بيانات SQLمستودع بيانات Azure SQL، مستودع البيانات المتوازية

يحدد سمات مؤشر خادم Transact-SQL، مثل خصائص العرض والاستعلام المستخدم لإنشاء مجموعة النتائج التي يعمل عليها المؤشر. تدعم عبارة DECLARE CURSOR بناء الجملة القياسي ISO وبناء الجملة الذي يستخدم مجموعة ملحقات لغة Transact-SQL.

بناء الجملة ISO أعلن cursor_name [ غير حساس ] [ SCROLL ] المؤشر لـ Select_statement [ FOR ( للقراءة فقط | تحديث [ OF column_name [ ,...n ] ] ) ] [;] بناء جملة SQL للعمليات الموسعة قم بتعريف cursor_name CURSOR [محلي | عالمي ] [ FORWARD_ONLY | التمرير ] [ ثابت | مجموعة المفاتيح | ديناميكي | FAST_FORWARD ] [للقراءة_فقط | SCROLL_LOCKS | متفائل ] [ TYPE_WARNING ] لبيان_select_statement [ للتحديث [ OF column_name [ ,...n ] ] ] [;]

cursor_name
cursor_name

غير حساس
tempdb; وبالتالي، لا تنعكس التغييرات التي يتم إجراؤها على الجداول الأساسية في البيانات التي يتم إرجاعها بواسطة تحديدات هذا المؤشر، ولا يكون هذا المؤشر قابلاً للتغيير. عند استخدام بناء جملة ISO، ما لم يتم تحديد خيار INSENSITIVE، تظهر التحديثات وعمليات الحذف التي تم إجراؤها على الجداول الأساسية في التحديدات اللاحقة.

انتقل
يشير إلى أن جميع خيارات أخذ العينات متاحة (الأول، الأخير، السابق، التالي، النسبي، المطلق). إذا لم تحدد عبارة ISO DECLARE CURSOR خيار SCROLL، فسيتم دعم خيار الجلب التالي فقط. لا يمكن تحديد خيار SCROLL باستخدام خيار FAST_FORWARD.

Select_statement
عبارة SELECT قياسية تحدد مجموعة نتائج المؤشر. لا يُسمح بالكلمات الرئيسية FOR BROWSE وINTO في Select_statementإعلان المؤشر.

Select_statementيتعارض مع مؤشر من النوع المطلوب.

يقرأ فقط

تحديث ]
اسم العمود [, .. ] تم تحديده، الأعمدة المدرجة فقط هي التي تسمح بالتغييرات. إذا تم استخدام عبارة UPDATE بدون قائمة الأعمدة، فمن الممكن التحديث لجميع الأعمدة.

cursor_name
اسم Transact-SQL لمؤشر الخادم المحدد. cursor_nameيجب أن تتبع قواعد المعرفات.

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

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

إلى الأمام فقط
يحدد أنه لا يمكن عرض المؤشر إلا من السطر الأول إلى الأخير. يتم دعم خيار الجلب FETCH NEXT فقط. إذا تم تحديد FORWARD_ONLY بدون الكلمات الأساسية STATIC أو KEYSET أو DYNAMIC، فسيعمل المؤشر كمؤشر DYNAMIC. إذا لم يتم تحديد الوسيطة FORWARD_ONLY أو الوسيطة SCROLL، فإن الإعداد الافتراضي هو الوسيطة FORWARD_ONLY ما لم تكن الكلمات الأساسية STATIC أو KEYSET أو DYNAMIC موجودة. تحتوي المؤشرات STATIC وKEYSET وDYNAMIC على قيمة افتراضية SCROLL. على عكس واجهات برمجة تطبيقات قاعدة البيانات مثل ODBC وADO، يتم دعم وضع FORWARD_ONLY بواسطة مؤشرات Transact-SQL التالية: STATIC وKEYSET وDYNAMIC.

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

مجموعة المفاتيح
يشير إلى أن عضوية أو ترتيب الصفوف في المؤشر لا يتغير عند فتحه. يتم تضمين مجموعة من المفاتيح التي تحدد الصفوف بشكل فريد في الجدول tempdbمُسَمًّى مفاتيح.

يتم عرض التغييرات على القيم غير الأساسية في الجداول الأساسية التي أجراها مالك المؤشر أو تم إجراؤها بواسطة مستخدمين آخرين عندما يشاهدها مالك المؤشر. لا تنعكس التغييرات التي أجراها المستخدمون الآخرون (لا يمكن إجراء التغييرات باستخدام مؤشر خادم Transact-SQL). إذا تم حذف صف، فإن محاولة جلب الصفوف ترجع @@FETCH_STATUS -2. تشبه تحديثات القيم الأساسية عبر حدود المؤشر حذف صف قديم ثم إدراج صف جديد. الصف بالقيم الجديدة غير مرئي ومحاولات جلب الصف بالقيم القديمة ترجع @@FETCH_STATUS -2. تكون التحديثات مرئية على الفور إذا تم إجراؤها من خلال المؤشر باستخدام جملة WHERE CURRENT OF.

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

FAST_FORWARD
يشير إلى مؤشر FORWARD_ONLY، READ_ONLY تم تمكين تحسين الأداء فيه. لا يمكن تحديد الخيار FAST_FORWARD باستخدام الخيارين SCROLL أو FOR_UPDATE.

يقرأ فقط
يمنع التغييرات التي تم إجراؤها من خلال هذا المؤشر. لا يمكن أن تشير جملة WHERE CURRENT OF إلى مؤشر في عبارة UPDATE أو DELETE. يتمتع هذا الخيار بالأولوية على ميزة تحديث المؤشر الافتراضية.

SCROLL_LOCKS
يشير إلى أن التحديثات الموضوعة أو عمليات الحذف التي تم إجراؤها باستخدام المؤشر مضمونة للنجاح. يقوم SQL Server بتأمين الصفوف أثناء قراءتها في المؤشر للتأكد من أن هذه الصفوف متاحة للتغييرات اللاحقة. لا يمكن تحديد الخيار SCROLL_LOCKS باستخدام الخيار FAST_FORWARD أو STATIC.

مستبشر
يحدد أن التحديثات الموضوعة أو عمليات الحذف التي تم إجراؤها باستخدام المؤشر ستفشل إذا تم تحديث الصف منذ قراءته في المؤشر. لا يقوم SQL Server بتأمين الصفوف أثناء قراءتها داخل المؤشر. يتم استخدام المقارنات بدلا من ذلك الطابع الزمنيقيم العمود أو المجاميع الاختبارية، إن لم يكن في الجدول الطابع الزمنيالعمود لتحديد ما إذا كان الصف قد تغير منذ قراءته داخل المؤشر. إذا تم تعديل الصف، فستفشل محاولات التحديث أو الحذف. لا يمكن تحديد الخيار OPTIMISTIC باستخدام الخيار FAST_FORWARD.

TYPE_WARNING
يحدد أنه سيتم إرسال تحذير إلى العميل إذا تم تحويل المؤشر ضمنيًا من نوع مطلوب إلى آخر.

Select_statement
عبارة SELECT قياسية تحدد مجموعة نتائج المؤشر. لا يُسمح بالكلمات الأساسية COMPUTE وCOMPUTE BY وFOR BROWSE وINTO Select_statementإعلان المؤشر.

يقوم SQL Server ضمنيًا بتحويل المؤشر إلى نوع آخر إذا كانت الجمل موجودة Select_statementيتعارض مع مؤشر من النوع المطلوب. لمزيد من المعلومات، راجع تحويلات المؤشر الضمنية.

للتحديث]
يحدد الأعمدة في المؤشر المراد تحديثها. إذا كان اسم العمود [, ... ن] يتم توفيره، الأعمدة المدرجة فقط هي التي تسمح بالتغييرات. إذا تم استخدام عبارة UPDATE بدون قائمة أعمدة، فسيكون التحديث ممكنًا لجميع الأعمدة ما لم يتم تحديد خيار التزامن READ_ONLY.

تحدد عبارة DECLARE CURSOR سمات مؤشر خادم Transact-SQL، مثل خصائص العرض والاستعلام المستخدم لإنشاء مجموعة النتائج التي يعمل عليها المؤشر. تقوم عبارة OPEN بملء مجموعة النتائج، وتقوم عبارة FETCH بإرجاع صف منها. تقوم عبارة CLOSE بمسح مجموعة النتائج الحالية المرتبطة بالمؤشر. يقوم بيان DEALLOCATE بتحرير الموارد التي يستخدمها المؤشر.

يستخدم النموذج الأول من عبارة DECLARE CURSOR بناء جملة ISO لتحديد معلمات المؤشر. يستخدم النموذج الثاني من عبارة DECLARE CURSOR امتدادات للغة Transact-SQL التي تسمح لك بتعريف المؤشرات باستخدام نفس الأنواع المستخدمة في وظائف المؤشر لواجهات برمجة تطبيقات قاعدة البيانات مثل ODBC وADO.

ولا يمكن الخلط بين هذين الشكلين. إذا قمت بتحديد SCROLL أو حذف الكلمات الأساسية قبل الكلمة الأساسية CURSOR، فلن تتمكن من استخدام الكلمات الأساسية بين CURSOR وأيضًا لـ Select_statementالكلمات الدالة. عند تحديد الكلمات الرئيسية بين المؤشر، وكذلك ل Select_statementالكلمات الأساسية، لا يمكنك تحديد SCROLL أو INSENSITIVE قبل الكلمة الأساسية CURSOR.

إذا كنت تستخدم بناء جملة Transact-SQL لعبارة DECLARE CURSOR ولم تحدد خيارات READ_ONLY أو OPTIMISTIC أو SCROLL_LOCKS، فسيتم افتراض القيمة الافتراضية التالية.

    إذا كانت عبارة SELECT لا تدعم التحديثات (أو لديها أذونات غير كافية، أو تقوم بالوصول إلى الجداول البعيدة التي لا تدعم التحديثات، وما إلى ذلك)، فسيتم تعيين المؤشر إلى READ_ONLY.

    المؤشرات STATIC وFAST_FORWARD الافتراضية هي READ_ONLY.

    يتم تعيين مؤشرات DYNAMIC وKEYSET بشكل افتراضي على OPTIMISTIC.

لا يمكن الرجوع إلى المؤشرات إلا من خلال عبارات Transact-SQL الأخرى. لا يمكن لوظائف API لقاعدة البيانات الرجوع إلى المؤشرات. على سبيل المثال، بمجرد الإعلان عن المؤشر، لا يمكن لوظائف وأساليب OLE DB أو ODBC أو ADO الإشارة إلى اسمه. لا يمكن تحديد صفوف المؤشر باستخدام وظائف وأساليب واجهة برمجة التطبيقات المقابلة؛ لهذا الغرض، يجب عليك استخدام عبارات FETCH Transact-SQL.

يمكن استخدام الإجراءات المخزنة التالية لتعريف خصائص المؤشر بعد الإعلان عنه.

يمكن استخدام المتغيرات كجزء Select_statement، حيث يتم الإعلان عن المؤشر. لا تتغير قيم متغيرات المؤشر بعد الإعلان عنها.

افتراضيًا، يتم منح أذونات DECLARE CURSOR لجميع المستخدمين الذين لديهم إذن SELECT في طرق العرض والجداول والأعمدة التي يستخدمها المؤشر.

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

أ. استخدام مؤشر بسيط وبناء الجملة

تتضمن مجموعة النتائج التي يتم إنشاؤها عند فتح هذا المؤشر جميع صفوف وأعمدة الجدول. يمكن تحديث هذا المؤشر، ويتم تمثيل كافة التحديثات والحذف في التحديد لهذا المؤشر. يتم جلب FETCH``NEXT فقط لأنه لم يتم تحديد معلمة SCROLL.

قم بإعلان مؤشر vend_cursor للاختيار * من الشراء. Vendor OPEN vend_cursor FETCH NEXT FROM vend_cursor؛

ب. استخدام المؤشرات المتداخلة لعرض التقرير

يستخدم المثال التالي المؤشرات المتداخلة لعرض تقرير معقد. يتم الإعلان عن مؤشر داخلي لكل مزود.

قم بضبط NOCOUNT على؛ أعلن @vendor_id int , @vendor_name nvarchar ( 50 ) , @message varchar ( 80 ) , @product nvarchar ( 50 );مطبعة" -------- تقرير منتجات البائعين --------"; قم بإعلان مؤشر البائع_المؤشر لتحديد معرف البائع، الاسم من المشتري.Vendor WHERE PreferredVendorStatus = 1 ORDER BY VendorID؛افتح البائع_cursor الجلب التالي من البائع_cursor إلى @vendor_id، @vendor_name بينما @@FETCH_STATUS = 0 ابدأ الطباعة " " حدد @message = "----- منتجات من البائع: "+ @vendor_name PRINT @message - قم بتعريف المؤشر الداخلي القائم - على معرف المورد من المؤشر الخارجي.قم بتعريف مؤشر Product_cursor لتحديد v.Name من Purchasing.ProductVendor pv، Production.Product v WHERE pv.ProductID = v.ProductID وpv.VendorID = @vendor_id - قيمة متغيرة من المؤشر الخارجيافتح Product_cursor FETCH التالي من Product_cursor إلى @product IF @@FETCH_STATUS<>0 طباعة "<>" بينما @@FETCH_STATUS = 0 تبدأ في تحديد @message = " " + @product PRINT @message جلب التالي من Product_cursor إلى @product END CLOSE Product_cursor DEALLOCATE Product_cursor -- احصل على البائع التالي. جلب التالي من المورد_cursor إلى @vendor_id، @vendor_name نهاية إغلاق بائع_cursor؛ DEALLOCATE sales_cursor;


المؤشر هو رابط لمنطقة الذاكرة السياقية. في بعض تطبيقات لغة برمجة SQL (Oracle، Microsoft SQL Server) - مجموعة النتائج التي تم الحصول عليها عند تنفيذ استعلام ومؤشر السجل الحالي المرتبط به. أود أن أقول إن المؤشر عبارة عن جدول افتراضي يمثل مخزنًا بديلاً للبيانات. في هذه الحالة، يسمح لك المؤشر بالوصول إلى بياناته كما لو كانت بيانات مصفوفة عادية.
يتم استخدام المؤشرات في الإجراءات المخزنة. يكفي نظرية، دعونا نلقي نظرة على مثال:
لدينا قاعدة بيانات (قاعدة البيانات ليست جيدة بعض الشيء، وهذه واحدة من قاعدة بياناتي العمل المختبري، لكن مدرس قاعدة البيانات لدينا أصر على مثل هذا الهيكل)
/*المعلومات المصرفية*/
إنشاء جدول "البنك" (

`اسم البنك` VARCHAR (50) COLLATE utf8_bin ليس افتراضيًا فارغًا "" ,


المفتاح الأساسي ("الرقم البنكي")

)المحرك=InnoDB
مجموعة الأحرف "utf8" COLLATE "utf8_bin" ؛
/*بيانات عن الودائع*/
إنشاء جدول "التوزيع البنكي" (
`BankId` عدد صحيح (11) ليس فارغًا،
عدد صحيح "مستمر" (11) افتراضي فارغ،
`ContributeAmount` رقم عشري (10,0) ليس فارغًا،
عدد صحيح "ClientId" (11) ليس فارغًا،
المفتاح الأساسي ("معرف البنك"، "معرف العميل")،
المفتاح `BankId` (`BankId`)،
المفتاح `معرف العميل` (`معرف العميل`)،
القيد `bankdistribution_fk` المفتاح الخارجي (`BankId`) المراجع `bank` (`BankId`)،
القيد `bankdistribution_fk1` المفتاح الخارجي (`ClientId`) المراجع `client` (`ClientId`)
)المحرك=InnoDB
/*بيانات عن المستثمرين*/
إنشاء جدول "العميل" (
عدد صحيح ``ClientId` (3) وليس زيادة تلقائية فارغة،
`CreditCardId` BIGINT(10) ليست فارغة،
`اللقب` VARCHAR (50) COLLATE utf8_bin ليس افتراضيًا فارغًا "" ,
`الاسم` VARCHAR (50) COLLATE utf8_bin ليس افتراضيًا فارغًا "" ,
`الاسم الأول` VARCHAR (50) COLLATE utf8_bin ليس افتراضيًا فارغًا "" ,
`الهاتف` VARCHAR (50) COLLATE utf8_bin ليس افتراضيًا فارغًا "" ,
`العنوان` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
`SafeId` عدد صحيح (5) ليس فارغًا،
المفتاح الأساسي('ClientId`، `CreditCardId`)،
المفتاح `ClientId` (`ClientId`)

)المحرك=InnoDB
AUTO_INCREMENT=11 مجموعة أحرف "utf8" تجميع "utf8_bin"

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

حدد "البنك".* من "البنك" عدد محدود من_السجلات_التي نحتاجها،1
. وبالتالي، باستخدام LIMIT WE NEED_RECORD NUMBER، 1، نقوم باستخراج كل سجل في دورة من جدول البنك بدوره وتنفيذ الإجراءات التي نحتاجها معه، مع زيادة قيمة WE NEED_RECORD NUMBER بمقدار 1. الآن سنفعل الشيء نفسه ولكن باستخدام المؤشر
يبدأ
/* المتغيرات التي نستخرج منها البيانات */
قم بتعريف عدد صحيح vBankId؛
قم بتعريف vBankName VARCHAR(50);
قم بتعريف vAddress VARCHAR(50);
قم بتعريف vPhone VARCHAR (50)؛
/* متغير هادلر - أ*/
أعلن أنه تم تنفيذ عدد صحيح افتراضي 0؛
/*إعلان المؤشر*/
قم بتعريف مؤشر BankCursor لتحديد `bank`.`BankId`،`bank`.`BankName`،`bank`.`عنوان`،`bank`.`هاتف`، من `bank` حيث 1؛
/*غرض المعالج، والذي سيتم شرحه أدناه*/
إعلان معالج المتابعة لـ SQLSTATE "02000" SET تم = 1؛
/* فتح المؤشر */
افتح مؤشر البنك؛
/*استرداد البيانات*/
أثناء الانتهاء = 0 افعل

نحن نتخذ الإجراءات التي نحتاجها
نهاية بينما ;
/*إغلاق المؤشر*/
إغلاق مؤشر البنك؛
نهاية ؛

* تم تمييز كود المصدر هذا باستخدام Source Code Highlighter.

خطأ: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)

الرسالة: لا توجد بيانات - لم يتم جلب أي صفوف أو تحديدها أو معالجتها

SQLSTATE: يتم تشغيل 02000 عند الوصول إلى نهاية المؤشر، أو عندما يقوم التحديد أو التحديث بإرجاع سلسلة فارغة.

في السطر التالي أعلنا عن المؤشر DECLARE cursor_name CURSOR FOR Select_statement؛
افتح المؤشر افتح cursor_name؛
ثم، حتى نصل إلى نهاية المؤشر (أثناء الانتهاء = 0 DO)، نقوم باستخراج البيانات ومعالجتها.
يجب عليك إغلاق المؤشر قبل الخروج من الإجراء المخزن. إغلاق cursor_name؛

لا يبدو الأمر معقدا. ولكن هناك العديد من المخاطر المرتبطة بـ SQLSTATE "02000".

أثناء الانتهاء = 0 افعل
جلب BankCursor INTO vBankId,vBankName,vAddress,vPhone;

حدد (ContributeAmount) INTO vContributeAmountSUM من Bankdistribution حيث BankId = vBankId Limit 1؛
نقوم ببعض الإجراءات
نهاية بينما ;

* تم تمييز كود المصدر هذا باستخدام Source Code Highlighter.


كل شيء على ما يرام وصحيح من وجهة نظر بناء الجملة. لكن من وجهة نظر منطقية، لا. قد يحدث أن المودعين لم يفتحوا حسابات في بعض البنوك، ثم حدد (ContributeAmount) INTO vContributeAmountSUM من توزيع البنوك حيث BankId = vBankId Limit 1؛ SQLSTATE: سيتم إطلاق 02000، وسيتم تعيين المتغير الذي تم إنجازه على 1، وستنتهي الحلقة في وقت أبكر مما توقعنا. ويمكن تجنب ذلك عن طريق القيام بما يلي
أثناء الانتهاء = 0 افعل
جلب BankCursor INTO vBankId,vBankName,vAddress,vPhone;
/*استخرج للبنك مبلغ أي من ودائعه*/


إذا (vContributeAmountSUM > 0) ثم
/*استخرج للبنك مبلغ أي من ودائعه*/

إنهاء إذا ؛
نقوم ببعض الإجراءات
نهاية بينما ;

* تم تمييز كود المصدر هذا باستخدام Source Code Highlighter.


مع الطلب الأول، تحققنا مما إذا كانت هناك مساهمات (إذا لم تكن هناك أي مساهمات، فحينئذٍ vContributeAmountSUM == 0) وفقط في حالة وجودها، نقوم باسترداد البيانات.

لنفترض الآن أننا بحاجة إلى إزالة المبلغ الإجمالي في الحسابات في بنوك مختلفة لكل عميل
قم بتعريف مؤشر ClientSummCursor لتحديد المبلغ

قم بتعريف مؤشر ClientSummCursor لتحديد المبلغ (`bankdistribution`.`ContributeAmount`)، `bankdistribution`.`ClientId` من `bankdistribution` الانضمام الداخلي للعميل على (client.ClientId = Bankdistribution.`ClientId`) حيث يتم تجميع 1 حسب `bankdistribution`. `معرف العميل`;

افتح ClientSummCursor؛
أثناء الانتهاء = 0 افعل
جلب BankCursor INTO vBankId,vBankName,vAddress,vPhone;
/*استخرج للبنك مبلغ أي من ودائعه*/
حدد Count(ContributeAmount) INTO vContributeAmountSUM FROM Bankdistribution حيث BankId = vBankId Limit 1؛
/* تحقق مما إذا كانت هناك ودائع بالفعل في هذا البنك */
إذا (vContributeAmountSUM > 0) ثم
/*استخرج للبنك مبلغ أي من ودائعه*/
حدد ContributeAmount INTO vContributeAmountSUM من Bankdistribution حيث BankId = vBankId Limit 1؛
إنهاء إذا ؛


نقوم ببعض الإجراءات.
نهاية بينما ;

* تم تمييز كود المصدر هذا باستخدام Source Code Highlighter.

قد ينشأ نفس الموقف عندما تنتهي البيانات الموجودة في مؤشر ClientSummCursor في وقت أبكر من البيانات الموجودة في BankCursor، ويتم تشغيل SQLSTATE: 02000، ويتم تعيين المتغير المنجز على 1، وتنتهي حلقة while في وقت أبكر مما توقعنا. ويمكن تجنب ذلك عن طريق القيام بما يلي

افتح ClientSummCursor؛
أثناء الانتهاء = 0 افعل
جلب BankCursor INTO vBankId,vBankName,vAddress,vPhone;
/*استخرج للبنك مبلغ أي من ودائعه*/
حدد Count(ContributeAmount) INTO vContributeAmountSUM FROM Bankdistribution حيث BankId = vBankId Limit 1؛
/* تحقق مما إذا كانت هناك ودائع بالفعل في هذا البنك */
إذا (vContributeAmountSUM > 0) ثم
/*استخرج للبنك مبلغ أي من ودائعه*/
حدد ContributeAmount INTO vContributeAmountSUM من Bankdistribution حيث BankId = vBankId Limit 1؛
إنهاء إذا ؛
/* قبل استخراج البيانات من المؤشر الثاني، تذكر حالة sqlstate */
تعيين الحالة القديمة = تم؛
/* استخراج البيانات التي نحتاجها */
FETCH ClientSummCursor INTO vSum,vClientId;
/* تحقق مما إذا كان قد تم استرداد البيانات وما إذا كان SQLstate 0200 قد فشل */
إذا (تم = 0) ثم
نقوم ببعض الإجراءات.
إنهاء إذا ؛
/* قبل نهاية المدة، قم باستعادة قيمة المتغير المنجز */
تم الإعداد = old_status;
نهاية بينما ;

* تم تمييز كود المصدر هذا باستخدام Source Code Highlighter.

شكرًا لكل من قرأ هذا حتى الآن، وآمل أن يكون هذا مفيدًا لشخص ما.

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

وفقا لمعيار SQL، عند العمل مع المؤشرات، يتم تنفيذ الإجراءات الأساسية التالية:

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

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

في بعض الحالات، لا يمكنك الاستغناء عن استخدام المؤشر. ومع ذلك، إذا أمكن، يجب عليك تجنب استخدام المؤشر والعمل باستخدام أوامر معالجة البيانات القياسية: SELECT، UPDATE، INSERT، DELETE. ويرجع ذلك إلى حقيقة أن المؤشرات لا تسمح بعمليات التعديل على كامل حجم البيانات وأن سرعة إجراء عمليات معالجة البيانات باستخدام المؤشر أقل بشكل ملحوظ من سرعة تنفيذ المؤشر الوسائل القياسية SQL.

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

الإعلان عن المؤشر

يجب الإعلان عن المؤشرات قبل أن يتم استخدامها. يستخدم معيار SQL بناء الجملة التالي لإنشاء المؤشر:

قم بتعريف المؤشر cursor_name لـ Select_statement ])]

يعلن هذا التعبير عن المؤشر أعلن المؤشربالاسم "cursor_name".

غير حساسيتم إنشاء مؤشر ثابت لا يسمح بإجراء تغييرات. بالإضافة إلى ذلك، لا يتم عرض التغييرات التي أجراها مستخدمون آخرون. إذا كانت الكلمة الأساسية INSENSITIVE مفقودة، فسيتم إنشاء مؤشر ديناميكي.

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

تعبير Select_statementيشير إلى بنية لقراءة المعلومات مثل تحديد ... من ... . يجب ألا يحتوي على المشغل داخل، نظرًا لأن المؤشر له مشغل خاص به أحضرلملء المتغيرات ببيانات المؤشر.

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

إنشاء مؤشر مع وسيطة للتحديثيسمح لك بإجراء تغييرات على البيانات الموجودة في المؤشر إما في أعمدة محددة أو في حالة عدم وجود وسيطة من column_name، في جميع الأعمدة.

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

المؤشر مفتوح

يحدد SQL بناء الجملة التالي لفتح المؤشر "فتح المؤشر":

افتح cursor_name؛

جلب البيانات من المؤشر، جلب المؤشر

بناء جملة قراءة البيانات من المؤشر إلى بعض المتغيرات كما يلي:

جلب cursor_name إلى var_name [, var_name] ...;

المشغل أو العامل أحضرتحديد بيانات المؤشر المفتوحة في المتغيرات الموجودة بعد ذلك داخلوينقل المؤشر إلى الموضع التالي.

إغلاق المؤشر

المشغل أو العامل يغلقيغلق المؤشر. إذا لم يتم تحديد عامل التشغيل بشكل صريح، فسيتم إغلاق المؤشر تلقائيًا عند إغلاق كتلة البرنامج المقابلة.

إغلاق cursor_name؛

بعد الإغلاق، يصبح المؤشر غير قابل للوصول. عند الإغلاق، يتم تحرير جميع الأقفال التي تم تثبيتها أثناء تشغيل المؤشر. يمكن إغلاق المؤشرات المفتوحة فقط. يمكن إعادة فتح المؤشر المغلق ولكن لم يتم تحريره. لا يجوز إغلاق المؤشر غير المفتوح.

كل نظام إدارة قواعد بيانات له خصائصه الخاصة في استخدام المؤشر.

ميزات استخدام المؤشرات في Oracle

هناك أربع سمات للمؤشر في PL/SQL ٪وجد, ٪غير معثور عليه, ٪مفتوحو %ROWCOUNT. يتم الإعلان عن سمات المؤشر مثل عوامل التشغيل %TYPE و%ROWTYPE، على يمين اسم المؤشر.

%FOUND السمة

السمة غير موجودة

السمة %NOTFOUND هي عكس %FOUND تمامًا.

سمة %ISOPEN

تشير سمة %ISOPEN فقط إلى ما إذا كان المؤشر مفتوحًا أم لا.

%ROWCOUNT السمة

يصف %ROWCOUNTهي سمة رقمية تُرجع عدد الصفوف التي قرأها المؤشر في وقت معين.

مثال لمؤشر SQL في Oracle DBMS

قم بتعريف v_id managers.id %TYPE؛ v_name manager.name%TYPE; v_comm managers.comm%TYPE; مؤشر crs لتحديد المعرف والاسم والمجموع (comm) كاتصال من المديرين حيث يتم تجميع البيانات بين "2014-11-01" و"2014-11-30" حسب المعرف والاسم؛ ابدأ بفتح crs؛ حلقة الخروج عندما لا يتم العثور على crs%؛ جلب crs إلى v_id، v_name، v_comm؛ أدخل في قيم المكافأة (id، name، comm) (crs.id، crs.name، crs.comm)؛ حلقة النهاية؛ يقترف؛ إغلاق crs؛ نهاية؛

ميزات استخدام المؤشرات في خادم SQL

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

يدعم SQL Server المؤشرات الثابتة والديناميكية والمتسلسلة والمعتمدة على مجموعة المفاتيح.

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

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

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

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

لا تسمح المؤشرات التسلسلية بجلب البيانات في الاتجاه المعاكس، فقط من بداية المؤشر إلى نهايته. لا يقوم المؤشر المتسلسل بتخزين مجموعة من كافة صفوف البيانات. تتم قراءتها من قاعدة البيانات بمجرد تحديد المؤشر، مما يسمح بعكس جميع التغييرات التي أجراها المستخدمون على قاعدة البيانات ديناميكيًا باستخدام أوامر INSERT وUPDATE وDELETE. يقرأ المؤشر حالة البيانات الأحدث.

إعلان المؤشر

قم بتعريف المؤشر cursor_name لـ SELECT_statement ]]

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

المشغل أو العامل إلى الأمام فقطيحدد مؤشرًا تسلسليًا يسمح باسترداد البيانات فقط في الاتجاه من الصف الأول إلى الأخير. عند استخدام المشغل انتقليتم إنشاء مؤشر قابل للتمرير يسمح بالوصول إلى البيانات بأي ترتيب وفي أي اتجاه.

يتم تحديد نوع المؤشر من قبل المشغلين:

  • ثابت - إنشاء مؤشر ثابت.
  • ديناميكي - إنشاء مؤشر ديناميكي؛
  • KEYSET - إنشاء مؤشر رئيسي.

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

إذا تم إنشاء المؤشر مع المشغل مستبشر، فيمنع تغيير أو حذف الصفوف التي تم تغييرها بعد فتح المؤشر.

عند تحديد حجة TYPE_WARNINGسيقوم الخادم بالإبلاغ عن تغيير ضمني في نوع المؤشر إذا كان غير متوافق مع استعلام SELECT.

استرجاع البيانات من المؤشر، جلب

مباشرة بعد فتح المؤشر، يمكنك الحصول على محتوياته باستخدام الأمر التالي:

عند استخدام المشغل أولاًسيتم إرجاع الصف الأول من مجموعة نتائج المؤشر، والذي يصبح الصف الحالي. عندما يتم تحديدها آخرسيتم إرجاع السطر الأخير من المؤشر. ويصبح أيضًا السطر الحالي.

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

عند تحديد عامل قبلسيتم إرجاع السطر السابق للسطر الحالي. يصبح هذا الخط هو السطر الحالي.

المشغل أو العامل المطلق (رقم_السطر | @line_number_variable)إرجاع صف برقمه الترتيبي المطلق في مجموعة النتائج الكاملة للمؤشر. يمكن تحديد رقم السطر باستخدام ثابت أو كاسم متغير يتم تخزين رقم السطر فيه. يجب أن يكون المتغير من نوع بيانات عدد صحيح. يشار إلى كل من القيم الإيجابية والسلبية. عند تحديد قيمة موجبة، يتم حساب السلسلة من بداية المجموعة، بينما يتم حساب القيمة السالبة من النهاية. يصبح السطر المحدد هو السطر الحالي. إذا تم تحديد قيمة فارغة، فلن يتم إرجاع أي صف.

دعوى نسبي (عدد الصفوف | @عدد الصفوف المتغير)تقوم بإرجاع السطر الذي يقابل العدد المحدد من الأسطر بعد السطر الحالي. إذا قمت بتحديد عدد سالب من الصفوف، فسيتم إرجاع الصف الذي يمثل عدد الصفوف المحدد قبل الصف الحالي. سيؤدي تحديد قيمة فارغة إلى إرجاع الصف الحالي. يصبح الصف الذي تم إرجاعه هو الصف الحالي.

لفتح مؤشر عمومي، يجب عليك تحديد كلمة أساسية قبل اسمها عالمي. يمكن أيضًا تحديد اسم المؤشر باستخدام متغير.

في التعبير INTO @variable_name [،...n]يتم تحديد قائمة المتغيرات التي سيتم فيها تخزين قيم الأعمدة المقابلة للصف الذي تم إرجاعه. يجب أن يتطابق ترتيب المتغيرات مع ترتيب الأعمدة في المؤشر، ويجب أن يتطابق نوع بيانات المتغير مع نوع البيانات في عمود المؤشر.

تغيير وحذف البيانات باستخدام المؤشر

لتغيير البيانات باستخدام المؤشر، يجب عليك إصدار أمر UPDATE بالتنسيق التالي:

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

لحذف البيانات باستخدام المؤشر، استخدم أمر DELETE بالتنسيق التالي:

ونتيجة لذلك، سيتم حذف السطر الحالي في المؤشر.

تحرير الذاكرة، إلغاء تخصيصها

لإزالة المؤشر من الذاكرة، استخدم الأمر

إلغاء تخصيص cursor_name؛

@@FETCH_STATUS السمة

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

مثال على المؤشر في خادم SQL

قم بتعريف @company varchar(50)، @manager varchar(50)، @message varchar(256); أعلن مؤشر crs_clients محليًا لشركة محددة ومديرًا من العملاء حيث المدينة = "موسكو" حسب الشركة والمدير؛ طباعة "قائمة العملاء"; فتح crs_clients؛ جلب التالي من crs_clients إلى @company، @manager؛ بينما يبدأ @@FETCH_STATUS = 0 حدد @message = "Company" + @company + " manager " + @manager؛ طباعة @رسالة؛ - انتقل إلى جلب السجل التالي من crs_clients إلى @company، @manager؛ نهاية؛ إغلاق crs_clients؛ إلغاء تخصيص crs_clients؛

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

مفهوم المؤشر

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

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

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

وفقا لمعيار SQL، عند العمل مع المؤشرات، يمكن تحديد الإجراءات الرئيسية التالية:

  • الخلق أو إعلان المؤشر;
  • مؤشر الفتح، أي. ملئها بالبيانات المخزنة في الذاكرة متعددة المستويات؛
  • الاختيار من المؤشروتغيير صفوف البيانات معها؛
  • إغلاق المؤشروبعد ذلك يصبح غير قابل للوصول لبرامج المستخدم؛
  • تحرير المؤشر، أي. حذف المؤشر ككائن لأن إغلاقه لا يؤدي بالضرورة إلى تحرير الذاكرة المرتبطة به.

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

في بعض الحالات، استخدام المؤشر أمر لا مفر منه. ومع ذلك، إذا أمكن، يجب تجنب ذلك والعمل باستخدام أوامر معالجة البيانات القياسية: SELECT، UPDATE، INSERT، DELETE. بالإضافة إلى حقيقة أن المؤشرات لا تسمح بعمليات التعديل على حجم البيانات بأكمله، فإن سرعة إجراء عمليات معالجة البيانات باستخدام المؤشر أقل بشكل ملحوظ من أدوات SQL القياسية.

تنفيذ المؤشرات في بيئة MS SQL Server

يدعم SQL Server ثلاثة أنواع من المؤشرات:

  • تُستخدم مؤشرات SQL بشكل أساسي ضمن المشغلات والإجراءات المخزنة والبرامج النصية؛
  • تعمل مؤشرات الخادم على الخادم وتنفذ واجهة برمجة التطبيقات لـ ODBC وOLE DB وDB_Library؛
  • يتم تطبيق مؤشرات العميل على العميل نفسه. يقومون بإحضار مجموعة الصفوف الناتجة بالكامل من الخادم وتخزينها محليًا، مما يؤدي إلى تسريع عملية معالجة البيانات عن طريق تقليل الوقت الضائع الذي يتم قضاؤه في عمليات الشبكة.

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

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

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

يدعم SQL Server البيانات الثابتة والديناميكية تسلسليويتم التحكم بها عن طريق مجموعة من المفاتيح.

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

إذا قام مستخدمون آخرون بتغيير البيانات المضمنة في المؤشر في الجدول المصدر، فلن يؤثر ذلك على مؤشر ثابت.

في مؤشر ثابتليس من الممكن إجراء تغييرات، لذلك يتم فتحه دائمًا في وضع القراءة فقط.

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

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

المؤشرات المتسلسلةلا يسمح لهم بجلب البيانات في الاتجاه العكسي. يمكن للمستخدم فقط تحديد الصفوف من بداية المؤشر إلى نهايته. المؤشر التسلسليلا يخزن مجموعة من كافة الصفوف. تتم قراءتها من قاعدة البيانات بمجرد تحديدها في المؤشر، مما يسمح لجميع التغييرات التي أجراها المستخدمون على قاعدة البيانات أن تنعكس ديناميكيًا باستخدام أوامر INSERT وUPDATE وDELETE. يعرض المؤشر أحدث حالة للبيانات.

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

إدارة المؤشر في بيئة MS SQL Server

التحكم بالمؤشريتم تنفيذها عن طريق تنفيذ الأوامر التالية:

  • أعلن - الخلق أو إعلان المؤشر;
  • يفتح - مؤشر الفتح، أي. ملئه بالبيانات؛
  • أحضر الاختيار من المؤشروتغيير صفوف البيانات باستخدام المؤشر؛
  • يغلق - إغلاق المؤشر;
  • إلغاء التخصيص – تحرير المؤشر، أي. حذف المؤشر ككائن.

إعلان المؤشر

يوفر معيار SQL الأمر التالي لإنشاء مؤشر:

سيؤدي استخدام الكلمة الأساسية غير الحساسة إلى إنشاء مؤشر ثابت. تغييرات البياناتغير مسموح بها، بالإضافة إلى ذلك، لا يتم عرض التغييرات التي أجراها المستخدمون الآخرون. إذا كانت الكلمة الأساسية INSENSITIVE مفقودة، أ المؤشر الديناميكي.

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

تحدد عبارة SELECT نص طلب SELECT، الذي يحدد مجموعة الصفوف الناتجة للمؤشر.

يؤدي تحديد FOR READ_ONLY إلى إنشاء مؤشر للقراءة فقط ولا يسمح بأي تعديلات على البيانات. وهو يختلف عن الثابت، على الرغم من أن الأخير لا يسمح أيضًا بتغيير البيانات. يمكن إعلانه كمؤشر للقراءة فقط المؤشر الديناميكي، مما سيسمح بعرض التغييرات التي أجراها مستخدم آخر.

يسمح لك إنشاء مؤشر باستخدام وسيطة FOR UPDATE بالتنفيذ في المؤشر تغيير البياناتإما في الأعمدة المحددة أو، في حالة عدم وجود وسيطة OF column_name، في كافة الأعمدة.

في بيئة MS SQL Server، يتم قبول بناء الجملة التالي لأمر إنشاء المؤشر:

<создание_курсора>::= الإعلان عن cursor_name CURSOR FOR SELECT_statement ]]

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

إذا تم تحديد الكلمة الأساسية GLOBAL، فسيتم إنشاء مؤشر عام؛ فهو موجود حتى يتم إغلاق الاتصال الحالي.

يؤدي تحديد FORWARD_ONLY إلى الإنشاء المؤشر التسلسلي; لا يمكن أخذ عينات من البيانات إلا في الاتجاه من الصف الأول إلى الأخير.

يؤدي تحديد SCROLL إلى إنشاء مؤشر قابل للتمرير; يمكن الوصول إلى البيانات بأي ترتيب وفي أي اتجاه.

تحديد STATIC ينشئ مؤشر ثابت.

يؤدي تحديد KEYSET إلى إنشاء مؤشر مفتاح.

تحديد الديناميكية يخلق المؤشر الديناميكي.

إذا قمت بتحديد الوسيطة FAST_FORWARD لمؤشر READ_ONLY، فسيتم تحسين المؤشر الذي تم إنشاؤه للوصول السريع إلى البيانات. لا يمكن استخدام هذه الوسيطة مع الوسيطتين FORWARD_ONLY أو OPTIMISTIC.

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

من خلال تحديد الوسيطة TYPE_WARNING، سيقوم الخادم بإبلاغ المستخدم بتغيير ضمني في نوع المؤشر إذا كان غير متوافق مع استعلام SELECT.

فتح المؤشر

ل فتح المؤشروملئها بالبيانات من استعلام SELECT المحدد عند إنشاء المؤشر، استخدم الأمر التالي:

بعد فتح المؤشريتم تنفيذ عبارة SELECT المرتبطة، ويتم تخزين مخرجاتها في ذاكرة متعددة المستويات.

استرجاع البيانات من المؤشر

تماما بعد فتح المؤشريمكنك تحديد محتوياته (نتيجة تنفيذ الاستعلام المقابل) باستخدام الأمر التالي:

سيؤدي تحديد FIRST إلى إرجاع الصف الأول من مجموعة النتائج الكاملة للمؤشر، والذي يصبح الصف الحالي.

يؤدي تحديد LAST إلى إرجاع أحدث صف في المؤشر. ويصبح أيضًا السطر الحالي.

يؤدي تحديد NEXT إلى إرجاع الصف مباشرة بعد الصف الحالي في مجموعة النتائج الكاملة. الآن أصبح الحالي. بشكل افتراضي، يستخدم أمر FETCH هذه الطريقة لجلب الصفوف.

تقوم الكلمة الأساسية PRIOR بإرجاع الصف الذي يسبق الصف الحالي. يصبح الحالي.

دعوى المطلق (رقم_السطر | @line_number_variable)تقوم بإرجاع صف برقمه الترتيبي المطلق في مجموعة النتائج الكاملة للمؤشر. يمكن تحديد رقم السطر باستخدام ثابت أو كاسم متغير يتم تخزين رقم السطر فيه. يجب أن يكون المتغير من نوع بيانات عدد صحيح. يشار إلى كل من القيم الإيجابية والسلبية. عند تحديد قيمة موجبة، يتم حساب السلسلة من بداية المجموعة، بينما يتم حساب القيمة السالبة من النهاية. يصبح السطر المحدد هو السطر الحالي. إذا تم تحديد قيمة فارغة، فلن يتم إرجاع أي صف.

دعوى نسبي (عدد الصفوف | @عدد الصفوف المتغير)تقوم بإرجاع السطر الذي يمثل العدد المحدد من الأسطر بعد السطر الحالي. إذا قمت بتحديد عدد سالب من الصفوف، فسيتم إرجاع الصف الذي يمثل عدد الصفوف المحدد قبل الصف الحالي. سيؤدي تحديد قيمة فارغة إلى إرجاع الصف الحالي. يصبح الصف الذي تم إرجاعه هو الصف الحالي.

ل فتح المؤشر العالمي، يجب عليك تحديد الكلمة الأساسية GLOBAL قبل اسمها. يمكن أيضًا تحديد اسم المؤشر باستخدام متغير.

في التصميم INTO @variable_name [،...n]يتم تحديد قائمة المتغيرات التي سيتم فيها تخزين قيم الأعمدة المقابلة للصف الذي تم إرجاعه. يجب أن يتطابق ترتيب تحديد المتغيرات مع ترتيب الأعمدة في المؤشر، ويجب أن يتطابق نوع بيانات المتغير مع نوع البيانات في عمود المؤشر. إذا لم يتم تحديد بنية INTO، فإن سلوك أمر FETCH سوف يشبه سلوك أمر SELECT - حيث يتم عرض البيانات على الشاشة.

تغيير وحذف البيانات

لإجراء تغييرات باستخدام المؤشر، يجب عليك إصدار أمر UPDATE بالتنسيق التالي:

يمكن تغيير عدة أعمدة من صف المؤشر الحالي في عملية واحدة، ولكن يجب أن تنتمي جميعها إلى نفس الجدول.

لحذف البيانات باستخدام المؤشر، استخدم أمر DELETE بالتنسيق التالي:

ونتيجة لذلك، سيتم حذف السطر الحالي الموجود في المؤشر.

إغلاق المؤشر

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

حرر المؤشر

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

للتحكم في ما إذا كان قد تم الوصول إلى نهاية المؤشر، يوصى باستخدام الوظيفة: @@FETCH_STATUS

ترجع الدالة @@FETCH_STATUS:

0 إذا تم الجلب بنجاح؛

1 إذا فشل الجلب بسبب محاولة جلب خط خارج المؤشر؛

2 إذا فشل الجلب بسبب محاولة الوصول إلى صف محذوف أو معدل.

أعلن @id_kl INT، @firm VARCHAR(50)، @fam VARCHAR(50)، @message VARCHAR(80)، @nam VARCHAR(50)، @d DATETIME، @p INT، @s INT SET @s=0 PRINT "قائمة التسوق" قم بتعريف klient_cursor CURSOR LOCAL لتحديد رمز العميل والشركة والاسم الأخير من العميل WHERE City = "Moscow" اطلب حسب الشركة واسم العائلة، افتح klient_cursor وجلب التالي من klient_cursor إلى @id_kl، @firm، @fam بينما @@FETCH_STATUS =0 ابدأ حدد @message="Client "+@fam+ "Company"+ @firm PRINT @message SELECT @message="اسم المنتج تكلفة تاريخ الشراء" PRINT @message قم بإعلان مؤشر tovar_cursor لتحديد اسم المنتج وتاريخ المعاملة والمنتج .السعر* المعاملة.الكمية كتكلفة من معاملة الانضمام الداخلية للمنتج على المنتج. رمز المنتج=المعاملة.رمز المنتج حيث المعاملة.رمز العميل=@id_kl افتح tovar_cursor وجلب التالي من tovar_cursor إلى @nam، @d، @p IF @@FETCH_STATUS<>0 اطبع "لا توجد مشتريات" بينما @@FETCH_STATUS=0 ابدأ في تحديد @message=" "+@nam+" "+ CAST(@d AS CHAR(12))+" "+ CAST(@p AS CHAR(6)) PRINT @message SET @s=@s+@p جلب التالي من tovar_cursor إلى @nam، @d، @p END CLOSE tovar_cursor DEALLOCATE tovar_cursor SELECT @message="Total cost "+ CAST(@s AS CHAR(6)) PRINT @message -- الانتقال إلى العميل التالي -- جلب التالي من klient_cursor إلى @id_kl، @firm، @fam END CLOSE klient_cursor DEALLOCATE klient_cursor مثال 13.6. مؤشر لعرض قائمة السلع التي اشتراها العملاء من موسكو وتكلفتها الإجمالية.

مثال 13.7.تطوير مؤشر قابل للتمرير للعملاء من موسكو. إذا كان رقم الهاتف يبدأ بـ 1، فاحذف العميل الذي يحمل هذا الرقم وفي إدخال المؤشر الأول، استبدل الرقم الأول في رقم الهاتف بـ 4.

أعلن @firm VARCHAR(50)، @fam VARCHAR(50)، @tel VARCHAR(8)، @message VARCHAR(80) اطبع "قائمة العملاء" أعلن klient_cursor CURSOR GLOBAL SCROLL KEYSET لاختيار شركة، اسم العائلة، هاتف من العميل حيث المدينة ="موسكو" اطلب حسب الشركة، الاسم الأخير للتحديث، افتح klient_cursor FETCH التالي من klient_cursor إلى @firm، @fam، @tel بينما @@FETCH_STATUS=0 ابدأ في تحديد @message="Client "+@fam+ " Company "+ @firm " Phone "+ @tel PRINT @message - إذا كان رقم الهاتف يبدأ بـ 1، - احذف العميل بهذا الرقم إذا @tel LIKE '1%' احذف العميل حيث يوجد klient_cursor ELSE - انتقل إلى التالي جلب العميل التالي من klient_cursor إلى @firm، @fam، @tel END FETCH ABSOLUTE 1 من klient_cursor إلى @firm، @fam، @tel - في الإدخال الأول، استبدل الرقم الأول في رقم الهاتف بـ 4 UPDATE Client SET Phone ='4' + RIGHT(@ tel,LEN(@tel)-1)) حيث حدد klient_cursor الحالي @message="Client "+@fam+" Firm "+ @firm "Phone "+ @tel PRINT @message CLOSE klient_cursor إلغاء تخصيص klient_cursor مثال 13.7. مؤشر قابل للتمرير للعملاء من موسكو.

مثال 13.8.الاستخدام المؤشر كمعلمة إخراج الإجراء. يقوم الإجراء بإرجاع مجموعة بيانات - قائمة بالمنتجات.

يتم استدعاء الإجراء وطباعة البيانات من مؤشر الإخراج على النحو التالي:

أعلن @my_cur CURSOR DECLARE @n VARCHAR(20) EXEC my_proc @cur=@my_cur جلب الإخراج التالي من @my_cur INTO @n SELECT @n بينما (@@FETCH_STATUS=0) ابدأ الجلب التالي من @my_cur إلى @n SELECT @n نهاية إغلاق @my_cur DEALLOCATE @my_cur




قمة