سؤال

لقد كتبت إجراءً مخزنًا مخزّنًا باستخدام SQL Server 2005. يستغرق الأمر عددًا من المعلمات ومعايير البحث معقدة بشكل معتدل.

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

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

كمية البيانات في النظام ليست عالية جدًا (فقط بضعة ملايين صف لجداول أكبر). قد يكون هناك العديد من المستخدمين المتزامنين.

ما هي أفكار الناس حول هذه الأساليب؟ هل قام أي شخص بحل هذه المشكلة من قبل بطريقة لم أفكر فيها؟

أنهم لا تستطيع خذ النتائج وعد في نفس الوقت من مكالمة واحدة.

شكرًا!

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

المحلول

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

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

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

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

نصائح أخرى

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

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

أنا متأكد من أنك فكرت في هذا: إذا كانت البيانات تغير العدد وقد يكون أي ترحيل فعلي لاحق مختلفًا (إذا تمت إضافة / إزالتها)

يمكن أن يكون لديك وظيفة محددة المستخدم التي أعادت PKs من الصفوف المطابقة ، من السهل نسبيًا القيام

SELECT COUNT(*) FROM dbo.MyQueryFunction(@Param1, @Param2)

للحصول على العد ، ثم

SELECT Col1, Col2, ...
FROM dbo.MyQueryFunction(@Param1, @Param2) AS FN
     JOIN dbo.MyTable AS T
         ON T.ID = FN.ID
     ... more JOINs ...

للحصول على البيانات.

لا أعرف مدى جودة هذا الأمر مع row_number للترحيل اللاحق ، ولكنه سيبقي "منطق الاستعلام" الفعلي الموجود في MyQueryFunction - لا يزال لديك جميع الوصلات لأي عمود يتم استرجاعه التكرار في sproc و sproc و الوظيفة.

قد لا تساعد في مشكلتك المحددة ، ولكن SQL 2005 تقدم وظيفة ROW_Number وهي مفيدة للتحقق من الترحيل

مثال row_number

أسهل بكثير من جداول مؤقتة.

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

الشيء الكبير مع SQL Server هو أنك قد تحتاج إلى استخدام row_number () vs Rownum.

procedure get_sample_results (
    startrow in number default 1,
    numberofrows in number default 10,
    whereclause in varchar2,
    matchingrows out number,
    rc  out sys_refcursor
)
is
    stmnt varchar2(5000);
    endrow number;
begin

    stmnt := stmnt || 'select * from table t where 1=1';
    if whereclause is not null then
        stmnt := stmnt || ' and ' || whereclause;
    end if;

    execute immediate 'select count(*) from (' || stmnt || ')' into matchingrows;

    stmnt := 'select * from (' || stmnt || ') where rownum between :1 and :2';        

    -- must subtract one to compenstate for the inclusive between clause
    endrow := startrow + numberofrows - 1;
    open rc for stmnt using startrow, endrow;

end get_sample_results;

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

هذا شيء أفكر فيه بصوت عالٍ (وهو يتجول في وقت سريري ...)

CREATE PROCEDURE WhatEver
(
   @SomeParam1 NVARCHAR(200),
   ....
   @SomeParam_X INT,
   @NumberOfResults INTEGER OUTPUT
)
BEGIN
    SET NOCOUNT ON

    -- Do your search stuff.
    -- ....
    SELECT Whatever
    FROM WhatWhat
    ...

    -- Ok, the results/recordset has been sent prepared.
    -- Now the rowcount
    SET @NumberOfResults = @@ROWCOUNT
END

HTH.

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