PostgreSQL में (x IS NULL नहीं) बनाम (NOT x IS NULL)


16

के x IS NOT NULLबराबर क्यों नहीं है NOT x IS NULL?

यह कोड:

CREATE TABLE bug_test (
    id int,
    name text
);

INSERT INTO bug_test
VALUES (1, NULL);

DO $$
DECLARE
    v_bug_test bug_test;
BEGIN
    RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
    RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
    RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);

    SELECT *
    INTO v_bug_test
    FROM bug_test
    WHERE id = 1;

    RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
    RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
    RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);
END
$$;

DROP TABLE bug_test;

निम्नलिखित आउटपुट देता है:

(,): t
(,): f
(,): f
(1,): f
(1,): f ???
(1,): t

जबकि मुझे यह आउटपुट मिलने की उम्मीद है:

(,): t
(,): f
(,): f
(1,): f
(1,): t <<<
(1,): t

1
क्या आप इस तथ्य पर विचार कर रहे हैं कि आप वास्तव में NULL के खिलाफ पूरे रिकॉर्ड की जाँच कर रहे हैं। (आप हैं
जोआनोलो

@joanolo हाँ। मैंने idअपने वास्तविक कोडबेस में जांच करने के लिए कोड को स्विच कर दिया है , लेकिन केवल कुछ घंटों के लिए समस्या की खोज करने के बाद।
अनिल

1
यह मुझे लगता है कि rec_variable IS NOT NULLजाँच रहा है कि सभी कॉलम NULL नहीं हैं, जबकि rec_variable IS NULLजाँच रहा है कि क्या सभी कॉलम NULL हैं। इसलिए NOT rec_variable IS NULLमुझे जो उम्मीद थी - सवाल का जवाब "क्या अंदर कुछ है?"।
अनिल

जवाबों:


17

आपको दो स्थितियों में अंतर करना होगा: आप NULL के विरुद्ध एक COLUMN की तुलना करते हैं, या आप NULL के विरुद्ध पूरे ROW (RECORD) की तुलना करते हैं।

निम्नलिखित प्रश्न पर विचार करें:

SELECT
    id, 
    txt, 
    txt     IS NULL AS txt_is_null, 
    NOT txt IS NULL AS not_txt_is_null, 
    txt IS NOT NULL AS txt_is_not_null
FROM
    (VALUES
        (1::integer, NULL::text)
    ) 
    AS x(id, txt) ;

आप इसे प्राप्त करें:

+----+-----+-------------+-----------------+-----------------+
| id | txt | txt_is_null | not_txt_is_null | txt_is_not_null | 
+----+-----+-------------+-----------------+-----------------+
|  1 |     | t           | f               | f               | 
+----+-----+-------------+-----------------+-----------------+

यह है, मुझे लगता है, आप और मैं क्या उम्मीद करेंगे। आप NULL के खिलाफ एक COLUMN की जाँच कर रहे हैं, और आपको "txt IS NOT NULL" और "NOT txt IS NULL" बराबर हैं।

हालाँकि, यदि आप एक अलग जाँच करते हैं:

SELECT
    id, 
    txt, 
    x       IS NULL AS x_is_null,
    NOT x   IS NULL AS not_x_is_null,
    x   IS NOT NULL AS x_is_not_null
FROM
    (VALUES
        (1, NULL)
    ) 
    AS x(id, txt) ;

फिर आप प्राप्त करें

+----+-----+-----------+---------------+---------------+
| id | txt | x_is_null | not_x_is_null | x_is_not_null |
+----+-----+-----------+---------------+---------------+
|  1 |     | f         | t             | f             |
+----+-----+-----------+---------------+---------------+

यह आश्चर्य की बात हो सकती है। एक चीज़ उचित लगती है (x IS NULL) और (NOT x IS NULL) एक दूसरे के विपरीत हैं। दूसरी बात (तथ्य यह है कि न तो "x IS NULL" है और न ही "x IS NOT NULL" सच है), अजीब लगता है।

हालाँकि, यह वही है जो PostgreSQL प्रलेखन कहता है कि ऐसा होना चाहिए:

यदि अभिव्यक्ति पंक्ति-मान है, तो पंक्ति पूर्ण होने पर IS NULL सत्य है या पंक्ति के सभी फ़ील्ड शून्य हैं, जबकि IS NOT NULL सत्य है जब पंक्ति अभिव्यक्ति स्वयं अशक्त है और सभी पंक्ति फ़ील्ड हैं गैर-शून्य। इस व्यवहार के कारण, IS NULL और IS NOT NULL हमेशा पंक्ति-मूल्यवान अभिव्यक्तियों के लिए उलटा परिणाम नहीं देते हैं; विशेष रूप से, एक पंक्ति-मूल्यवान अभिव्यक्ति जिसमें शून्य और गैर-शून्य दोनों फ़ील्ड शामिल हैं, दोनों परीक्षणों के लिए गलत वापस आ जाएंगे। कुछ मामलों में, पंक्ति से IS IS DISTINCT FULL लिखना संभव नहीं हो सकता है या NULL से पंक्ति नहीं है, जो कि केवल यह जाँच करेगा कि पंक्ति फ़ील्ड पर कोई अतिरिक्त परीक्षण किए बिना समग्र पंक्ति मान शून्य है या नहीं।

मुझे स्वीकार करना चाहिए कि मुझे नहीं लगता कि मैंने कभी भी अशक्त के खिलाफ एक पंक्ति-मूल्यवान तुलना का उपयोग किया है, लेकिन मुझे लगता है कि यदि संभावना है, तो इसके लिए कुछ उपयोग-मामला हो सकता है। मुझे नहीं लगता कि यह किसी भी तरह से सामान्य है।


हां, यह स्पष्टीकरण समझ में आता है और मैंने इसे पोस्ट करने के बाद से किए गए प्रयोगों के परिणामों से मेल खाता है। मैंने पूरे रिकॉर्ड चर की तुलना क्यों की है क्योंकि मेरी पृष्ठभूमि गैर-SQL भाषाओं में है, जहां यह काफी सामान्य है। उपयोग के मामलों के बारे में, मुझे लगता है कि यह तब काम आता है जब कोई यह जांचना चाहता है कि क्या रिकॉर्ड चर में सभी फ़ील्ड भरे गए हैं (फिर भी IS NULL नहीं है), इसके बजाय इसे क्षेत्र के आधार पर करें।
अनिल

1
@ एनील: आपके द्वारा उल्लिखित उपयोग का मामला इससे पहले पॉप अप हो चुका है: stackoverflow.com/questions/21021102/…
Erwin Brandstetter
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.