ऑपरेटर
यह @ डैनियल के चतुर ऑपरेटर पर बन रहा है ।
इस पर रहते हुए, पॉलीमॉर्फिक प्रकारों का उपयोग करके फ़ंक्शन / ऑपरेटर कॉम्बो बनाएं । फिर यह किसी भी प्रकार के लिए काम करता है - निर्माण की तरह।
और फंक्शन करें 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
);
प्रतीकात्मक के साथ एक त्वरित खोज खाली आई, इसलिए ऑपरेटर <!>
किसी भी मॉड्यूल में उपयोग में नहीं लगता है।
यदि आप इस ऑपरेटर का बहुत उपयोग करने जा रहे हैं, तो आप क्वेरी प्लानर की सहायता के लिए इसे कुछ और दे सकते हैं ( जैसे कि टिप्पणी में खोए हुए सुझाव )। शुरुआत के लिए, आप क्वेरी ऑप्टिमाइज़र की सहायता के लिए COMMUTATOR
और NEGATOR
खंड जोड़ सकते हैं । CREATE OPERATOR
इसे ऊपर से बदलें :
CREATE OPERATOR <!> (
PROCEDURE = is_distinct_from(anyelement,anyelement),
LEFTARG = anyelement
, RIGHTARG = anyelement
, COMMUTATOR = <!>
, NEGATOR = =!=
);
और जोड़:
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 = <!>
);
लेकिन अतिरिक्त खंड हाथ पर उपयोग के मामले में मदद नहीं करेगा और सादे सूचकांक अभी भी उपयोग नहीं किया जाएगा। इसे प्राप्त करने के लिए यह बहुत अधिक परिष्कृत है। (मैंने कोशिश नहीं की है।) विवरण के लिए मैनुअल में अध्याय "ऑपरेटर अनुकूलन सूचना" पढ़ें ।
परीक्षण का मामला
प्रश्न में परीक्षण का मामला तभी सफल हो सकता है जब सरणी में सभी मान समान हों। प्रश्न में सरणी के लिए ( '{null,A}'::text[]
) परिणाम हमेशा TRUE होता है। क्या यह इरादा है? मैंने "IS DISTINCT FROM ALL" के लिए एक और टेस्ट जोड़ा:
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
मानक ऑपरेटरों के साथ वैकल्पिक
foo IS DISTINCT FROM ANY (test_arr) -- illegal syntax
कर सकते हैं लगभग करने के लिए अनुवाद किया जा
foo = ALL (test_arr) IS NOT TRUE
foo = ALL (test_arr)
पैदावार ...
TRUE
.. यदि सभी तत्व हैं foo
FALSE
.. यदि कोई NOT NULL
तत्व है <> foo
NULL
.. यदि कम से कम एक तत्व है IS NULL
और कोई तत्व नहीं है<> foo
तो, शेष कोने का मामला है जहां
- foo IS NULL
- और तत्वों test_arr
के अलावा कुछ भी नहीं NULL
है।
यदि दोनों में से किसी एक को खारिज किया जा सकता है, तो हम किए जाते हैं। इसलिए, सरल परीक्षण का उपयोग करें यदि
- स्तंभ परिभाषित है NOT NULL
।
- या आप जानते हैं कि सरणी कभी भी पूर्ण नहीं है।
अतिरिक्त, अतिरिक्त रूप से परीक्षण करें:
AND ('A' = ALL(test_arr) IS NOT NULL OR
'B' = ALL(test_arr) IS NOT NULL OR
foo IS NOT NULL)
कहाँ 'A'
और कोई भी विशिष्ट मूल्य 'B'
हो सकते हैं। SO पर इस संबंधित प्रश्न के तहत स्पष्टीकरण और विकल्प: PostgreSQL में सभी NULLs सरणी है
फिर, यदि आप किसी ऐसे मूल्य के बारे में जानते हैं test_arr
जो खाली स्ट्रिंग के उदाहरण के लिए मौजूद नहीं हो सकता है ''
, तो आप अभी भी इसे सरल बना सकते हैं:
AND ('' = ALL(test_arr) IS NOT NULL OR
foo IS NOT NULL)
सभी संयोजनों की जांच के लिए यहां एक पूर्ण परीक्षण मैट्रिक्स दिया गया है:
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
यह एंड्री के EXCEPT
समाधान की तुलना में थोड़ा अधिक है , लेकिन यह काफी तेजी से है।