سؤال

وأتمنى للبحث في جدول قاعدة البيانات على عمود قيم الفارغة. في بعض الأحيان قيمة انا ابحث عن ذاتها فارغة. منذ خالية يساوي شيئا، حتى NULL، قائلا

where MYCOLUMN=SEARCHVALUE 

وسوف تفشل. والآن لا بد لي من اللجوء إلى

where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL))

هل هناك طريقة أبسط من أن تقول ذلك؟

و(أنا باستخدام Oracle إذا ما يهم)

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

المحلول

ويمكنك القيام ISNULL أو الاشياء NVL، لكنه مجرد الذهاب لجعل محرك بذل المزيد من العمل. عليك أن تكون استدعاء وظائف للقيام التحويلات العمود التي لها ثم لمقارنة النتائج.

استخدم ما لديك

where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL))

نصائح أخرى

وAndy يستر يؤكد أن النموذج الأصلي للاستعلام أكثر كفاءة من استخدام NVL. قررت لاختبار هذا التأكيد:

    SQL> DECLARE
      2    CURSOR B IS
      3       SELECT batch_id, equipment_id
      4         FROM batch;
      5    v_t1  NUMBER;
      6    v_t2  NUMBER;
      7    v_c1  NUMBER;
      8    v_c2  NUMBER;
      9    v_b   INTEGER;
     10  BEGIN
     11  -- Form 1 of the where clause
     12    v_t1 := dbms_utility.get_time;
     13    v_c1 := dbms_utility.get_cpu_time;
     14    FOR R IN B LOOP
     15       SELECT COUNT(*)
     16         INTO v_b
     17         FROM batch
     18        WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL);
     19    END LOOP;
     20    v_t2 := dbms_utility.get_time;
     21    v_c2 := dbms_utility.get_cpu_time;
     22    dbms_output.put_line('For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL)');
     23    dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
     24    dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
     25  
     26  -- Form 2 of the where clause
     27    v_t1 := dbms_utility.get_time;
     28    v_c1 := dbms_utility.get_cpu_time;
     29    FOR R IN B LOOP
     30       SELECT COUNT(*)
     31         INTO v_b
     32         FROM batch
     33        WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx');
     34    END LOOP;
     35    v_t2 := dbms_utility.get_time;
     36    v_c2 := dbms_utility.get_cpu_time;
     37    dbms_output.put_line('For clause: WHERE NVL(equipment_id,''xxxx'') = NVL(R.equipment_id,''xxxx'')');
     38    dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
     39    dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
     40  END;
     41  /


    For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL)
    CPU seconds used: 84.69
    Elapsed time: 84.8
    For clause: WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx')
    CPU seconds used: 124
    Elapsed time: 124.01

    PL/SQL procedure successfully completed

    SQL> select count(*) from batch;

  COUNT(*)
----------
     20903

SQL> 

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

في الخبراء أوراكل العمارة قاعدة بيانات رأيت:

WHERE DECODE(MYCOLUMN, SEARCHVALUE, 1) = 1

وأنا لا أعرف ما اذا كان أسهل، ولكن لقد استعملت بعض الأحيان


WHERE ISNULL(MyColumn, -1) = ISNULL(SearchValue, -1)

واستبدال "-1" مع بعض قيمة صالحة لنوع العمود ولكن أيضا ليس من المرجح أن تكون وجدت في الواقع في البيانات.

ملحوظة: أنا استخدم MS SQL، وليس أوراكل، لذلك لست متأكدا إذا كان "ISNULL" صالحة

استخدم NVL ليحل محل لاغية مع بعض قيمة وهمية على كلا الجانبين، كما في:

WHERE NVL(MYCOLUMN,0) = NVL(SEARCHVALUE,0)

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

وشبة الكود التالي.

if (SEARCHVALUE IS NULL) {
    condition = 'MYCOLUMN IS NULL'
} else {
    condition = 'MYCOLUMN=SEARCHVALUE'
}
runQuery(query,condition)

إذا قيمة خارج النطاق ممكنة:

where coalesce(mycolumn, 'out-of-band') 
    = coalesce(searchvalue, 'out-of-band')

وهذا يمكن أيضا القيام بهذه المهمة في أوراكل.

WHERE MYCOLUMN || 'X'  = SEARCHVALUE || 'X'

وهناك بعض الحالات التي يتفوق على اختبار NULL IS مع OR.

وفوجئت أيضا أن DECODE يتيح لك تحقق NULL ضد NULL.

WITH 
TEST AS
(
    SELECT NULL A FROM DUAL
)
SELECT DECODE (A, NULL, 'NULL IS EQUAL', 'NULL IS NOT EQUAL')
FROM TEST

وحاول

WHERE NVL(mycolumn,'NULL') = NVL(searchvalue,'NULL')

وأعتقد أن ما لديك على ما يرام. هل يمكن أن نستخدم ربما:

where NVL(MYCOLUMN, '') = NVL(SEARCHVALUE, '')

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

WHERE rte_pending.ltr_rte_id = prte_id
  OR ((rte_pending.ltr_rte_id IS NULL OR rte_pending.ltr_rte_id IS NOT NULL)
      AND prte_id IS NULL)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top