Şebeke
Bu, @ Daniel'in akıllı operatörü üzerine inşa edilmiştir .
Bu sırada, polimorfik tipler kullanarak fonksiyon / operatör birleşimini oluşturun . Sonra her tür için çalışır - tıpkı yapı gibi.
Ve işlevi yapın IMMUTABLE
.
CREATE FUNCTION is_distinct_from(anyelement, anyelement)
RETURNS bool LANGUAGE sql IMMUTABLE AS
'SELECT $1 IS DISTINCT FROM $2';
CREATE OPERATOR <!> (
PROCEDURE = is_distinct_from(anyelement,anyelement),
LEFTARG = anyelement
, RIGHTARG = anyelement
);
Symbolhound ile hızlı bir arama bitti, bu nedenle operatör <!>
modüllerin hiçbirinde kullanımda görünmüyor.
Eğer bu operatöre çok kullanacağız, sen (sorgu planlayıcısı yardımcı olmak biraz daha eti dışarı olabilir losthorse yorumunda önerilen gibi ). Yeni başlayanlar için, sorgu optimize edicisine yardımcı olmak üzere COMMUTATOR
ve NEGATOR
cümlelerini ekleyebilirsiniz . CREATE OPERATOR
Yukarıdakileri bununla değiştir :
CREATE OPERATOR <!> (
PROCEDURE = is_distinct_from(anyelement,anyelement),
LEFTARG = anyelement
, RIGHTARG = anyelement
, COMMUTATOR = <!>
, NEGATOR = =!=
);
Ve Ekle:
CREATE FUNCTION is_not_distinct_from(anyelement, anyelement)
RETURNS bool LANGUAGE sql IMMUTABLE AS
'SELECT $1 IS NOT DISTINCT FROM $2';
CREATE OPERATOR =!= (
PROCEDURE = is_not_distinct_from(anyelement,anyelement),
LEFTARG = anyelement
, RIGHTARG = anyelement
, COMMUTATOR = =!=
, NEGATOR = <!>
);
Ancak ek hükümler eldeki kullanım durumuna yardımcı olmaz ve düz dizinler hala kullanılmaz. Bunu başarmak çok daha karmaşık. (Denemedim.) Ayrıntılar için kılavuzdaki "Operatör Optimizasyon Bilgileri" bölümünü okuyun .
Test durumu
Sorudaki test durumu ancak dizideki tüm değerler aynı olduğunda başarılı olabilir. Question ( '{null,A}'::text[]
) içindeki dizi için sonuç her zaman TRUE olur. Bu amaçlanıyor mu? "TÜM FARKLIDIR" için başka bir test ekledim:
SELECT foo
, foo <!> ANY ('{null,A}'::text[]) AS chk_any
, foo <!> ALL ('{null,A}'::text[]) AS chk_all
FROM (
VALUES ('A'),('Z'),(NULL)
) z(foo)
foo | chk_any | chk_all
-----+---------+---------
A | t | f
Z | t | t
| t | f
Standart operatörlerle alternatif
foo IS DISTINCT FROM ANY (test_arr) -- illegal syntax
olabilir neredeyse çevrilecek
foo = ALL (test_arr) IS NOT TRUE
foo = ALL (test_arr)
verimler ...
TRUE
.. eğer tüm elemanlar foo
FALSE
.. herhangi bir NOT NULL
eleman ise <> foo
NULL
.. en az bir eleman IS NULL
ve hiçbir eleman<> foo
Yani, kalan köşe durumu
- foo IS NULL
- ve elemanlardan test_arr
başka bir şeyden NULL
oluşmuyor.
İkisinden biri hariç tutulabilirse, işimiz bitmiştir. Bu nedenle,
- sütunu tanımlanmışsa basit testi kullanın NOT NULL
.
- ya sen biliyor dizisi tüm NULL asla.
Başka, ayrıca test edin:
AND ('A' = ALL(test_arr) IS NOT NULL OR
'B' = ALL(test_arr) IS NOT NULL OR
foo IS NOT NULL)
Burada 'A'
ve 'B'
olabilmektedir bir farklı değerleri. SO: Bu ilgili soru altında açıklama ve alternatifler
PostgreSQL tüm NULLs dizi
Yine, örneğin boş dizede var olmayan herhangi bir değeri biliyorsanız , yine de basitleştirebilirsiniz:test_arr
''
AND ('' = ALL(test_arr) IS NOT NULL OR
foo IS NOT NULL)
İşte tüm kombinasyonları kontrol etmek için eksiksiz bir test matrisi:
SELECT foo, test_arr
, foo = ALL(test_arr) IS NOT TRUE AS test_simple
, foo = ALL(test_arr) IS NOT TRUE
AND ('A' = ALL(test_arr) IS NOT NULL OR
'B' = ALL(test_arr) IS NOT NULL OR
foo IS NOT NULL) AS test_sure
FROM (
VALUES ('A'),('Z'),(NULL)
) v(foo)
CROSS JOIN (
VALUES ('{null,A}'::text[]),('{A,A}'),('{null,null}')
) t(test_arr)
foo | test_arr | test_simple | test_sure
-----+-------------+-------------+-----------
A | {NULL,A} | t | t
A | {A,A} | f | f -- only TRUE case
A | {NULL,NULL} | t | t
Z | {NULL,A} | t | t
Z | {A,A} | t | t
Z | {NULL,NULL} | t | t
| {NULL,A} | t | t
| {A,A} | t | t
| {NULL,NULL} | t | f -- special case
Bu, Andriy'nin EXCEPT
çözümünden biraz daha ayrıntılı , ancak önemli ölçüde daha hızlı.