احصل على باطل == فارغة في SQL
سؤال
وأتمنى للبحث في جدول قاعدة البيانات على عمود قيم الفارغة. في بعض الأحيان قيمة انا ابحث عن ذاتها فارغة. منذ خالية يساوي شيئا، حتى 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)