it-swarm.asia

هل هناك طريقة بسيطة في PL / pgSQL للتحقق مما إذا كان الاستعلام لم ينتج عنه أي نتيجة؟

أجرب حاليًا بعض الشيء مع PL/pgSQL وأريد أن أعرف ما إذا كانت هناك طريقة أكثر أناقة للقيام بشيء مثل هذا:

select c.data into data from doc c where c.doc_id = id and c.group_cur > group_cur order by c.id desc limit 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        select c.data into data from doc c where c.doc_id = id and c.global_cur > global_cur order by c.id desc limit 1;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN NULL;
17
icefex

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

في قسم أخطاء الاعتراض في وثائق PL/PgSQL يمكنك العثور على هذا التلميح:

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

بدلاً من استخدام الاستثناءات (سيئة) ، أو IF/THEN/ELSIF (أفضل) ، يمكنك إعادة كتابة ذلك إلى استعلام واحد:

SELECT c.data into data
FROM  doc c
WHERE c.doc_id = id
  and (
    c.group_cur > group_cur
    or
    c.global_cur > global_cur
  )
ORDER BY
  -- this will make group always preferred over global
  case when c.group_cur > group_cur then 1 else 2 end ASC,
  -- and this is your normal ordering
  c.id DESC
limit 1;

إذا كنت تريد حقًا استعلامين ، فيمكنك استخدام متغير FOUND خاص لاختبار ما إذا كان الاستعلام السابق أعطى أي نتيجة:

select c.data into data
from doc c
where c.doc_id = id and c.group_cur > group_cur
order by c.id desc limit 1;
if not found then
    select c.data into data
    from doc c
    where c.doc_id = id and c.global_cur > global_cur
    order by c.id desc limit 1;
    if not found then return null; end if;
end if;

إجباري RTFM روابط folllow :-)

انظر هذا للحصول على وصف للمتغير FOUND و هذا للكتل IF/THEN.

21
filiprem

يمكنك فحص متغير خاص FOUND من نوع منطقي. من التوثيق:

يبدأ FOUND في خطأ كل استدعاء دالة PL/pgSQL. يتم تعيينه من قبل كل نوع من أنواع البيانات التالية:

تقوم عبارة SELECT INTO بتعيين FOUND true إذا تم تعيين صف ، false إذا لم يتم إرجاع أي صف.

تقوم عبارة PERFORM بتعيين FOUND true إذا كانت تنتج (وتتجاهل) صفًا واحدًا أو أكثر ، خطأ إذا لم يتم إنتاج صف.

عبارات UPDATE و INSERT و DELETE تعين FOUND true إذا تأثر صف واحد على الأقل ، false إذا لم يتأثر أي صف.

تقوم عبارة FETCH بتعيين FOUND true إذا أرجعت صفًا ، false إذا لم يتم إرجاع أي صف.

تقوم عبارة MOVE بتعيين FOUND true إذا نجحت في تغيير موضع المؤشر بنجاح ، وإلا فإن false.

تقوم عبارة FOR أو FOREACH بتعيين FOUND true إذا تكررت مرة واحدة أو أكثر ، وإلا فإن false. يتم تعيين FOUND بهذه الطريقة عند خروج الحلقة ؛ داخل تنفيذ الحلقة ، لا يتم تعديل FOUND بواسطة عبارة الحلقة ، على الرغم من أنه قد يتغير عن طريق تنفيذ عبارات أخرى داخل نص الحلقة.

RETURN QUERY و RETURN QUERY EXECUTE set FOUND true إذا وجد الاستعلام صفًا واحدًا على الأقل ، خطأ إذا لم يتم إرجاع أي صف.

لا تغير عبارات PL/pgSQL الأخرى حالة FOUND. لاحظ على وجه الخصوص أن EXECUTE يغير ناتج GET DIAGNOSTICS ، لكنه لا يغير FOUND.

FOUND هو متغير محلي داخل كل دالة PL/pgSQL ؛ أي تغييرات عليها تؤثر فقط على الوظيفة الحالية.

14
alexk