PostgreSQL'de (x NOT NULL) ve (NOT x IS NULL)


16

Neden x IS NOT NULLeşit değil NOT x IS NULL?

Bu kod:

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;

aşağıdaki çıktıyı verir:

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

Ben bu çıktı almak için beklenirken:

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

1
Gerçekte bir kaydı NULL'a karşı kontrol ettiğinizi düşünüyor musunuz? (Sen
joanolo

@joanolo Evet. Kodumu idgerçek kod tabanımda kontrol etmek için değiştirdim , ancak sadece bir sorun aramak için birkaç saat geçirdikten sonra.
Anil

1
Bana öyle geliyor ki rec_variable IS NOT NULL, tüm sütunların NULL DEĞİL rec_variable IS NULLolup olmadığını kontrol ederken , tüm sütunların NULL olup olmadığını kontrol ediyor . Dolayısıyla NOT rec_variable IS NULLbeklediğim şeyi veriyor - "İçinde bir şey var mı?"
Anıl

Yanıtlar:


17

İki durumu ayırmanız gerekir: bir COLUMN'u NULL ile karşılaştırırsınız veya ROW'un (RECORD) tamamını NULL ile karşılaştırırsınız.

Aşağıdaki sorguyu düşünün:

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) ;

Bunu aldın:

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

Sanırım, sen ve ben ne bekliyordum. Bir COLUMN'u NULL'a karşı denetliyorsunuz ve "txt IS NULL" ve "NOT txt IS NULL" eşdeğeridir.

Ancak, farklı bir kontrol yaparsanız:

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) ;

Sonra sen al

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

Bu şaşırtıcı olabilir. Bir şey makul görünüyor (x IS NULL) ve (NOT x IS NULL) birbirinin tersidir. Diğer şey (ne "x IS NULL" veya "x IS NULL DEĞİL" doğrudur), garip görünüyor.

Ancak, PostgreSQL belgelerinde bunun olması gerektiği söyleniyor:

İfade satır değerliyse, satır ifadesinin kendisi null olduğunda veya satırın tüm alanları null olduğunda IS NULL doğrudur; satır ifadesinin kendisi null olmadığında ve tüm satır alanları boş olduğunda IS NOT NULL doğrudur boş olmayan. Bu davranış nedeniyle, IS NULL ve IS NOT NULL her zaman satır değerli ifadeler için ters sonuçlar döndürmez; özellikle, null ve null olmayan alanları içeren satır değerli bir ifade her iki test için false değerini döndürür. Bazı durumlarda, satır alanlarında herhangi bir ek test yapılmadan toplam satır değerinin null olup olmadığını kontrol edecek olan satırın NULL'DEN DISTINCT veya NULL'DEN DISTINCT DEĞİLDİR yazması tercih edilebilir.

İtiraf etmeliyim ki, hiç null'a karşı satır değerli bir karşılaştırma kullandığımı düşünmüyorum, ama sanırım olasılık varsa, bunun için bir kullanım durumu olabilir. Zaten ortak olduğunu düşünmüyorum.


Evet, açıklama anlamlıdır ve bunu yayınladığımdan beri yaptığım deneylerin sonuçlarıyla eşleşir. Tüm kayıt değişkenini karşılaştırmamın nedeni, arka planımın oldukça yaygın olduğu SQL olmayan dillerde olması. Kullanım durumları ile ilgili olarak, bir alan değişken yapmak yerine bir kayıt değişkenindeki tüm alanların dolu (rec IS NOT NULL) olup olmadığını kontrol etmek istediğinde bu kullanışlı bir şey.
Anil

1
@Anil: Bahsettiğiniz kullanım durumu daha önce ortaya çıktı: stackoverflow.com/questions/21021102/…
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.