الوصول إلى مجموعات النتائج من داخل الإجراءات المخزنة Transact-SQL SQL Server

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

  •  09-06-2019
  •  | 
  •  

سؤال

أنا أستخدم SQL Server 2005، وأود أن أعرف كيفية الوصول إلى مجموعات نتائج مختلفة من داخل transact-sql.يقوم الإجراء المخزن التالي بإرجاع مجموعتين من النتائج، كيف يمكنني الوصول إليهما، على سبيل المثال، من خلال إجراء مخزن آخر؟

CREATE PROCEDURE getOrder (@orderId as numeric) AS
BEGIN   
    select order_address, order_number from order_table where order_id = @orderId
    select item, number_of_items, cost from order_line where order_id = @orderId
END

أحتاج إلى أن أكون قادرًا على التكرار خلال مجموعتي النتائج بشكل فردي.

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

مجموعات النتائج التي يتم إرجاعها بواسطة الإجراءات ليست نفس أنواع البيانات أو عدد الأعمدة.

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

المحلول

الجواب القصير هو:لا يمكنك أن تفعل ذلك.

من خلال T-SQL، لا توجد طريقة للوصول إلى نتائج متعددة لاستدعاء إجراء مخزن متداخل، دون تغيير الإجراء المخزن كما اقترح الآخرون.

للاكتمال، إذا كان الإجراء يُرجع نتيجة واحدة، فيمكنك إدراجها في جدول مؤقت أو متغير جدول بالصيغة التالية:

INSERT INTO #Table (...columns...)
EXEC MySproc ...parameters...

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

نصائح أخرى

لقد تمكنت بسهولة من القيام بذلك عن طريق إنشاء إجراء مخزن لـ SQL2005 CLR والذي يحتوي على مجموعة بيانات داخلية.

كما ترى، سيقوم SqlDataAdapter الجديد بملء sproc مجموعة نتائج متعددة في مجموعة بيانات متعددة الجداول بشكل افتراضي.يمكن إدراج البيانات الموجودة في هذه الجداول بدورها في جداول #Temp في sproc الاستدعاء الذي ترغب في كتابته. dataset.ReadXmlSchema سوف تظهر لك مخطط كل مجموعة النتائج.

الخطوة 1:ابدأ في كتابة sproc الذي سيقرأ البيانات من sproc متعدد النتائج

أ.إنشاء جدول منفصل لكل مجموعة نتائج حسب المخطط.

CREATE PROCEDURE [dbo].[usp_SF_Read] AS
SET NOCOUNT ON;
CREATE TABLE #Table01 (Document_ID VARCHAR(100)
  , Document_status_definition_uid INT
  , Document_status_Code VARCHAR(100) 
  , Attachment_count INT
  , PRIMARY KEY (Document_ID));

ب.عند هذه النقطة قد تحتاج إلى إعلان مؤشر للاتصال بشكل متكرر بـ CLR sproc الذي ستقوم بإنشائه هنا:

الخطوة 2:اصنع CLR Sproc

Partial Public Class StoredProcedures
    <Microsoft.SqlServer.Server.SqlProcedure()> _
    Public Shared Sub usp_SF_ReadSFIntoTables()

    End Sub
End Class

أ.الاتصال باستخدام New SqlConnection("context connection=true").

ب.قم بإعداد كائن أمر (cmd) ليحتوي على مجموعة النتائج المتعددة sproc.

ج.احصل على جميع البيانات باستخدام ما يلي:

    Dim dataset As DataSet = New DataSet
    With New SqlDataAdapter(cmd)
        .Fill(dataset) ' get all the data.
    End With
'you can use dataset.ReadXmlSchema at this point...

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

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

هذا كل ما في الأمر!

~ شون، بالقرب من سياتل

هناك حماقة يمكنك القيام بها أيضًا.قم بإضافة معلمة اختيارية N int إلى sproc الخاص بك.افتراضي قيمة N إلى -1.إذا كانت قيمة N هي -1، فقم بتنفيذ كل ما تختاره.بخلاف ذلك، قم بتحديد Nth ثم حدد Nth فقط.

على سبيل المثال،

if (N = -1 or N = 0)
    select ...

if (N = -1 or N = 1)
    select ...

سيحصل المتصلون بـ sproc الخاص بك الذين لم يحددوا N على مجموعة نتائج تحتوي على أكثر من جدول واحد.إذا كنت بحاجة إلى استخراج واحد أو أكثر من هذه الجداول من sproc آخر، فما عليك سوى الاتصال بـ sproc الخاص بك وتحديد قيمة لـ N.سيكون عليك الاتصال بـ sproc مرة واحدة لكل جدول ترغب في استخراجه.غير فعال إذا كنت بحاجة إلى أكثر من جدول واحد من مجموعة النتائج، ولكنه يعمل في TSQL خالص.

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

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

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

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

هناك طريقتان للقيام بذلك بسهولة.قم إما بلصق النتائج في جدول مؤقت ثم قم بالرجوع إلى الجدول المؤقت من sproc الخاص بك.البديل الآخر هو وضع النتائج في متغير XML الذي يتم استخدامه كمتغير OUTPUT.

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

مع XML، يمكن أن يكون كثيفًا للذاكرة وبطيئًا.

يمكنك تحديدها في جداول مؤقتة أو كتابة وظائف ذات قيمة في الجدول لإرجاع مجموعات النتائج.هل تسأل عن كيفية التكرار من خلال مجموعات النتائج؟

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